perf(dart/transform) Restructure transform to independent phases

Update summary:
- Removes the need for resolution, gaining transform speed at the cost
  of some precision and ability to detect errors
- Generates type registrations in the package alongside their declarations
- Ensures that line numbers do not change in transformed user code
This commit is contained in:
Tim Blasi
2015-02-27 14:42:21 -08:00
parent 08bd3a4443
commit d0aceef4e0
52 changed files with 1530 additions and 318 deletions

View File

@ -0,0 +1,56 @@
library angular2.src.transform.directive_linker.linker;
import 'dart:async';
import 'package:angular2/src/transform/common/logging.dart';
import 'package:angular2/src/transform/common/names.dart';
import 'package:angular2/src/transform/common/ngdata.dart';
import 'package:barback/barback.dart';
import 'package:code_transformers/assets.dart';
import 'package:dart_style/dart_style.dart';
import 'package:path/path.dart' as path;
Future<String> linkNgDeps(Transform transform, String code, String path) async {
var commentIdx = code.lastIndexOf('//');
if (commentIdx < 0) return code;
var ngData = new NgData.fromJson(code.substring(commentIdx + 2));
StringBuffer importBuf =
new StringBuffer(code.substring(0, ngData.importOffset));
StringBuffer declarationBuf = new StringBuffer(
code.substring(ngData.importOffset, ngData.registerOffset));
String tail = code.substring(ngData.registerOffset, commentIdx);
var ngDeps = await _processNgImports(transform, ngData.imports);
for (var i = 0; i < ngDeps.length; ++i) {
importBuf.write('import \'${ngDeps[i]}\' as i${i};');
declarationBuf.write('i${i}.${SETUP_METHOD_NAME}(${REFLECTOR_VAR_NAME});');
}
return '${importBuf}${declarationBuf}${tail}';
}
String _toDepsUri(String importUri) =>
'${path.withoutExtension(importUri)}${DEPS_EXTENSION}';
bool _isNotDartImport(String importUri) {
return !importUri.startsWith('dart:');
}
Future<List<String>> _processNgImports(
Transform transform, List<String> imports) async {
var retVal = <String>[];
return Future
.wait(imports.where(_isNotDartImport).map(_toDepsUri).map((ngDepsUri) {
var importAsset = uriToAssetId(
transform.primaryInput.id, ngDepsUri, logger, null /* span */);
return transform.hasInput(importAsset).then((hasInput) {
if (hasInput) {
retVal.add(ngDepsUri);
}
});
})).then((_) => retVal);
}

View File

@ -0,0 +1,43 @@
library angular2.src.transform.directive_linker.transformer;
import 'dart:async';
import 'package:angular2/src/transform/common/formatter.dart';
import 'package:angular2/src/transform/common/logging.dart' as log;
import 'package:angular2/src/transform/common/names.dart';
import 'package:angular2/src/transform/common/options.dart';
import 'package:barback/barback.dart';
import 'linker.dart';
/// Transformer responsible for processing .ngDeps.dart files created by
/// [DirectiveProcessor] and ensuring that the generated calls to
/// `setupReflection` call the necessary `setupReflection` method in all
/// dependencies.
class DirectiveLinker extends Transformer {
final TransformerOptions options;
DirectiveLinker(this.options);
@override
bool isPrimary(AssetId id) => id.path.endsWith(DEPS_EXTENSION);
@override
Future apply(Transform transform) async {
log.init(transform);
try {
var assetCode = await transform.primaryInput.readAsString();
var assetPath = transform.primaryInput.id.path;
var transformedCode = await linkNgDeps(transform, assetCode, assetPath);
var formattedCode = formatter.format(transformedCode, uri: assetPath);
transform.addOutput(
new Asset.fromString(transform.primaryInput.id, formattedCode));
} catch (ex, stackTrace) {
log.logger.error('Linking ng directives failed.\n'
'Exception: $ex\n'
'Stack Trace: $stackTrace');
}
return null;
}
}