From dfd123714669c415bdaa5698257e8a56568fd6f6 Mon Sep 17 00:00:00 2001 From: Sigmund Cherem Date: Mon, 8 Dec 2014 09:15:22 -0800 Subject: [PATCH] Simplify how we discover libraries in the checker. R=vsm@google.com Review URL: https://chromereviews.googleplex.com/125187013 --- pkg/dev_compiler/lib/src/testing.dart | 19 +---- pkg/dev_compiler/lib/src/utils.dart | 16 ++++ pkg/dev_compiler/lib/typechecker.dart | 118 +++----------------------- 3 files changed, 30 insertions(+), 123 deletions(-) diff --git a/pkg/dev_compiler/lib/src/testing.dart b/pkg/dev_compiler/lib/src/testing.dart index 3ded2c4a200..523cf2e53f6 100644 --- a/pkg/dev_compiler/lib/src/testing.dart +++ b/pkg/dev_compiler/lib/src/testing.dart @@ -59,9 +59,7 @@ testChecker(Map testFiles, {bool mockSdk: true}) { var visitor = new _ErrorMarkerVisitor(expectedErrors); var initialLibrary = resolver.context.getLibraryElement(testUriResolver.files[mainFile]); - List reachableLibraries = []; - _findReachable(initialLibrary, reachableLibraries); - for (var lib in reachableLibraries) { + for (var lib in reachableLibraries(initialLibrary)) { for (var unit in lib.units) { unit.unit.accept(visitor); } @@ -137,21 +135,6 @@ SourceSpan _spanFor(AstNode node) { return source.spanFor(node); } - -/// Recursively visits all libraries loaded by the test files. -_findReachable(lib, results, [Set seen]) { - if (seen == null) seen = new Set(); - if (seen.contains(lib)) return results; - seen.add(lib); - results.add(lib); - for (var other in lib.importedLibraries) { - _findReachable(other, results, seen); - } - for (var other in lib.exportedLibraries) { - _findReachable(other, results, seen); - } -} - /// Visitor that extracts expected errors from comments. class _ErrorMarkerVisitor extends UnifyingAstVisitor { Map> expectedErrors; diff --git a/pkg/dev_compiler/lib/src/utils.dart b/pkg/dev_compiler/lib/src/utils.dart index 3879af24417..96f82884d85 100644 --- a/pkg/dev_compiler/lib/src/utils.dart +++ b/pkg/dev_compiler/lib/src/utils.dart @@ -2,8 +2,24 @@ library ddc.src.utils; import 'package:analyzer/src/generated/source.dart'; +import 'package:analyzer/src/generated/element.dart'; import 'package:source_span/source_span.dart'; +/// Returns all libraries transitively imported or exported from [start]. +List reachableLibraries(LibraryElement start) { + var results = []; + var seen = new Set(); + void find(LibraryElement lib) { + if (seen.contains(lib)) return; + seen.add(lib); + results.add(lib); + lib.importedLibraries.forEach(find); + lib.exportedLibraries.forEach(find); + } + find(start); + return results; +} + /// Cache of [SourceFile]s per [Source], so we avoid recomputing line-breaks and /// source-span information on a file multiple times. // TODO(sigmund): consider truncating the size of this cache. diff --git a/pkg/dev_compiler/lib/typechecker.dart b/pkg/dev_compiler/lib/typechecker.dart index 6d504673e51..f0113e9f1e6 100644 --- a/pkg/dev_compiler/lib/typechecker.dart +++ b/pkg/dev_compiler/lib/typechecker.dart @@ -10,6 +10,7 @@ import 'package:logging/logging.dart' as logger; import 'src/resolver.dart'; import 'src/static_info.dart'; import 'src/type_rules.dart'; +import 'src/utils.dart'; final _log = new logger.Logger('ddc.checker'); @@ -58,13 +59,6 @@ class Library { Library(this.uri, this.source, this.lib); } -class _WorkListItem { - final Uri uri; - final Source source; - final bool isLibrary; - _WorkListItem(this.uri, this.source, this.isLibrary); -} - class ProgramChecker extends RecursiveAstVisitor { final TypeResolver _resolver; final TypeRules _rules; @@ -72,33 +66,6 @@ class ProgramChecker extends RecursiveAstVisitor { final bool _checkSdk; final Map _unitMap = {}; final Map libraries = {}; - Library _currentLibrary; - final List<_WorkListItem> _workList = []; - final List<_WorkListItem> _partWorkList = []; - - Uri toUri(String string) { - // FIXME: Use analyzer's resolver logic. - if (string.startsWith('package:')) { - String package = string.substring(8); - string = 'packages/' + package; - return _root.resolve(string); - } else { - return _currentLibrary.uri.resolve(string); - } - } - - void add(Uri uri, Source source, bool isLibrary) { - if (isLibrary) { - _workList.add(new _WorkListItem(uri, source, isLibrary)); - if (_currentLibrary != null) { - // This is an import / export. - // Record the key. Fill in the library later. - _currentLibrary.imports[uri] = null; - } - } else { - _partWorkList.add(new _WorkListItem(uri, source, isLibrary)); - } - } void finalizeImports() { libraries.forEach((Uri uri, Library lib) { @@ -108,82 +75,23 @@ class ProgramChecker extends RecursiveAstVisitor { }); } - CompilationUnit load(Uri uri, Source source, bool isLibrary) { - if (!_checkSdk && uri.scheme == 'dart') { - return null; - } - if (_unitMap.containsKey(uri)) { - assert(isLibrary); - return _unitMap[uri]; - } - final unit = getCompilationUnit(source, isLibrary); - _rules.setCompilationUnit(unit); - _unitMap[uri] = unit; - final last = _currentLibrary; - if (isLibrary) { - assert(!libraries.containsKey(uri)); - var lib = new Library(uri, source, unit); - libraries[uri] = lib; - _currentLibrary = lib; - } else { - var lib = _currentLibrary; - assert(!lib.parts.containsKey(uri)); - lib.parts[uri] = unit; - } - unit.visitChildren(this); - if (isLibrary) { - while (_partWorkList.isNotEmpty) { - _WorkListItem item = _partWorkList.removeAt(0); - assert(!item.isLibrary); - load(item.uri, item.source, item.isLibrary); - } - assert(_currentLibrary.uri == uri); - _currentLibrary = last; - } - return unit; - } - - void loadFromDirective(UriBasedDirective directive, bool isLibrary) { - String content = directive.uri.stringValue; - Uri uri = toUri(content); - Source source = directive.source; - add(uri, source, isLibrary); - } - - CompilationUnit getCompilationUnit(Source source, bool isLibrary) { - var container = isLibrary ? source : _currentLibrary.source; - var res = _resolver.context.resolveCompilationUnit2(source, container); - failure = _resolver.logErrors(source) || failure; - return res; - } - - ProgramChecker(this._resolver, this._rules, this._root, this._checkSdk) { - add(_root, _resolver.findSource(_root), true); - } + ProgramChecker(this._resolver, this._rules, this._root, this._checkSdk); void check() { - while (_workList.isNotEmpty) { - _WorkListItem item = _workList.removeAt(0); - assert(item.isLibrary); - load(item.uri, item.source, item.isLibrary); + var startLibrary = _resolver.context.computeLibraryElement( + _resolver.findSource(_root)); + for (var lib in reachableLibraries(startLibrary)) { + if (!_checkSdk && lib.isInSdk) continue; + var source = lib.source; + libraries[source.uri] = + new Library(source.uri, source, lib.definingCompilationUnit.node); + for (var unit in lib.units) { + _rules.setCompilationUnit(unit.node); + unit.node.visitChildren(this); + } } } - visitExportDirective(ExportDirective node) { - loadFromDirective(node, true); - node.visitChildren(this); - } - - visitImportDirective(ImportDirective node) { - loadFromDirective(node, true); - node.visitChildren(this); - } - - visitPartDirective(PartDirective node) { - loadFromDirective(node, false); - node.visitChildren(this); - } - visitAssignmentExpression(AssignmentExpression node) { DartType staticType = _rules.getStaticType(node.leftHandSide); checkAssignment(node.rightHandSide, staticType);