From f728691ac8aefd5fc8f5e8992b0e2e2bea189aa9 Mon Sep 17 00:00:00 2001 From: John Messerly Date: Thu, 14 May 2015 16:42:33 -0700 Subject: [PATCH] Fixes #179 -- compile error if editing files during server mode this avoids reloading file contents many times during a compile. `.contents.data` == bad! also fixes #73, using Analyzer's LineInfo instead of FileSpan to avoid finding line breaks over and over I did some manual testing on sunflower as well as diffing SDK messages before and after The one baseline change (23 -> 22) seems more accurate than it was before. R=vsm@google.com Review URL: https://codereview.chromium.org/1141013002 --- pkg/dev_compiler/bin/edit_files.dart | 12 +- pkg/dev_compiler/lib/devc.dart | 131 ++++++----- .../lib/src/checker/resolver.dart | 52 +--- .../lib/src/codegen/code_generator.dart | 27 ++- .../lib/src/codegen/dart_codegen.dart | 15 +- .../lib/src/codegen/js_codegen.dart | 18 +- .../lib/src/codegen/reify_coercions.dart | 26 +- .../lib/src/dependency_graph.dart | 87 ++++--- pkg/dev_compiler/lib/src/info.dart | 15 ++ pkg/dev_compiler/lib/src/report.dart | 84 +++---- pkg/dev_compiler/lib/src/testing.dart | 15 +- pkg/dev_compiler/lib/src/utils.dart | 41 ++-- .../test/dart_codegen/expect/core/string.dart | 2 +- .../test/dependency_graph_test.dart | 222 +++++++++--------- pkg/dev_compiler/test/report_test.dart | 6 +- 15 files changed, 400 insertions(+), 353 deletions(-) diff --git a/pkg/dev_compiler/bin/edit_files.dart b/pkg/dev_compiler/bin/edit_files.dart index cf9d82aa78cb..b526feece955 100644 --- a/pkg/dev_compiler/bin/edit_files.dart +++ b/pkg/dev_compiler/bin/edit_files.dart @@ -13,6 +13,7 @@ library dev_compiler.bin.edit_files; import 'dart:io'; import 'dart:convert'; +import 'package:analyzer/src/generated/source.dart' show Source; import 'package:args/args.dart'; import 'package:cli_util/cli_util.dart' show getSdkDir; import 'package:source_maps/refactor.dart'; @@ -63,6 +64,8 @@ class EditFileSummaryVisitor extends RecursiveSummaryVisitor { RegExp includePattern; RegExp excludePattern; + final Map _sources = {}; + EditFileSummaryVisitor(this.typeResolver, this.level, this.checkoutFilesExecutable, this.checkoutFilesArg, this.includePattern, this.excludePattern); @@ -72,6 +75,13 @@ class EditFileSummaryVisitor extends RecursiveSummaryVisitor { return new TextEditTransaction(fileContents, new SourceFile(fileContents)); }); + /// Find the corresponding [Source] for [uri]. + Source findSource(Uri uri) { + var source = _sources[uri]; + if (source != null) return source; + return _sources[uri] = typeResolver.context.sourceFactory.forUri('$uri'); + } + @override void visitMessage(MessageSummary message) { var uri = message.span.sourceUrl; @@ -88,7 +98,7 @@ class EditFileSummaryVisitor extends RecursiveSummaryVisitor { break; } } - var fullName = typeResolver.findSource(uri).fullName; + var fullName = findSource(uri).fullName; if (includePattern != null && !includePattern.hasMatch(fullName)) return; if (excludePattern != null && excludePattern.hasMatch(fullName)) return; var edits = getEdits(fullName); diff --git a/pkg/dev_compiler/lib/devc.dart b/pkg/dev_compiler/lib/devc.dart index 826ab5008131..a187e71bd390 100644 --- a/pkg/dev_compiler/lib/devc.dart +++ b/pkg/dev_compiler/lib/devc.dart @@ -9,7 +9,10 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; -import 'package:analyzer/src/generated/engine.dart' show ChangeSet; +import 'package:analyzer/src/generated/error.dart' as analyzer; +import 'package:analyzer/src/generated/engine.dart' + show AnalysisContext, ChangeSet; +import 'package:analyzer/src/generated/source.dart' show Source; import 'package:logging/logging.dart' show Level, Logger, LogRecord; import 'package:path/path.dart' as path; import 'package:shelf/shelf.dart' as shelf; @@ -25,7 +28,8 @@ import 'src/codegen/dart_codegen.dart'; import 'src/codegen/html_codegen.dart'; import 'src/codegen/js_codegen.dart'; import 'src/dependency_graph.dart'; -import 'src/info.dart' show LibraryInfo, CheckerResults, LibraryUnit; +import 'src/info.dart' + show AnalyzerError, CheckerResults, LibraryInfo, LibraryUnit; import 'src/options.dart'; import 'src/report.dart'; import 'src/utils.dart'; @@ -39,19 +43,25 @@ StreamSubscription setupLogger(Level level, printFn) { }); } +abstract class AbstractCompiler { + CompilerOptions get options; + AnalysisContext get context; + TypeRules get rules; + Uri get entryPointUri; +} + /// Encapsulates the logic to do a one-off compilation or a partial compilation /// when the compiler is run as a development server. -class Compiler { - final CompilerOptions _options; - final TypeResolver _resolver; +class Compiler implements AbstractCompiler { + final CompilerOptions options; + final AnalysisContext context; final CheckerReporter _reporter; - final TypeRules _rules; + final TypeRules rules; final CodeChecker _checker; - final SourceGraph _graph; final SourceNode _entryNode; List _libraries = []; - final List _generators; - final bool _hashing; + final _generators = []; + bool _hashing; bool _failure = false; factory Compiler(CompilerOptions options, @@ -61,15 +71,15 @@ class Compiler { ? new TypeResolver.fromMock(mockSdkSources, options) : new TypeResolver.fromDir(options.dartSdkPath, options); } + var context = resolver.context; if (reporter == null) { reporter = options.dumpInfo - ? new SummaryReporter(options.logLevel) - : new LogReporter(options.useColors); + ? new SummaryReporter(context, options.logLevel) + : new LogReporter(context, useColors: options.useColors); } - var graph = new SourceGraph(resolver.context, reporter, options); - var rules = - new RestrictedRules(resolver.context.typeProvider, options: options); + var graph = new SourceGraph(context, reporter, options); + var rules = new RestrictedRules(context.typeProvider, options: options); var checker = new CodeChecker(rules, reporter, options); var inputFile = options.entryPointFile; @@ -80,26 +90,26 @@ class Compiler { ? ResolverOptions.implicitHtmlFile : inputFile)); var entryNode = graph.nodeFromUri(inputUri); - var outputDir = options.outputDir; - var generators = []; + + return new Compiler._( + options, context, reporter, rules, checker, entryNode); + } + + Compiler._(this.options, this.context, this._reporter, this.rules, + this._checker, this._entryNode) { if (options.dumpSrcDir != null) { - generators.add(new EmptyDartGenerator( - options.dumpSrcDir, entryNode.uri, rules, options)); + _generators.add(new EmptyDartGenerator(this)); } - if (outputDir != null) { - generators.add(options.outputDart - ? new DartGenerator(outputDir, entryNode.uri, rules, options) - : new JSGenerator(outputDir, entryNode.uri, rules, options)); + if (options.outputDir != null) { + _generators.add( + options.outputDart ? new DartGenerator(this) : new JSGenerator(this)); } - return new Compiler._(options, resolver, reporter, rules, checker, graph, - entryNode, generators, - // TODO(sigmund): refactor to support hashing of the dart output? - options.enableHashing && generators.length == 1 && !options.outputDart); + // TODO(sigmund): refactor to support hashing of the dart output? + _hashing = + options.enableHashing && _generators.length == 1 && !options.outputDart; } - Compiler._(this._options, this._resolver, this._reporter, this._rules, - this._checker, this._graph, this._entryNode, this._generators, - this._hashing); + Uri get entryPointUri => _entryNode.uri; bool _buildSource(SourceNode node) { if (node is HtmlSourceNode) { @@ -118,30 +128,30 @@ class Compiler { } void _buildHtmlFile(HtmlSourceNode node) { - if (_options.outputDir == null) return; + if (options.outputDir == null) return; var uri = node.source.uri; _reporter.enterHtml(uri); - var output = generateEntryHtml(node, _options); + var output = generateEntryHtml(node, options); if (output == null) { _failure = true; return; } _reporter.leaveHtml(); var filename = path.basename(node.uri.path); - String outputFile = path.join(_options.outputDir, filename); + String outputFile = path.join(options.outputDir, filename); new File(outputFile).writeAsStringSync(output); - if (_options.outputDart) return; + if (options.outputDart) return; } void _buildResourceFile(ResourceSourceNode node) { // ResourceSourceNodes files that just need to be copied over to the output // location. These can be external dependencies or pieces of the // dev_compiler runtime. - if (_options.outputDir == null || _options.outputDart) return; + if (options.outputDir == null || options.outputDart) return; var filepath = resourceOutputPath(node.uri, _entryNode.uri); assert(filepath != null); - filepath = path.join(_options.outputDir, filepath); + filepath = path.join(options.outputDir, filepath); var dir = path.dirname(filepath); new Directory(dir).createSync(recursive: true); new File.fromUri(node.source.uri).copySync(filepath); @@ -156,10 +166,10 @@ class Compiler { void _buildDartLibrary(DartSourceNode node) { var source = node.source; // TODO(sigmund): find out from analyzer team if there is a better way - _resolver.context.applyChanges(new ChangeSet()..changedSource(source)); - var entryUnit = _resolver.context.resolveCompilationUnit2(source, source); + context.applyChanges(new ChangeSet()..changedSource(source)); + var entryUnit = context.resolveCompilationUnit2(source, source); var lib = entryUnit.element.enclosingElement; - if (!_options.checkSdk && lib.isInSdk) return; + if (!options.checkSdk && lib.isInSdk) return; var current = node.info; if (current != null) { assert(current.library == lib); @@ -168,25 +178,25 @@ class Compiler { } _reporter.enterLibrary(source.uri); _libraries.add(current); - _rules.currentLibraryInfo = current; + rules.currentLibraryInfo = current; var resolvedParts = node.parts - .map((p) => _resolver.context.resolveCompilationUnit2(p.source, source)) + .map((p) => context.resolveCompilationUnit2(p.source, source)) .toList(growable: false); var libraryUnit = new LibraryUnit(entryUnit, resolvedParts); bool failureInLib = false; for (var unit in libraryUnit.libraryThenParts) { var unitSource = unit.element.source; - _reporter.enterSource(unitSource); + _reporter.enterCompilationUnit(unit); // TODO(sigmund): integrate analyzer errors with static-info (issue #6). - failureInLib = _resolver.logErrors(unitSource, _reporter) || failureInLib; + failureInLib = logErrors(unitSource) || failureInLib; _checker.visitCompilationUnit(unit); if (_checker.failure) failureInLib = true; - _reporter.leaveSource(); + _reporter.leaveCompilationUnit(); } if (failureInLib) { _failure = true; - if (!_options.forceCompile) return; + if (!options.forceCompile) return; } for (var cg in _generators) { @@ -196,6 +206,21 @@ class Compiler { _reporter.leaveLibrary(); } + /// Log any errors encountered when resolving [source] and return whether any + /// errors were found. + bool logErrors(Source source) { + List errors = context.getErrors(source).errors; + bool failure = false; + if (errors.isNotEmpty) { + for (var error in errors) { + var message = new AnalyzerError.from(error); + if (message.level == Level.SEVERE) failure = true; + _reporter.log(message); + } + } + return failure; + } + CheckerResults run() { var clock = new Stopwatch()..start(); @@ -204,13 +229,13 @@ class Compiler { // like more than one script tag (see .severe messages in // dependency_graph.dart). Such failures should be reported back // here so we can mark failure=true in the CheckerResutls. - rebuild(_entryNode, _graph, _buildSource); + rebuild(_entryNode, _buildSource); _dumpInfoIfRequested(); clock.stop(); var time = (clock.elapsedMilliseconds / 1000).toStringAsFixed(2); _log.fine('Compiled ${_libraries.length} libraries in ${time} s\n'); return new CheckerResults( - _libraries, _rules, _failure || _options.forceCompile); + _libraries, rules, _failure || options.forceCompile); } void _runAgain() { @@ -219,7 +244,7 @@ class Compiler { int changed = 0; // TODO(sigmund): propagate failures here (see TODO in run). - rebuild(_entryNode, _graph, (n) { + rebuild(_entryNode, (n) { changed++; return _buildSource(n); }); @@ -230,12 +255,12 @@ class Compiler { } _dumpInfoIfRequested() { - if (!_options.dumpInfo || _reporter is! SummaryReporter) return; + if (!options.dumpInfo || _reporter is! SummaryReporter) return; var result = (_reporter as SummaryReporter).result; - if (!_options.serverMode) print(summaryToString(result)); - var filepath = _options.serverMode - ? path.join(_options.outputDir, 'messages.json') - : _options.dumpInfoFile; + if (!options.serverMode) print(summaryToString(result)); + var filepath = options.serverMode + ? path.join(options.outputDir, 'messages.json') + : options.dumpInfoFile; if (filepath == null) return; new File(filepath).writeAsStringSync(JSON.encode(result.toJsonMap())); } @@ -272,7 +297,7 @@ class CompilerServer { CompilerServer._( Compiler compiler, this.outDir, this.host, this.port, String entryPath) : this.compiler = compiler, - this._entryPath = compiler._options.useImplicitHtml + this._entryPath = compiler.options.useImplicitHtml ? ResolverOptions.implicitHtmlFile : entryPath; diff --git a/pkg/dev_compiler/lib/src/checker/resolver.dart b/pkg/dev_compiler/lib/src/checker/resolver.dart index 6af5659330ab..954bdfa3bc85 100644 --- a/pkg/dev_compiler/lib/src/checker/resolver.dart +++ b/pkg/dev_compiler/lib/src/checker/resolver.dart @@ -10,7 +10,6 @@ import 'package:analyzer/analyzer.dart'; import 'package:analyzer/src/generated/ast.dart'; import 'package:analyzer/src/generated/element.dart'; import 'package:analyzer/src/generated/engine.dart'; -import 'package:analyzer/src/generated/error.dart' as analyzer; import 'package:analyzer/src/generated/java_io.dart' show JavaFile; import 'package:analyzer/src/generated/resolver.dart'; import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk; @@ -25,7 +24,6 @@ import 'package:path/path.dart' as path; import 'package:dev_compiler/src/in_memory.dart'; import 'package:dev_compiler/src/options.dart'; -import 'package:dev_compiler/src/report.dart'; import 'package:dev_compiler/src/utils.dart'; import 'dart_sdk.dart'; import 'multi_package_resolver.dart'; @@ -40,12 +38,12 @@ String _implicitEntryHtml(String src) => ''' '''; +// TODO(jmesserly): this class can be removed, and converted to some top-level +// methods that create the AnalysisContext. /// Encapsulates a resolver from the analyzer package. class TypeResolver { final InternalAnalysisContext context; - final Map _sources = {}; - TypeResolver(DartUriResolver sdkResolver, ResolverOptions options, {List otherResolvers}) : context = _initContext(options) { @@ -77,49 +75,13 @@ class TypeResolver { : this( new DartUriResolver(new DirectoryBasedDartSdk(new JavaFile(sdkPath))), options, otherResolvers: otherResolvers); - - UriResolver _createImplicitEntryResolver(ResolverOptions options) { - var entry = path.absolute(ResolverOptions.implicitHtmlFile); - var src = path.absolute(options.entryPointFile); - var index = {'$entry': _implicitEntryHtml(src)}; - return new InMemoryUriResolver(index, representNonExistingFiles: false); - } - - /// Find the corresponding [Source] for [uri]. - Source findSource(Uri uri) { - var source = _sources[uri]; - if (source != null) return source; - return _sources[uri] = context.sourceFactory.forUri('$uri'); - } - - /// Log any errors encountered when resolving [source] and return whether any - /// errors were found. - bool logErrors(Source source, CheckerReporter reporter) { - List errors = context.getErrors(source).errors; - bool failure = false; - if (errors.isNotEmpty) { - for (var error in errors) { - var message = new AnalyzerError.from(error); - if (message.level == logger.Level.SEVERE) failure = true; - reporter.log(message); - } - } - return failure; - } } -class AnalyzerError extends Message { - factory AnalyzerError.from(analyzer.AnalysisError error) { - var severity = error.errorCode.type.severity; - var isError = severity == analyzer.ErrorSeverity.ERROR; - var level = isError ? logger.Level.SEVERE : logger.Level.WARNING; - int begin = error.offset; - int end = begin + error.length; - return new AnalyzerError(error.message, level, begin, end); - } - - const AnalyzerError(String message, logger.Level level, int begin, int end) - : super('[from analyzer]: $message', level, begin, end); +UriResolver _createImplicitEntryResolver(ResolverOptions options) { + var entry = path.absolute(ResolverOptions.implicitHtmlFile); + var src = path.absolute(options.entryPointFile); + var index = {'$entry': _implicitEntryHtml(src)}; + return new InMemoryUriResolver(index, representNonExistingFiles: false); } /// Creates an analysis context that contains our restricted typing rules. diff --git a/pkg/dev_compiler/lib/src/codegen/code_generator.dart b/pkg/dev_compiler/lib/src/codegen/code_generator.dart index ee16c93d75a1..1d4526a9b52c 100644 --- a/pkg/dev_compiler/lib/src/codegen/code_generator.dart +++ b/pkg/dev_compiler/lib/src/codegen/code_generator.dart @@ -9,16 +9,35 @@ import 'dart:io'; import 'package:analyzer/src/generated/ast.dart' show CompilationUnit; import 'package:analyzer/src/generated/element.dart' show CompilationUnitElement, LibraryElement; +import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; import 'package:path/path.dart' as path; +import 'package:dev_compiler/devc.dart' show AbstractCompiler; import 'package:dev_compiler/src/info.dart'; import 'package:dev_compiler/src/utils.dart' show canonicalLibraryName; import 'package:dev_compiler/src/checker/rules.dart'; +import 'package:dev_compiler/src/options.dart'; abstract class CodeGenerator { + final AbstractCompiler compiler; final String outDir; final Uri root; final TypeRules rules; + final AnalysisContext context; + final CompilerOptions options; + + CodeGenerator(AbstractCompiler compiler) + : compiler = compiler, + outDir = path.absolute(compiler.options.outputDir), + root = compiler.entryPointUri, + rules = compiler.rules, + context = compiler.context, + options = compiler.options; + + /// Return a hash, if any, that can be used for caching purposes. When two + /// invocations to this function return the same hash, the underlying + /// code-generator generated the same code. + String generateLibrary(LibraryUnit unit, LibraryInfo info); static List _searchPaths = () { // TODO(vsm): Can we remove redundancy with multi_package_resolver logic? @@ -124,12 +143,4 @@ abstract class CodeGenerator { return new Uri( scheme: 'package', path: path.joinAll(parts.sublist(index + 1))); } - - CodeGenerator(String outDir, this.root, this.rules) - : outDir = path.absolute(outDir); - - /// Return a hash, if any, that can be used for caching purposes. When two - /// invocations to this function return the same hash, the underlying - /// code-generator generated the same code. - String generateLibrary(LibraryUnit unit, LibraryInfo info); } diff --git a/pkg/dev_compiler/lib/src/codegen/dart_codegen.dart b/pkg/dev_compiler/lib/src/codegen/dart_codegen.dart index b9f55933cf1e..53fea1d74585 100644 --- a/pkg/dev_compiler/lib/src/codegen/dart_codegen.dart +++ b/pkg/dev_compiler/lib/src/codegen/dart_codegen.dart @@ -15,8 +15,8 @@ import 'package:dart_style/dart_style.dart'; import 'package:logging/logging.dart' as logger; import 'package:path/path.dart' as path; +import 'package:dev_compiler/devc.dart' show AbstractCompiler; import 'package:dev_compiler/src/info.dart'; -import 'package:dev_compiler/src/checker/rules.dart'; import 'package:dev_compiler/src/options.dart'; import 'package:dev_compiler/src/utils.dart' as utils; import 'ast_builder.dart'; @@ -385,13 +385,9 @@ class UnitGenerator extends UnitGeneratorCommon with ConversionVisitor { } class DartGenerator extends codegenerator.CodeGenerator { - final CompilerOptions options; - TypeRules _rules; final DevCompilerRuntime _runtime = new DevCompilerRuntime(); - DartGenerator(String outDir, Uri root, TypeRules rules, this.options) - : _rules = rules, - super(outDir, root, rules); + DartGenerator(AbstractCompiler compiler) : super(compiler); Set computeExtraImports(Map ids) { var imports = new Set(); @@ -410,7 +406,7 @@ class DartGenerator extends codegenerator.CodeGenerator { } String generateLibrary(LibraryUnit library, LibraryInfo info) { - var r = new CoercionReifier(library, rules, options, _runtime); + var r = new CoercionReifier(library, compiler, _runtime); var ids = r.reify(); var extraImports = computeExtraImports(ids); @@ -448,10 +444,7 @@ class EmptyUnitGenerator extends UnitGeneratorCommon { // This class emits the code unchanged, for comparison purposes. class EmptyDartGenerator extends codegenerator.CodeGenerator { - final CompilerOptions options; - - EmptyDartGenerator(String outDir, Uri root, TypeRules rules, this.options) - : super(outDir, root, rules); + EmptyDartGenerator(AbstractCompiler compiler) : super(compiler); String generateLibrary(LibraryUnit library, LibraryInfo info) { for (var unit in library.partsThenLibrary) { diff --git a/pkg/dev_compiler/lib/src/codegen/js_codegen.dart b/pkg/dev_compiler/lib/src/codegen/js_codegen.dart index a898d076b759..8af06b9dfb02 100644 --- a/pkg/dev_compiler/lib/src/codegen/js_codegen.dart +++ b/pkg/dev_compiler/lib/src/codegen/js_codegen.dart @@ -23,6 +23,7 @@ import 'package:dev_compiler/src/codegen/reify_coercions.dart' import 'package:dev_compiler/src/js/js_ast.dart' as JS; import 'package:dev_compiler/src/js/js_ast.dart' show js; +import 'package:dev_compiler/devc.dart' show AbstractCompiler; import 'package:dev_compiler/src/checker/rules.dart'; import 'package:dev_compiler/src/info.dart'; import 'package:dev_compiler/src/options.dart'; @@ -49,6 +50,7 @@ const DCALL = 'dcall'; const DSEND = 'dsend'; class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { + final AbstractCompiler compiler; final CompilerOptions options; final TypeRules rules; final LibraryInfo libraryInfo; @@ -87,8 +89,11 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { ModuleItemLoadOrder _loader; - JSCodegenVisitor(this.options, this.rules, this.libraryInfo, - this._extensionMethods, this._fieldsNeedingStorage) { + JSCodegenVisitor(AbstractCompiler compiler, this.libraryInfo, + this._extensionMethods, this._fieldsNeedingStorage) + : compiler = compiler, + options = compiler.options, + rules = compiler.rules { _loader = new ModuleItemLoadOrder(_emitModuleItem); } @@ -99,7 +104,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { String jsDefaultValue = null; // Modify the AST to make coercions explicit. - new CoercionReifier(library, rules, options).reify(); + new CoercionReifier(library, compiler).reify(); var unit = library.library; if (unit.directives.isNotEmpty) { @@ -2386,15 +2391,12 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { } class JSGenerator extends CodeGenerator { - final CompilerOptions options; - /// For fast lookup of extension methods, we first check the name, then do a /// (possibly expensive) subtype test to see if it matches one of the types /// that declares that method. final _extensionMethods = new HashMap>(); - JSGenerator(String outDir, Uri root, TypeRules rules, this.options) - : super(outDir, root, rules) { + JSGenerator(AbstractCompiler context) : super(context) { // TODO(jacobr): determine the the set of types with extension methods from // the annotations rather than hard coding the list once the analyzer @@ -2417,7 +2419,7 @@ class JSGenerator extends CodeGenerator { String generateLibrary(LibraryUnit unit, LibraryInfo info) { var fields = findFieldsNeedingStorage(unit); var codegen = - new JSCodegenVisitor(options, rules, info, _extensionMethods, fields); + new JSCodegenVisitor(compiler, info, _extensionMethods, fields); var module = codegen.emitLibrary(unit); var dir = path.join(outDir, jsOutputPath(info, root)); return writeJsLibrary(module, dir, emitSourceMaps: options.emitSourceMaps); diff --git a/pkg/dev_compiler/lib/src/codegen/reify_coercions.dart b/pkg/dev_compiler/lib/src/codegen/reify_coercions.dart index e9b54b06e60b..cff462edc4d8 100644 --- a/pkg/dev_compiler/lib/src/codegen/reify_coercions.dart +++ b/pkg/dev_compiler/lib/src/codegen/reify_coercions.dart @@ -7,9 +7,10 @@ library dev_compiler.src.codegen.reify_coercions; import 'package:analyzer/analyzer.dart' as analyzer; import 'package:analyzer/src/generated/ast.dart'; import 'package:analyzer/src/generated/element.dart'; +import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; import 'package:logging/logging.dart' as logger; -import 'package:source_span/source_span.dart' show SourceFile; +import 'package:dev_compiler/devc.dart' show AbstractCompiler; import 'package:dev_compiler/src/checker/rules.dart'; import 'package:dev_compiler/src/info.dart'; import 'package:dev_compiler/src/options.dart' show CompilerOptions; @@ -108,30 +109,34 @@ class _Inference extends DownwardsInference { // abstract coercion nodes with their dart implementations. class CoercionReifier extends analyzer.GeneralizingAstVisitor with ConversionVisitor { + final AnalysisContext _context; final CoercionManager _cm; final TypeManager _tm; final VariableManager _vm; final LibraryUnit _library; - SourceFile _file; bool _skipCoercions = false; final TypeRules _rules; final _Inference _inferrer; final InstrumentedRuntime _runtime; final CompilerOptions _options; + CompilationUnit _unit; + CoercionReifier._(this._cm, this._tm, this._vm, this._library, this._rules, - this._inferrer, this._runtime, this._options); + this._inferrer, this._runtime, this._context, this._options); - factory CoercionReifier( - LibraryUnit library, TypeRules rules, CompilerOptions options, + factory CoercionReifier(LibraryUnit library, AbstractCompiler compiler, [InstrumentedRuntime runtime]) { var vm = new VariableManager(); var tm = new TypeManager(library.library.element.enclosingElement, vm, runtime); + var rules = compiler.rules; var cm = new CoercionManager(vm, tm, rules, runtime); var inferrer = new _Inference(rules, tm); + var context = compiler.context; + var options = compiler.options; return new CoercionReifier._( - cm, tm, vm, library, rules, inferrer, runtime, options); + cm, tm, vm, library, rules, inferrer, runtime, context, options); } // This should be the entry point for this class. Entering via the @@ -144,21 +149,20 @@ class CoercionReifier extends analyzer.GeneralizingAstVisitor } void generateUnit(CompilationUnit unit) { - _file = new SourceFile(unit.element.source.contents.data, - url: unit.element.source.uri); + _unit = unit; visitCompilationUnit(unit); - _file = null; + _unit = null; } ///////////////// Private ////////////////////////////////// String _locationInfo(Expression e) { - if (_file != null) { + if (_unit != null) { final begin = e is AnnotatedNode ? (e as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset : e.offset; if (begin != 0 && e.end > begin) { - var span = _file.span(begin, e.end); + var span = utils.createSpan(_context, _unit, begin, e.end); var s = span.message("Cast"); return s.substring(0, s.indexOf("Cast")); } diff --git a/pkg/dev_compiler/lib/src/dependency_graph.dart b/pkg/dev_compiler/lib/src/dependency_graph.dart index dcded66942ca..dcf876d41257 100644 --- a/pkg/dev_compiler/lib/src/dependency_graph.dart +++ b/pkg/dev_compiler/lib/src/dependency_graph.dart @@ -25,12 +25,10 @@ import 'package:html/dom.dart' show Document, Node; import 'package:html/parser.dart' as html; import 'package:logging/logging.dart' show Logger, Level; import 'package:path/path.dart' as path; -import 'package:source_span/source_span.dart' show SourceSpan; import 'info.dart'; import 'options.dart'; import 'report.dart'; -import 'utils.dart'; /// Holds references to all source nodes in the import graph. This is mainly /// used as a level of indirection to ensure that each source has a canonical @@ -70,11 +68,11 @@ class SourceGraph { var source = _context.sourceFactory.forUri(uriString); var extension = path.extension(uriString); if (extension == '.html') { - return new HtmlSourceNode(uri, source, this); + return new HtmlSourceNode(this, uri, source); } else if (extension == '.dart' || uriString.startsWith('dart:')) { - return new DartSourceNode(uri, source); + return new DartSourceNode(this, uri, source); } else { - return new ResourceSourceNode(uri, source); + return new ResourceSourceNode(this, uri, source); } }); } @@ -82,6 +80,8 @@ class SourceGraph { /// A node in the import graph representing a source file. abstract class SourceNode { + final SourceGraph graph; + /// Resolved URI for this node. final Uri uri; @@ -90,6 +90,8 @@ abstract class SourceNode { Source _source; Source get source => _source; + String get contents => graph._context.getContents(source).data; + /// Last stamp read from `source.modificationStamp`. int _lastStamp = 0; @@ -113,22 +115,27 @@ abstract class SourceNode { /// parts are excluded from this list. Iterable get depsWithoutParts => const []; - SourceNode(this.uri, this._source); + SourceNode(this.graph, this.uri, this._source); /// Check for whether the file has changed and, if so, mark [needsRebuild] and /// [structureChanged] as necessary. - void update(SourceGraph graph) { + void update() { if (_source == null) { _source = graph._context.sourceFactory.forUri(Uri.encodeFull('$uri')); if (_source == null) return; } int newStamp = _source.modificationStamp; if (newStamp > _lastStamp) { + // If the timestamp changed, read the file from disk and cache it. + // We don't want the source text to change during compilation. + saveUpdatedContents(); _lastStamp = newStamp; needsRebuild = true; } } + void saveUpdatedContents() {} + String toString() { var simpleUri = uri.scheme == 'file' ? path.relative(uri.path) : "$uri"; return '[$runtimeType: $simpleUri]'; @@ -156,15 +163,16 @@ class HtmlSourceNode extends SourceNode { /// Parsed document, updated whenever [update] is invoked. Document document; - HtmlSourceNode(Uri uri, Source source, SourceGraph graph) + HtmlSourceNode(SourceGraph graph, Uri uri, Source source) : runtimeDeps = graph.runtimeDeps, - super(uri, source); + super(graph, uri, source); - void update(SourceGraph graph) { - super.update(graph); + @override + void update() { + super.update(); if (needsRebuild) { graph._reporter.clearHtml(uri); - document = html.parse(source.contents.data, generateSpans: true); + document = html.parse(contents, generateSpans: true); var newScripts = new Set(); var tags = document.querySelectorAll('script[type="application/dart"]'); for (var script in tags) { @@ -204,7 +212,9 @@ class HtmlSourceNode extends SourceNode { void _reportError(SourceGraph graph, String message, Node node) { graph._reporter.enterHtml(source.uri); - graph._reporter.log(new DependencyGraphError(message, node.sourceSpan)); + var span = node.sourceSpan; + graph._reporter.log( + new Message(message, Level.SEVERE, span.start.offset, span.end.offset)); graph._reporter.leaveHtml(); } } @@ -223,7 +233,7 @@ class DartSourceNode extends SourceNode { /// How many times this file is included as a part. int includedAsPart = 0; - DartSourceNode(uri, source) : super(uri, source); + DartSourceNode(graph, uri, source) : super(graph, uri, source); @override Iterable get allDeps => @@ -235,14 +245,25 @@ class DartSourceNode extends SourceNode { LibraryInfo info; - void update(SourceGraph graph) { - super.update(graph); + // TODO(jmesserly): it would be nice to not keep all sources in memory at + // once, but how else can we ensure a consistent view across a given + // compile? One different from dev_compiler vs analyzer is that our + // messages later in the compiler need the original source text to print + // spans. We also read source text ourselves to parse directives. + // But we could discard it after that point. + void saveUpdatedContents() { + graph._context.setContents(source, source.contents.data); + } - if (needsRebuild && source.contents.data != null) { + @override + void update() { + super.update(); + + if (needsRebuild && contents != null) { graph._reporter.clearLibrary(uri); // If the defining compilation-unit changed, the structure might have // changed. - var unit = parseDirectives(source.contents.data, name: source.fullName); + var unit = parseDirectives(contents, name: source.fullName); var newImports = new Set(); var newExports = new Set(); var newParts = new Set(); @@ -262,7 +283,7 @@ class DartSourceNode extends SourceNode { if (targetUri != target.uri) print(">> ${target.uri} $targetUri"); } var node = graph.nodes.putIfAbsent( - targetUri, () => new DartSourceNode(targetUri, target)); + targetUri, () => new DartSourceNode(graph, targetUri, target)); //var node = graph.nodeFromUri(targetUri); if (node.source == null || !node.source.exists()) { _reportError(graph, 'File $targetUri not found', unit, d); @@ -314,24 +335,26 @@ class DartSourceNode extends SourceNode { // contain imports, exports, or parts, we'll ignore them in our crawling. // However we do a full update to make it easier to adjust when users // switch a file from a part to a library. - p.update(graph); + p.update(); if (p.needsRebuild) needsRebuild = true; } } void _reportError( SourceGraph graph, String message, CompilationUnit unit, AstNode node) { - graph._reporter.enterLibrary(source.uri); - graph._reporter.log( - new DependencyGraphError(message, spanForNode(unit, source, node))); - graph._reporter.leaveLibrary(); + graph._reporter + ..enterLibrary(source.uri) + ..enterCompilationUnit(unit, source) + ..log(new Message(message, Level.SEVERE, node.offset, node.end)) + ..leaveCompilationUnit() + ..leaveLibrary(); } } /// Represents a runtime resource from our compiler that is needed to run an /// application. class ResourceSourceNode extends SourceNode { - ResourceSourceNode(uri, source) : super(uri, source); + ResourceSourceNode(graph, uri, source) : super(graph, uri, source); } /// Updates the structure and `needsRebuild` marks in nodes of [graph] reachable @@ -345,8 +368,8 @@ class ResourceSourceNode extends SourceNode { /// contained local changes. Rebuild decisions that derive from transitive /// changes (e.g. when the API of a dependency changed) are handled later in /// [rebuild]. -void refreshStructureAndMarks(SourceNode start, SourceGraph graph) { - visitInPreOrder(start, (n) => n.update(graph), includeParts: false); +void refreshStructureAndMarks(SourceNode start) { + visitInPreOrder(start, (n) => n.update(), includeParts: false); } /// Clears all the `needsRebuild` and `structureChanged` marks in nodes @@ -382,8 +405,8 @@ void clearMarks(SourceNode start) { /// whether other nodes need to be rebuilt. The function [build] is expected /// to return `true` on a node `n` if it detemines other nodes that import /// `n` may need to be rebuilt as well. -rebuild(SourceNode start, SourceGraph graph, bool build(SourceNode node)) { - refreshStructureAndMarks(start, graph); +rebuild(SourceNode start, bool build(SourceNode node)) { + refreshStructureAndMarks(start); // Hold which source nodes may have changed their public API, this includes // libraries that were modified or libraries that export other modified APIs. // TODO(sigmund): consider removing this special support for exports? Many @@ -454,12 +477,6 @@ visitInPostOrder(SourceNode start, void action(SourceNode node), bool _same(Set a, Set b) => a.length == b.length && a.containsAll(b); -/// An error message discovered while parsing the dependencies between files. -class DependencyGraphError extends MessageWithSpan { - const DependencyGraphError(String message, SourceSpan span) - : super(message, Level.SEVERE, span); -} - /// Runtime files added to all applications when running the compiler in the /// command line. final defaultRuntimeFiles = () { diff --git a/pkg/dev_compiler/lib/src/info.dart b/pkg/dev_compiler/lib/src/info.dart index 2ddd34f835bb..3db9e965f3f0 100644 --- a/pkg/dev_compiler/lib/src/info.dart +++ b/pkg/dev_compiler/lib/src/info.dart @@ -10,6 +10,7 @@ import 'dart:mirrors'; import 'package:analyzer/src/generated/ast.dart'; import 'package:analyzer/src/generated/element.dart'; +import 'package:analyzer/src/generated/error.dart' as analyzer; import 'package:analyzer/src/generated/scanner.dart' show Token, TokenType, SyntheticStringToken; import 'package:logging/logging.dart' show Level; @@ -730,3 +731,17 @@ final List infoTypes = () { return new List.from(allTypes.map((mirror) => mirror.reflectedType)) ..sort((t1, t2) => '$t1'.compareTo('$t2')); }(); + +class AnalyzerError extends Message { + factory AnalyzerError.from(analyzer.AnalysisError error) { + var severity = error.errorCode.type.severity; + var isError = severity == analyzer.ErrorSeverity.ERROR; + var level = isError ? Level.SEVERE : Level.WARNING; + int begin = error.offset; + int end = begin + error.length; + return new AnalyzerError(error.message, level, begin, end); + } + + const AnalyzerError(String message, Level level, int begin, int end) + : super('[from analyzer]: $message', level, begin, end); +} diff --git a/pkg/dev_compiler/lib/src/report.dart b/pkg/dev_compiler/lib/src/report.dart index de23525784ae..27452c125f2e 100644 --- a/pkg/dev_compiler/lib/src/report.dart +++ b/pkg/dev_compiler/lib/src/report.dart @@ -7,6 +7,8 @@ library dev_compiler.src.report; import 'dart:math' show max; +import 'package:analyzer/src/generated/ast.dart' show AstNode, CompilationUnit; +import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; import 'package:analyzer/src/generated/source.dart' show Source; import 'package:logging/logging.dart'; import 'package:path/path.dart' as path; @@ -22,7 +24,7 @@ import 'summary.dart'; /// Currently the location information includes only the offsets within a file /// where the error occurs. This is used in the context of a [CheckerReporter], /// where the current file is being tracked. -abstract class Message { +class Message { // Message description. final String message; @@ -38,22 +40,14 @@ abstract class Message { const Message(this.message, this.level, this.begin, this.end); } -/// Like [Message], but with a precomputed source span. -abstract class MessageWithSpan implements Message { - final String message; - - final Level level; - - final SourceSpan span; - - int get begin => span.start.offset; - int get end => span.end.offset; - - const MessageWithSpan(this.message, this.level, this.span); -} - // Interface used to report error messages from the checker. abstract class CheckerReporter { + final AnalysisContext _context; + CompilationUnit _unit; + Source _unitSource; + + CheckerReporter(this._context); + /// Called when starting to process a library. void enterLibrary(Uri uri); void leaveLibrary(); @@ -64,25 +58,35 @@ abstract class CheckerReporter { /// Called when starting to process a source. All subsequent log entries must /// belong to this source until the next call to enterSource. - void enterSource(Source source); - void leaveSource(); + void enterCompilationUnit(CompilationUnit unit, [Source source]) { + _unit = unit; + _unitSource = source; + } + void leaveCompilationUnit() { + _unit = null; + _unitSource = null; + } + void log(Message message); // Called in server-mode. void clearLibrary(Uri uri); void clearHtml(Uri uri); void clearAll(); + + SourceSpanWithContext _createSpan(int start, int end) => + createSpan(_context, _unit, start, end, _unitSource); } final _checkerLogger = new Logger('dev_compiler.checker'); /// Simple reporter that logs checker messages as they are seen. -class LogReporter implements CheckerReporter { +class LogReporter extends CheckerReporter { final bool useColors; - SourceFile _file; Source _current; - LogReporter([this.useColors = false]); + LogReporter(AnalysisContext context, {this.useColors: false}) + : super(context); void enterLibrary(Uri uri) {} void leaveLibrary() {} @@ -90,24 +94,12 @@ class LogReporter implements CheckerReporter { void enterHtml(Uri uri) {} void leaveHtml() {} - void enterSource(Source source) { - _file = new SourceFile(source.contents.data, url: source.uri); - _current = source; - } - - void leaveSource() { - _file = null; - _current = null; - } - void log(Message message) { if (message is StaticInfo) { - assert((message.node as dynamic).root.element.source == _current); + assert(message.node.root == _unit); } // TODO(sigmund): convert to use span information from AST (issue #73) - final span = message is MessageWithSpan - ? message.span - : _file.span(message.begin, message.end); + final span = _createSpan(message.begin, message.end); final level = message.level; final color = useColors ? colorOf(level.name) : null; final text = '[${message.runtimeType}] ${message.message}'; @@ -120,13 +112,13 @@ class LogReporter implements CheckerReporter { } /// A reporter that gathers all the information in a [GlobalSummary]. -class SummaryReporter implements CheckerReporter { +class SummaryReporter extends CheckerReporter { GlobalSummary result = new GlobalSummary(); IndividualSummary _current; - SourceFile _file; final Level _level; - SummaryReporter([this._level = Level.ALL]); + SummaryReporter(AnalysisContext context, [this._level = Level.ALL]) + : super(context); void enterLibrary(Uri uri) { var container; @@ -154,25 +146,19 @@ class SummaryReporter implements CheckerReporter { _current = null; } - void enterSource(Source source) { - _file = new SourceFile(source.contents.data, url: source.uri); + @override + void enterCompilationUnit(CompilationUnit unit, [Source source]) { + super.enterCompilationUnit(unit, source); if (_current is LibrarySummary) { - (_current as LibrarySummary).lines += _file.lines; + int lines = _unit.lineInfo.getLocation(_unit.endToken.end).lineNumber; + (_current as LibrarySummary).lines += lines; } } - void leaveSource() { - _file = null; - } - void log(Message message) { // Only summarize messages per configured logging level if (message.level < _level) return; - assert(message is MessageWithSpan || _file != null); - // TODO(sigmund): convert to use span information from AST (issue #73) - final span = message is MessageWithSpan - ? message.span - : _file.span(message.begin, message.end); + final span = _createSpan(message.begin, message.end); _current.messages.add(new MessageSummary('${message.runtimeType}', message.level.name.toLowerCase(), span, message.message)); } diff --git a/pkg/dev_compiler/lib/src/testing.dart b/pkg/dev_compiler/lib/src/testing.dart index 4c83c567d22f..9ef50d0da35e 100644 --- a/pkg/dev_compiler/lib/src/testing.dart +++ b/pkg/dev_compiler/lib/src/testing.dart @@ -6,7 +6,8 @@ library dev_compiler.src.testing; import 'package:analyzer/src/generated/ast.dart'; import 'package:analyzer/src/generated/element.dart'; -import 'package:analyzer/src/generated/engine.dart' show TimestampedData; +import 'package:analyzer/src/generated/engine.dart' + show AnalysisContext, TimestampedData; import 'package:analyzer/src/generated/source.dart'; import 'package:logging/logging.dart'; import 'package:path/path.dart' as path; @@ -51,7 +52,8 @@ import 'dependency_graph.dart' show runtimeFilesForServerMode; /// }); /// CheckerResults testChecker(Map testFiles, - {bool allowConstCasts: true, String sdkDir, CheckerReporter reporter, + {bool allowConstCasts: true, String sdkDir, + CheckerReporter createReporter(AnalysisContext context), covariantGenerics: true, relaxedCasts: true, inferDownwards: RulesOptions.inferDownwardsDefault, inferFromOverrides: ResolverOptions.inferFromOverridesDefault, @@ -81,11 +83,14 @@ CheckerResults testChecker(Map testFiles, otherResolvers: [testUriResolver]) : new TypeResolver.fromDir(sdkDir, options, otherResolvers: [testUriResolver]); + var context = resolver.context; // Run the checker on /main.dart. var mainFile = new Uri.file('/main.dart'); - var checkExpectations = reporter == null; - if (reporter == null) reporter = new TestReporter(); + var checkExpectations = createReporter == null; + var reporter = (createReporter == null) + ? new TestReporter(context) + : createReporter(context); var results = new Compiler(options, resolver: resolver, reporter: reporter).run(); @@ -147,6 +152,8 @@ class TestReporter extends SummaryReporter { Map>> infoMap = {}; Uri _current; + TestReporter(AnalysisContext context) : super(context); + void enterLibrary(Uri uri) { super.enterLibrary(uri); infoMap[uri] = {}; diff --git a/pkg/dev_compiler/lib/src/utils.dart b/pkg/dev_compiler/lib/src/utils.dart index d9ccdac94ac9..60c6d491386c 100644 --- a/pkg/dev_compiler/lib/src/utils.dart +++ b/pkg/dev_compiler/lib/src/utils.dart @@ -113,7 +113,8 @@ Iterable reachableSources(Source start, AnalysisContext context) { /// Returns sources that are imported or exported in [source] (parts are /// excluded). Iterable _importsAndExportsOf(Source source, AnalysisContext context) { - var unit = parseDirectives(source.contents.data, name: source.fullName); + var unit = + parseDirectives(context.getContents(source).data, name: source.fullName); return unit.directives .where((d) => d is ImportDirective || d is ExportDirective) .map((d) { @@ -291,19 +292,6 @@ SourceLocation locationForOffset(CompilationUnit unit, Uri uri, int offset) { column: lineInfo.columnNumber - 1); } -// TODO(sigmund): change to show the span from the beginning of the line (#73) -SourceSpan spanForNode(CompilationUnit unit, Source source, AstNode node) { - var currentToken = node is AnnotatedNode - ? node.firstTokenAfterCommentAndMetadata - : node.beginToken; - var begin = currentToken.offset; - var end = node.end; - var text = source.contents.data.substring(begin, end); - var uri = source.uri; - return new SourceSpan(locationForOffset(unit, uri, begin), - locationForOffset(unit, uri, end), '$text'); -} - /// Computes a hash for the given contents. String computeHash(String contents) { if (contents == null || contents == '') return null; @@ -439,3 +427,28 @@ InterfaceType findSupertype(InterfaceType type, bool match(InterfaceType t)) { if (match(s)) return type; return findSupertype(s, match); } + +SourceSpanWithContext createSpan( + AnalysisContext context, CompilationUnit unit, int start, int end, + [Source source]) { + if (source == null) source = unit.element.source; + var content = context.getContents(source).data; + var startLoc = locationForOffset(unit, source.uri, start); + var endLoc = locationForOffset(unit, source.uri, end); + + var lineStart = startLoc.offset - startLoc.column; + // Find the end of the line. This is not exposed directly on LineInfo, but + // we can find it pretty easily. + // TODO(jmesserly): for now we do the simple linear scan. Ideally we can get + // some help from the LineInfo API. + var lineInfo = unit.lineInfo; + int lineEnd = endLoc.offset; + int unitEnd = unit.endToken.end; + int lineNum = lineInfo.getLocation(lineEnd).lineNumber; + while (lineEnd < unitEnd && + lineInfo.getLocation(++lineEnd).lineNumber == lineNum); + + var text = content.substring(start, end); + var lineText = content.substring(lineStart, lineEnd); + return new SourceSpanWithContext(startLoc, endLoc, text, lineText); +} diff --git a/pkg/dev_compiler/test/dart_codegen/expect/core/string.dart b/pkg/dev_compiler/test/dart_codegen/expect/core/string.dart index 662016822ce0..ad1be6150cc0 100644 --- a/pkg/dev_compiler/test/dart_codegen/expect/core/string.dart +++ b/pkg/dev_compiler/test/dart_codegen/expect/core/string.dart @@ -85,7 +85,7 @@ RangeError.checkValueInInterval(rawIndex, 0, string.length, "rawIndex"); _position = _nextPosition = rawIndex; _currentCodePoint = null; } - int get current => DEVC$RT.cast(_currentCodePoint, num, int, "ImplicitCast", """line 702, column 23 of dart:core/string.dart: """, _currentCodePoint is int, true); + int get current => DEVC$RT.cast(_currentCodePoint, num, int, "ImplicitCast", """line 702, column 22 of dart:core/string.dart: """, _currentCodePoint is int, true); int get currentSize => _nextPosition - _position; String get currentAsString { if (_position == _nextPosition) return null; diff --git a/pkg/dev_compiler/test/dependency_graph_test.dart b/pkg/dev_compiler/test/dependency_graph_test.dart index a9b7e6d99324..f81d71ea61aa 100644 --- a/pkg/dev_compiler/test/dependency_graph_test.dart +++ b/pkg/dev_compiler/test/dependency_graph_test.dart @@ -64,7 +64,7 @@ void main() { testUriResolver = new InMemoryUriResolver(testFiles); context = new TypeResolver.fromMock(mockSdkSources, options, otherResolvers: [testUriResolver]).context; - graph = new SourceGraph(context, new LogReporter(), options); + graph = new SourceGraph(context, new LogReporter(context), options); }); group('HTML deps', () { @@ -73,8 +73,8 @@ void main() { var i2 = nodeOf('/index2.html'); expect(i1.scripts.length, 0); expect(i2.scripts.length, 0); - i1.update(graph); - i2.update(graph); + i1.update(); + i2.update(); expect(i1.scripts.length, 0); expect(i2.scripts.length, 1); expect(i2.scripts.first, nodeOf('/a1.dart')); @@ -83,7 +83,7 @@ void main() { test('add a dep', () { // After initial load, dependencies are 0: var node = nodeOf('/index1.html'); - node.update(graph); + node.update(); expect(node.scripts.length, 0); // Adding the dependency is discovered on the next round of updates: @@ -91,7 +91,7 @@ void main() { node.source.contents.data = ''; expect(node.scripts.length, 0); - node.update(graph); + node.update(); expect(node.scripts.length, 1); expect(node.scripts.first, nodeOf('/a2.dart')); }); @@ -99,7 +99,7 @@ void main() { test('add more deps', () { // After initial load, dependencies are 1: var node = nodeOf('/index2.html'); - node.update(graph); + node.update(); expect(node.scripts.length, 1); expect(node.scripts.first, nodeOf('/a1.dart')); @@ -107,7 +107,7 @@ void main() { node.source.contents.data += ''; expect(node.scripts.length, 1); - node.update(graph); + node.update(); expect(node.scripts.length, 2); expect(node.scripts.first, nodeOf('/a1.dart')); expect(node.scripts.last, nodeOf('/a2.dart')); @@ -116,7 +116,7 @@ void main() { test('remove all deps', () { // After initial load, dependencies are 1: var node = nodeOf('/index2.html'); - node.update(graph); + node.update(); expect(node.scripts.length, 1); expect(node.scripts.first, nodeOf('/a1.dart')); @@ -124,7 +124,7 @@ void main() { node.source.contents.modificationTime++; node.source.contents.data = ''; expect(node.scripts.length, 1); - node.update(graph); + node.update(); expect(node.scripts.length, 0); }); }); @@ -140,8 +140,8 @@ void main() { expect(a2.exports.length, 0); expect(a2.parts.length, 0); - a1.update(graph); - a2.update(graph); + a1.update(); + a2.update(); expect(a1.imports.length, 0); expect(a1.exports.length, 0); @@ -157,7 +157,7 @@ void main() { test('add deps', () { var node = nodeOf('/a1.dart'); - node.update(graph); + node.update(); expect(node.imports.length, 0); expect(node.exports.length, 0); expect(node.parts.length, 0); @@ -165,7 +165,7 @@ void main() { node.source.contents.modificationTime++; node.source.contents.data = 'import "a3.dart"; export "a5.dart"; part "a8.dart";'; - node.update(graph); + node.update(); expect(node.imports.length, 1); expect(node.exports.length, 1); @@ -177,7 +177,7 @@ void main() { test('remove deps', () { var node = nodeOf('/a2.dart'); - node.update(graph); + node.update(); expect(node.imports.length, 2); expect(node.exports.length, 1); expect(node.parts.length, 1); @@ -189,7 +189,7 @@ void main() { node.source.contents.modificationTime++; node.source.contents.data = 'import "a3.dart"; export "a7.dart"; part "a8.dart";'; - node.update(graph); + node.update(); expect(node.imports.length, 1); expect(node.exports.length, 1); @@ -201,7 +201,7 @@ void main() { test('change part to library', () { var node = nodeOf('/a2.dart'); - node.update(graph); + node.update(); expect(node.imports.length, 2); expect(node.exports.length, 1); expect(node.parts.length, 1); @@ -221,7 +221,7 @@ void main() { var a6 = nodeOf('/a6.dart'); a6.source.contents.modificationTime++; a6.source.contents.data = ''; - node.update(graph); + node.update(); expect(node.imports.length, 3); expect(node.exports.length, 1); @@ -239,7 +239,7 @@ void main() { test('change library to part', () { var node = nodeOf('/a2.dart'); var a4 = nodeOf('/a4.dart'); - node.update(graph); + node.update(); expect(node.imports.length, 2); expect(node.exports.length, 1); expect(node.parts.length, 1); @@ -248,7 +248,7 @@ void main() { expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); expect(node.parts.contains(nodeOf('/a6.dart')), isTrue); - a4.update(graph); + a4.update(); expect(a4.imports.length, 0); expect(a4.exports.length, 1); expect(a4.parts.length, 0); @@ -261,7 +261,7 @@ void main() { export 'a5.dart'; part 'a6.dart'; '''; - node.update(graph); + node.update(); expect(node.imports.length, 1); expect(node.exports.length, 1); @@ -287,7 +287,7 @@ void main() { export 'a5.dart'; part 'a6.dart'; '''; - node.update(graph); + node.update(); expect(node.imports.contains(a4), isTrue); expect(a4.imports.length, 0); expect(a4.exports.length, 1); @@ -299,35 +299,35 @@ void main() { group('needs rebuild', () { test('in HTML', () { var node = nodeOf('/index1.html'); - node.update(graph); + node.update(); expect(node.needsRebuild, isTrue); node.needsRebuild = false; - node.update(graph); + node.update(); expect(node.needsRebuild, isFalse); // For now, an empty modification is enough to trigger a rebuild node.source.contents.modificationTime++; expect(node.needsRebuild, isFalse); - node.update(graph); + node.update(); expect(node.needsRebuild, isTrue); }); test('main library in Dart', () { var node = nodeOf('/a2.dart'); var partNode = nodeOf('/a6.dart'); - node.update(graph); + node.update(); expect(node.needsRebuild, isTrue); node.needsRebuild = false; partNode.needsRebuild = false; - node.update(graph); + node.update(); expect(node.needsRebuild, isFalse); // For now, an empty modification is enough to trigger a rebuild node.source.contents.modificationTime++; expect(node.needsRebuild, isFalse); - node.update(graph); + node.update(); expect(node.needsRebuild, isTrue); }); @@ -336,19 +336,19 @@ void main() { var importNode = nodeOf('/a3.dart'); var exportNode = nodeOf('/a5.dart'); var partNode = nodeOf('/a6.dart'); - node.update(graph); + node.update(); expect(node.needsRebuild, isTrue); node.needsRebuild = false; partNode.needsRebuild = false; - node.update(graph); + node.update(); expect(node.needsRebuild, isFalse); // Modification in imported/exported node makes no difference for local // rebuild label (globally that's tested elsewhere) importNode.source.contents.modificationTime++; exportNode.source.contents.modificationTime++; - node.update(graph); + node.update(); expect(node.needsRebuild, isFalse); expect(partNode.needsRebuild, isFalse); @@ -356,7 +356,7 @@ void main() { partNode.source.contents.modificationTime++; expect(node.needsRebuild, isFalse); expect(partNode.needsRebuild, isFalse); - node.update(graph); + node.update(); expect(node.needsRebuild, isTrue); expect(partNode.needsRebuild, isTrue); }); @@ -365,35 +365,35 @@ void main() { group('structure change', () { test('no mod in HTML', () { var node = nodeOf('/index2.html'); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); node.structureChanged = false; - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); // An empty modification will not trigger a structural change node.source.contents.modificationTime++; expect(node.structureChanged, isFalse); - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); }); test('added scripts in HTML', () { var node = nodeOf('/index2.html'); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); expect(node.scripts.length, 1); node.structureChanged = false; - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); // This change will not include new script tags: node.source.contents.modificationTime++; node.source.contents.data += '
'; expect(node.structureChanged, isFalse); - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); expect(node.scripts.length, 1); @@ -401,7 +401,7 @@ void main() { node.source.contents.data += ''; expect(node.structureChanged, isFalse); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); expect(node.scripts.length, 2); }); @@ -411,11 +411,11 @@ void main() { var importNode = nodeOf('/a3.dart'); var exportNode = nodeOf('/a5.dart'); var partNode = nodeOf('/a6.dart'); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); node.structureChanged = false; - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); // These modifications make no difference at all. @@ -425,37 +425,37 @@ void main() { node.source.contents.modificationTime++; expect(node.structureChanged, isFalse); - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); }); test('same directives, different order', () { var node = nodeOf('/a2.dart'); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); node.structureChanged = false; - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); // modified order of imports, but structure stays the same: node.source.contents.modificationTime++; node.source.contents.data = 'import "a4.dart"; import "a3.dart"; ' 'export "a5.dart"; part "a6.dart";'; - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); }); test('changed parts', () { var node = nodeOf('/a2.dart'); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); node.structureChanged = false; - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); // added one. @@ -463,13 +463,13 @@ void main() { node.source.contents.data = 'import "a4.dart"; import "a3.dart"; ' 'export "a5.dart"; part "a6.dart"; part "a7.dart";'; expect(node.structureChanged, isFalse); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); // no change node.structureChanged = false; node.source.contents.modificationTime++; - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); // removed one @@ -477,17 +477,17 @@ void main() { node.source.contents.data = 'import "a4.dart"; import "a3.dart"; ' 'export "a5.dart"; part "a7.dart";'; expect(node.structureChanged, isFalse); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); }); test('changed import', () { var node = nodeOf('/a2.dart'); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); node.structureChanged = false; - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); // added one. @@ -496,13 +496,13 @@ void main() { 'import "a4.dart"; import "a3.dart"; import "a7.dart";' 'export "a5.dart"; part "a6.dart";'; expect(node.structureChanged, isFalse); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); // no change node.structureChanged = false; node.source.contents.modificationTime++; - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); // removed one @@ -510,17 +510,17 @@ void main() { node.source.contents.data = 'import "a4.dart"; import "a7.dart"; ' 'export "a5.dart"; part "a6.dart";'; expect(node.structureChanged, isFalse); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); }); test('changed exports', () { var node = nodeOf('/a2.dart'); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); node.structureChanged = false; - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); // added one. @@ -528,13 +528,13 @@ void main() { node.source.contents.data = 'import "a4.dart"; import "a3.dart";' 'export "a5.dart"; export "a9.dart"; part "a6.dart";'; expect(node.structureChanged, isFalse); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); // no change node.structureChanged = false; node.source.contents.modificationTime++; - node.update(graph); + node.update(); expect(node.structureChanged, isFalse); // removed one @@ -542,7 +542,7 @@ void main() { node.source.contents.data = 'import "a4.dart"; import "a3.dart"; ' 'export "a5.dart"; part "a6.dart";'; expect(node.structureChanged, isFalse); - node.update(graph); + node.update(); expect(node.structureChanged, isTrue); }); }); @@ -555,7 +555,7 @@ void main() { index3.html $_RUNTIME_GRAPH '''); - refreshStructureAndMarks(node, graph); + refreshStructureAndMarks(node); expectGraph(node, ''' index3.html [needs-rebuild] [structure-changed] |-- a2.dart [needs-rebuild] [structure-changed] @@ -570,7 +570,7 @@ void main() { test('cleared marks stay clear', () { var node = nodeOf('/index3.html'); - refreshStructureAndMarks(node, graph); + refreshStructureAndMarks(node); expectGraph(node, ''' index3.html [needs-rebuild] [structure-changed] |-- a2.dart [needs-rebuild] [structure-changed] @@ -593,7 +593,7 @@ void main() { $_RUNTIME_GRAPH '''); - refreshStructureAndMarks(node, graph); + refreshStructureAndMarks(node); expectGraph(node, ''' index3.html |-- a2.dart @@ -608,12 +608,12 @@ void main() { test('needsRebuild mark updated on local modifications', () { var node = nodeOf('/index3.html'); - refreshStructureAndMarks(node, graph); + refreshStructureAndMarks(node); clearMarks(node); var a3 = nodeOf('/a3.dart'); a3.source.contents.modificationTime++; - refreshStructureAndMarks(node, graph); + refreshStructureAndMarks(node); expectGraph(node, ''' index3.html |-- a2.dart @@ -628,13 +628,13 @@ void main() { test('structuredChanged mark updated on structure modifications', () { var node = nodeOf('/index3.html'); - refreshStructureAndMarks(node, graph); + refreshStructureAndMarks(node); clearMarks(node); var a5 = nodeOf('/a5.dart'); a5.source.contents.modificationTime++; a5.source.contents.data = 'import "a8.dart";'; - refreshStructureAndMarks(node, graph); + refreshStructureAndMarks(node); expectGraph(node, ''' index3.html |-- a2.dart @@ -656,7 +656,7 @@ void main() { runtimeDir: '/dev_compiler_runtime/', serverMode: true); context = new TypeResolver.fromMock(mockSdkSources, options2, otherResolvers: [testUriResolver]).context; - graph = new SourceGraph(context, new LogReporter(), options2); + graph = new SourceGraph(context, new LogReporter(context), options2); }); test('messages widget is automatically included', () { @@ -667,7 +667,7 @@ void main() { |-- messages_widget.js |-- messages.css '''); - refreshStructureAndMarks(node, graph); + refreshStructureAndMarks(node); expectGraph(node, ''' index3.html [needs-rebuild] [structure-changed] |-- a2.dart [needs-rebuild] [structure-changed] @@ -703,7 +703,7 @@ void main() { test('everything build on first run', () { var node = nodeOf('/index3.html'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); // Note: a6.dart is not included because it built as part of a2.dart expect(results, ['a3.dart', 'a10.dart', 'a4.dart', 'a5.dart', 'a2.dart'] ..addAll(runtimeFilesWithoutPath) @@ -724,95 +724,95 @@ void main() { test('nothing to do after build', () { var node = nodeOf('/index3.html'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, []); }); test('modified part triggers building library', () { var node = nodeOf('/index3.html'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); results = []; var a6 = nodeOf('/a6.dart'); a6.source.contents.modificationTime++; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, ['a2.dart']); results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, []); }); test('non-API change triggers build stays local', () { var node = nodeOf('/index3.html'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); results = []; var a3 = nodeOf('/a3.dart'); a3.source.contents.modificationTime++; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, ['a3.dart']); results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, []); }); test('no-API change in exported file stays local', () { var node = nodeOf('/index3.html'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); results = []; // similar to the test above, but a10 is exported from a4. var a3 = nodeOf('/a10.dart'); a3.source.contents.modificationTime++; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, ['a10.dart']); results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, []); }); test('API change in lib, triggers build on imports', () { var node = nodeOf('/index3.html'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); results = []; var a3 = nodeOf('/a3.dart'); a3.source.contents.modificationTime++; - rebuild(node, graph, buildWithTransitiveChange); + rebuild(node, buildWithTransitiveChange); expect(results, ['a3.dart', 'a2.dart']); results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, []); }); test('API change in export, triggers build on imports', () { var node = nodeOf('/index3.html'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); results = []; var a3 = nodeOf('/a10.dart'); a3.source.contents.modificationTime++; - rebuild(node, graph, buildWithTransitiveChange); + rebuild(node, buildWithTransitiveChange); // Node: a4.dart reexports a10.dart, but it doesn't import it, so we don't // need to rebuild it. expect(results, ['a10.dart', 'a2.dart']); results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, []); }); test('structural change rebuilds HTML, but skips unreachable code', () { var node = nodeOf('/index3.html'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); results = []; var a2 = nodeOf('/a2.dart'); @@ -821,30 +821,30 @@ void main() { var a3 = nodeOf('/a3.dart'); a3.source.contents.modificationTime++; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); // a3 will become unreachable, index3 reflects structural changes. expect(results, ['a2.dart', 'index3.html']); results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, []); }); test('newly discovered files get built too', () { var node = nodeOf('/index3.html'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); results = []; var a2 = nodeOf('/a2.dart'); a2.source.contents.modificationTime++; a2.source.contents.data = 'import "a9.dart";'; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, ['a8.dart', 'a9.dart', 'a2.dart', 'index3.html']); results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, []); }); @@ -859,7 +859,7 @@ void main() { var node = nodeOf('/index3.html'); var a2 = nodeOf('/a2.dart'); var a6 = nodeOf('/a6.dart'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expectGraph(node, ''' index3.html @@ -876,7 +876,7 @@ void main() { a6.source.contents.modificationTime++; a6.source.contents.data = 'library a6; import "a5.dart";'; results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); // Looks to us like a change in a part, we'll report errors that the // part is not really a part-file. Note that a6.dart is not included @@ -902,14 +902,14 @@ void main() { export 'a5.dart'; '''; results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); // Note that a6 is now included, because we haven't built it as a // library until now: expect(results, ['a6.dart', 'a2.dart', 'index3.html']); a6.source.contents.modificationTime++; results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, ['a6.dart']); expectGraph(node, ''' @@ -929,7 +929,7 @@ void main() { var node = nodeOf('/index3.html'); var a2 = nodeOf('/a2.dart'); var a6 = nodeOf('/a6.dart'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expectGraph(node, ''' index3.html @@ -951,7 +951,7 @@ void main() { export 'a5.dart'; '''; results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, ['a6.dart', 'a2.dart', 'index3.html']); expectGraph(node, ''' index3.html @@ -967,7 +967,7 @@ void main() { a6.source.contents.modificationTime++; a6.source.contents.data = 'library a6; import "a5.dart";'; results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, ['a6.dart', 'index3.html']); expectGraph(node, ''' index3.html @@ -986,7 +986,7 @@ void main() { var node = nodeOf('/index3.html'); var a2 = nodeOf('/a2.dart'); var a6 = nodeOf('/a6.dart'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expectGraph(node, ''' index3.html @@ -1009,7 +1009,7 @@ void main() { a6.source.contents.modificationTime++; a6.source.contents.data = 'library a6; import "a5.dart";'; results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); // a6 is not here, it's not reachable so we don't build it. expect(results, ['a2.dart', 'index3.html']); expectGraph(node, ''' @@ -1027,7 +1027,7 @@ void main() { var node = nodeOf('/index3.html'); var a2 = nodeOf('/a2.dart'); var a5 = nodeOf('/a5.dart'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expectGraph(node, ''' index3.html @@ -1049,7 +1049,7 @@ void main() { part 'a6.dart'; '''; results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, ['a2.dart', 'index3.html']); expectGraph(node, ''' index3.html @@ -1065,7 +1065,7 @@ void main() { a5.source.contents.modificationTime++; a5.source.contents.data = 'part of a2;'; results = []; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(results, ['a2.dart']); expectGraph(node, ''' index3.html @@ -1095,14 +1095,14 @@ void main() { test('non-existing files are tracked in dependencies', () { var node = nodeOf('/foo.dart'); node.source.contents.data = "import 'bar.dart';"; - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(node.allDeps.contains(nodeOf('/bar.dart')), isTrue); var source = nodeOf('/bar.dart').source; source.contents.data = "hi"; source.contents.modificationTime++; results = []; - rebuild(node, graph, buildWithTransitiveChange); + rebuild(node, buildWithTransitiveChange); expect(results, ['bar.dart', 'foo.dart']); }); }); @@ -1113,7 +1113,7 @@ void main() { representNonExistingFiles: false); context = new TypeResolver.fromMock(mockSdkSources, options, otherResolvers: [testUriResolver]).context; - graph = new SourceGraph(context, new LogReporter(), options); + graph = new SourceGraph(context, new LogReporter(context), options); }); test('recognize locally change between existing and not-existing', () { @@ -1122,7 +1122,7 @@ void main() { var source = new InMemorySource(new Uri.file('/foo.dart'), "hi"); testUriResolver.files[source.uri] = source; expect(n.source, isNull); - n.update(graph); + n.update(); expect(n.source, source); expect(n.source.exists(), isTrue); expect(n.needsRebuild, isTrue); @@ -1133,7 +1133,7 @@ void main() { new InMemorySource(new Uri.file('/foo.dart'), "import 'bar.dart';"); testUriResolver.files[s1.uri] = s1; var node = nodeOf('/foo.dart'); - rebuild(node, graph, buildNoTransitiveChange); + rebuild(node, buildNoTransitiveChange); expect(node.allDeps.length, 1); expect(node.allDeps.contains(nodeOf('/bar.dart')), isTrue); expect(nodeOf('/bar.dart').source, isNull); @@ -1141,7 +1141,7 @@ void main() { var s2 = new InMemorySource(new Uri.file('/bar.dart'), "hi"); testUriResolver.files[s2.uri] = s2; results = []; - rebuild(node, graph, buildWithTransitiveChange); + rebuild(node, buildWithTransitiveChange); expect(results, ['bar.dart', 'foo.dart']); }); }); diff --git a/pkg/dev_compiler/test/report_test.dart b/pkg/dev_compiler/test/report_test.dart index 6305aaeaffef..c19e3aba449f 100644 --- a/pkg/dev_compiler/test/report_test.dart +++ b/pkg/dev_compiler/test/report_test.dart @@ -33,8 +33,10 @@ void main() { '''.replaceAll('\n ', '\n'), }; testChecker(files); - var reporter = new SummaryReporter(); - testChecker(files, reporter: reporter); + + SummaryReporter reporter; + testChecker(files, + createReporter: (x) => reporter = new SummaryReporter(x)); _verifySummary(GlobalSummary summary) { var mainLib = summary.loose['file:///main.dart'];