feat(dart/transform): Bail early for files with no deferred libraries
In `DeferredRewriter` if we can determine that there are no `deferred` libraries imported, bail early to avoid parsing the entire file.
This commit is contained in:
parent
8f91ff84c7
commit
f80321fd26
|
@ -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<String> 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;
|
||||
|
|
|
@ -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());
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue