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 {
|
class Rewriter {
|
||||||
final AssetId _entryPoint;
|
final AssetId _entryPoint;
|
||||||
final AssetReader _reader;
|
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
|
/// Rewrites `loadLibrary` calls to initialize libraries once loaded.
|
||||||
/// and loadLibrary invocations. Then it removes any libraries that don't
|
///
|
||||||
/// require angular codegen. For the remaining libraries it rewrites the
|
/// 1. Finds all the deferred library imports and loadLibrary invocations in
|
||||||
/// import to the corresponding ng_dep file, and chains a future which
|
/// `_entryPoint`
|
||||||
/// first initializes the library.
|
/// 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
|
/// To the extent possible, this method does not change line numbers or
|
||||||
/// offsets in the provided code to facilitate debugging via source maps.
|
/// offsets in the provided code to facilitate debugging via source maps.
|
||||||
Future<String> rewrite() async {
|
Future<String> rewrite() async {
|
||||||
var code = await _reader.readAsString(_entryPoint);
|
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;
|
if (node == null) return null;
|
||||||
|
|
||||||
return logElapsedAsync(() async {
|
return logElapsedAsync(() async {
|
||||||
var visitor = new _FindDeferredLibraries(_reader, _entryPoint);
|
node.declarations.accept(_visitor);
|
||||||
node.accept(visitor);
|
|
||||||
// Look to see if we found any deferred libraries
|
// 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.
|
// Remove any libraries that don't need angular codegen.
|
||||||
await visitor.cull();
|
await _visitor.cull();
|
||||||
// Check again if there are any deferred libraries.
|
// 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;
|
var compare = (AstNode a, AstNode b) => a.offset - b.offset;
|
||||||
visitor.deferredImports.sort(compare);
|
_visitor.deferredImports.sort(compare);
|
||||||
visitor.loadLibraryInvocations.sort(compare);
|
_visitor.loadLibraryInvocations.sort(compare);
|
||||||
|
|
||||||
var buf = new StringBuffer();
|
var buf = new StringBuffer();
|
||||||
var idx =
|
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));
|
buf.write(code.substring(lastIdx, node.offset));
|
||||||
|
|
||||||
var import = code.substring(node.offset, node.end);
|
var import = code.substring(node.offset, node.end);
|
||||||
|
@ -54,7 +69,7 @@ class Rewriter {
|
||||||
return node.end;
|
return node.end;
|
||||||
});
|
});
|
||||||
|
|
||||||
idx = visitor.loadLibraryInvocations.fold(idx,
|
idx = _visitor.loadLibraryInvocations.fold(idx,
|
||||||
(int lastIdx, MethodInvocation node) {
|
(int lastIdx, MethodInvocation node) {
|
||||||
buf.write(code.substring(lastIdx, node.offset));
|
buf.write(code.substring(lastIdx, node.offset));
|
||||||
var value = node.realTarget as SimpleIdentifier;
|
var value = node.realTarget as SimpleIdentifier;
|
||||||
|
|
|
@ -44,13 +44,15 @@ void _testRewriteDeferredLibraries(String name, String inputPath) {
|
||||||
path.dirname(inputPath), 'expected', path.basename(inputPath));
|
path.dirname(inputPath), 'expected', path.basename(inputPath));
|
||||||
var expectedId = _assetIdForPath(expectedPath);
|
var expectedId = _assetIdForPath(expectedPath);
|
||||||
|
|
||||||
var output = await rewriteDeferredLibraries(reader, inputId);
|
var actualOutput = await rewriteDeferredLibraries(reader, inputId);
|
||||||
var input = await reader.readAsString(expectedId);
|
var expectedOutput = await reader.readAsString(expectedId);
|
||||||
if (input == null) {
|
if (expectedOutput == null) {
|
||||||
// Null input signals no output. Ensure that is true.
|
// Null expectedOutput signals no output. Ensure that is true.
|
||||||
expect(output).toBeNull();
|
expect(actualOutput).toBeNull();
|
||||||
} else {
|
} else {
|
||||||
expect(formatter.format(output)).toEqual(formatter.format(input));
|
expect(actualOutput).toBeNotNull();
|
||||||
|
expect(formatter.format(actualOutput))
|
||||||
|
.toEqual(formatter.format(expectedOutput));
|
||||||
}
|
}
|
||||||
}, log: new RecordingLogger());
|
}, log: new RecordingLogger());
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue