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,22 @@
library angular2.src.transform.common.formatter;
import 'package:dart_style/dart_style.dart';
import 'logging.dart';
DartFormatter _formatter;
void init(DartFormatter formatter) {
if (_formatter != null) {
logger.warning('Formatter is being overwritten.');
}
_formatter = formatter;
}
DartFormatter get formatter {
if (_formatter == null) {
logger.info('Formatter never initialized, using default formatter.');
_formatter = new DartFormatter();
}
return _formatter;
}

View File

@ -0,0 +1,19 @@
library angular2.src.transform.common.logging;
import 'package:barback/barback.dart';
import 'package:code_transformers/messages/build_logger.dart';
BuildLogger _logger;
/// Prepares [logger] for use throughout the transformer.
void init(Transform t) {
_logger = new BuildLogger(t);
}
/// The logger the transformer should use for messaging.
BuildLogger get logger {
if (_logger == null) {
throw new StateError('Logger never initialized.');
}
return _logger;
}

View File

@ -0,0 +1,7 @@
library angular2.src.transform.common.names;
const SETUP_METHOD_NAME = 'setupReflection';
const REFLECTOR_VAR_NAME = 'reflector';
const DEPS_EXTENSION = '.ngDeps.dart';
const REGISTER_TYPE_METHOD_NAME = 'registerType';
const REGISTER_SETTERS_METHOD_NAME = 'registerSetters';

View File

@ -0,0 +1,35 @@
library angular2.src.transform.common.ng_data;
import 'dart:convert';
const NG_DATA_VERSION = 1;
class NgData extends Object {
int importOffset = 0;
int registerOffset = 0;
List<String> imports = [];
NgData();
factory NgData.fromJson(String json) {
var data = JSON.decode(json);
return new NgData()
..importOffset = data['importOffset']
..registerOffset = data['registerOffset']
..imports = data['imports'];
}
String toJson() {
return JSON.encode({
'version': NG_DATA_VERSION,
'importOffset': importOffset,
'registerOffset': registerOffset,
'imports': imports
});
}
@override
String toString() {
return '[NgData: ${toJson()}]';
}
}

View File

@ -0,0 +1,29 @@
library angular2.src.transform.common.options;
const ENTRY_POINT_PARAM = 'entry_point';
const REFLECTION_ENTRY_POINT_PARAM = 'reflection_entry_point';
/// Provides information necessary to transform an Angular2 app.
class TransformerOptions {
/// The path to the file where the application's call to [bootstrap] is.
// TODO(kegluneq): Allow multiple entry points.
final String entryPoint;
/// The reflection entry point, that is, the path to the file where the
/// application's [ReflectionCapabilities] are set.
final String reflectionEntryPoint;
TransformerOptions._internal(this.entryPoint, this.reflectionEntryPoint);
factory TransformerOptions(String entryPoint, {String reflectionEntryPoint}) {
if (entryPoint == null) {
throw new ArgumentError.notNull(ENTRY_POINT_PARAM);
} else if (entryPoint.isEmpty) {
throw new ArgumentError.value(entryPoint, 'entryPoint');
}
if (reflectionEntryPoint == null || entryPoint.isEmpty) {
reflectionEntryPoint = entryPoint;
}
return new TransformerOptions._internal(entryPoint, reflectionEntryPoint);
}
}

View File

@ -0,0 +1,111 @@
library angular2.src.transform.common;
import 'package:analyzer/analyzer.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/scanner.dart';
/// Visitor providing common methods for concrete implementations.
class VisitorMixin {
PrintWriter writer;
/**
* Visit the given function body, printing the prefix before if given body is not empty.
*
* @param prefix the prefix to be printed if there is a node to visit
* @param body the function body to be visited
*/
void visitFunctionWithPrefix(String prefix, FunctionBody body) {
if (body is! EmptyFunctionBody) {
writer.print(prefix);
}
visitNode(body);
}
/// Safely visit [node].
void visitNode(AstNode node) {
if (node != null) {
node.accept(this);
}
}
/// Print a list of [nodes] without any separation.
void visitNodeList(NodeList<AstNode> nodes) {
visitNodeListWithSeparator(nodes, "");
}
/// Print a list of [nodes], separated by the given [separator].
void visitNodeListWithSeparator(NodeList<AstNode> nodes, String separator) {
if (nodes != null) {
int size = nodes.length;
for (int i = 0; i < size; i++) {
if (i > 0) {
writer.print(separator);
}
nodes[i].accept(this);
}
}
}
/// Print a list of [nodes], separated by the given [separator] and
/// preceded by the given [prefix].
void visitNodeListWithSeparatorAndPrefix(
String prefix, NodeList<AstNode> nodes, String separator) {
if (nodes != null) {
int size = nodes.length;
if (size > 0) {
writer.print(prefix);
for (int i = 0; i < size; i++) {
if (i > 0) {
writer.print(separator);
}
nodes[i].accept(this);
}
}
}
}
/// Print a list of [nodes], separated by the given [separator] and
/// succeeded by the given [suffix].
void visitNodeListWithSeparatorAndSuffix(
NodeList<AstNode> nodes, String separator, String suffix) {
if (nodes != null) {
int size = nodes.length;
if (size > 0) {
for (int i = 0; i < size; i++) {
if (i > 0) {
writer.print(separator);
}
nodes[i].accept(this);
}
writer.print(suffix);
}
}
}
/// If [node] is null does nothing. Otherwise, prints [prefix], then
/// visits [node].
void visitNodeWithPrefix(String prefix, AstNode node) {
if (node != null) {
writer.print(prefix);
node.accept(this);
}
}
/// If [node] is null does nothing. Otherwise, visits [node], then prints
/// [suffix].
void visitNodeWithSuffix(AstNode node, String suffix) {
if (node != null) {
node.accept(this);
writer.print(suffix);
}
}
/// Safely visit [node], printing [suffix] after the node if it is
/// non-`null`.
void visitTokenWithSuffix(Token token, String suffix) {
if (token != null) {
writer.print(token.lexeme);
writer.print(suffix);
}
}
}