diff --git a/modules_dart/transform/lib/src/transform/deferred_rewriter/rewriter.dart b/modules_dart/transform/lib/src/transform/deferred_rewriter/rewriter.dart index b8f2c0d56e..990181a4a7 100644 --- a/modules_dart/transform/lib/src/transform/deferred_rewriter/rewriter.dart +++ b/modules_dart/transform/lib/src/transform/deferred_rewriter/rewriter.dart @@ -14,39 +14,54 @@ import 'package:quiver/iterables.dart' as it; class Rewriter { final AssetId _entryPoint; final AssetReader _reader; + final _FindDeferredLibraries _visitor; - Rewriter(this._entryPoint, this._reader); + Rewriter(AssetId entryPoint, AssetReader reader) + : _entryPoint = entryPoint, + _reader = reader, + _visitor = new _FindDeferredLibraries(reader, entryPoint); - /// Rewrites the provided code by finding all the deferred library imports - /// and loadLibrary invocations. Then it removes any libraries that don't - /// require angular codegen. For the remaining libraries it rewrites the - /// import to the corresponding ng_dep file, and chains a future which - /// first initializes the library. + /// Rewrites `loadLibrary` calls to initialize libraries once loaded. + /// + /// 1. Finds all the deferred library imports and loadLibrary invocations in + /// `_entryPoint` + /// 2. Removes any libraries that don't require angular codegen. + /// 3. For the remaining libraries, rewrites the import to the corresponding + /// `ng_deps.dart` file. + /// 4. Chains a future to the `loadLibrary` call which initializes the + /// library. /// /// To the extent possible, this method does not change line numbers or /// offsets in the provided code to facilitate debugging via source maps. Future rewrite() async { var code = await _reader.readAsString(_entryPoint); - var node = parseCompilationUnit(code); + + // If we can determine there are no deferred libraries, avoid parsing the + // entire file and bail early. + var onlyDirectives = parseDirectives(code, name: _entryPoint.path); + if (onlyDirectives == null) return null; + onlyDirectives.directives.accept(_visitor); + if (_visitor.deferredImports.isEmpty) return null; + + var node = parseCompilationUnit(code, name: _entryPoint.path); if (node == null) return null; return logElapsedAsync(() async { - var visitor = new _FindDeferredLibraries(_reader, _entryPoint); - node.accept(visitor); + node.declarations.accept(_visitor); // Look to see if we found any deferred libraries - if (!visitor.hasDeferredLibrariesToRewrite()) return null; + if (!_visitor.hasDeferredLibrariesToRewrite()) return null; // Remove any libraries that don't need angular codegen. - await visitor.cull(); + await _visitor.cull(); // Check again if there are any deferred libraries. - if (!visitor.hasDeferredLibrariesToRewrite()) return null; + if (!_visitor.hasDeferredLibrariesToRewrite()) return null; var compare = (AstNode a, AstNode b) => a.offset - b.offset; - visitor.deferredImports.sort(compare); - visitor.loadLibraryInvocations.sort(compare); + _visitor.deferredImports.sort(compare); + _visitor.loadLibraryInvocations.sort(compare); var buf = new StringBuffer(); var idx = - visitor.deferredImports.fold(0, (int lastIdx, ImportDirective node) { + _visitor.deferredImports.fold(0, (int lastIdx, ImportDirective node) { buf.write(code.substring(lastIdx, node.offset)); var import = code.substring(node.offset, node.end); @@ -54,7 +69,7 @@ class Rewriter { return node.end; }); - idx = visitor.loadLibraryInvocations.fold(idx, + idx = _visitor.loadLibraryInvocations.fold(idx, (int lastIdx, MethodInvocation node) { buf.write(code.substring(lastIdx, node.offset)); var value = node.realTarget as SimpleIdentifier; diff --git a/modules_dart/transform/test/transform/deferred_rewriter/all_tests.dart b/modules_dart/transform/test/transform/deferred_rewriter/all_tests.dart index e6b91f9930..c34435af77 100644 --- a/modules_dart/transform/test/transform/deferred_rewriter/all_tests.dart +++ b/modules_dart/transform/test/transform/deferred_rewriter/all_tests.dart @@ -44,13 +44,15 @@ void _testRewriteDeferredLibraries(String name, String inputPath) { path.dirname(inputPath), 'expected', path.basename(inputPath)); var expectedId = _assetIdForPath(expectedPath); - var output = await rewriteDeferredLibraries(reader, inputId); - var input = await reader.readAsString(expectedId); - if (input == null) { - // Null input signals no output. Ensure that is true. - expect(output).toBeNull(); + var actualOutput = await rewriteDeferredLibraries(reader, inputId); + var expectedOutput = await reader.readAsString(expectedId); + if (expectedOutput == null) { + // Null expectedOutput signals no output. Ensure that is true. + expect(actualOutput).toBeNull(); } else { - expect(formatter.format(output)).toEqual(formatter.format(input)); + expect(actualOutput).toBeNotNull(); + expect(formatter.format(actualOutput)) + .toEqual(formatter.format(expectedOutput)); } }, log: new RecordingLogger()); });