Tim Blasi 2cab7c79c3 feat(dart/transform): Allow multiple transformer entry points
- Allow the user to specify multiple entry points to an app.
- Allow the Angular 2 transformer to run without explicit entry points to
generate necessary setters & getters on built-in directives like `For`
and `If`.

Closes #1246
2015-04-10 13:41:26 -07:00

97 lines
3.2 KiB
Dart

library angular2.transform.reflection_remover.codegen;
import 'package:analyzer/src/generated/ast.dart';
import 'package:barback/barback.dart';
import 'package:code_transformers/resolver.dart';
import 'package:path/path.dart' as path;
import 'package:angular2/src/transform/common/names.dart';
class Codegen {
static const _PREFIX_BASE = 'ngStaticInit';
/// The prefix used to import our generated file.
final String prefix;
/// The import uris
final Iterable<String> importUris;
Codegen(String reflectionEntryPointPath, Iterable<String> newEntryPointPaths,
{String prefix})
: this.prefix = prefix == null ? _PREFIX_BASE : prefix,
importUris = newEntryPointPaths.map((p) =>
path.relative(p, from: path.dirname(reflectionEntryPointPath))) {
if (this.prefix.isEmpty) throw new ArgumentError.value('(empty)', 'prefix');
}
factory Codegen.fromResolver(
Resolver resolver, AssetId reflectionEntryPoint, AssetId newEntryPoint) {
var lib = resolver.getLibrary(reflectionEntryPoint);
var prefix = _PREFIX_BASE;
var idx = 0;
while (lib.imports.any((import) {
return import.prefix != null && import.prefix == prefix;
})) {
prefix = '${_PREFIX_BASE}${idx++}';
}
return new Codegen(reflectionEntryPoint, newEntryPoint, prefix: prefix);
}
/// Generates code to import the library containing the method which sets up
/// Angular2 reflection statically.
///
/// The code generated here should follow the example of code generated for
/// an [ImportDirective] node.
String codegenImport() {
var count = 0;
return importUris
.map((importUri) => 'import \'${importUri}\' as ${prefix}${count++};')
.join('');
}
/// Generates code to call the method which sets up Angular2 reflection
/// statically.
///
/// If [reflectorAssignment] is provided, it is expected to be the node
/// representing the [ReflectionCapabilities] assignment, and we will
/// attempt to parse the access of [reflector] from it so that [reflector] is
/// properly prefixed if necessary.
String codegenSetupReflectionCall(
{AssignmentExpression reflectorAssignment}) {
var reflectorExpression = null;
if (reflectorAssignment != null) {
reflectorExpression = reflectorAssignment.accept(new _ReflectorVisitor());
}
if (reflectorExpression == null) {
reflectorExpression = 'reflector';
}
var count = 0;
return importUris
.map((_) =>
'${prefix}${count++}.${SETUP_METHOD_NAME}(${reflectorExpression});')
.join('');
}
}
/// A visitor whose job it is to find the access of [reflector].
class _ReflectorVisitor extends Object with SimpleAstVisitor<Expression> {
@override
Expression visitAssignmentExpression(AssignmentExpression node) {
if (node == null || node.leftHandSide == null) return null;
return node.leftHandSide.accept(this);
}
@override
Expression visitPropertyAccess(PropertyAccess node) {
if (node == null || node.target == null) return null;
return node.target;
}
@override
Expression visitPrefixedIdentifier(PrefixedIdentifier node) {
if (node == null || node.prefix == null) return null;
return node.prefix;
}
}