feature(dart/transform): Inject `initReflector` at @AngularEntrypoint
Detect the `@AngularEntrypoint` annotations on methods and/or functions and add a call to `initReflector` there. See #4865
This commit is contained in:
parent
6b2ef25c69
commit
87449ab43c
|
@ -1,9 +1,10 @@
|
||||||
library hello_world.index;
|
library hello_world.index;
|
||||||
|
|
||||||
import "package:angular2/bootstrap.dart" show bootstrap;
|
import "package:angular2/bootstrap.dart" show AngularEntrypoint, bootstrap;
|
||||||
import "package:angular2/angular2.dart"
|
import "package:angular2/angular2.dart"
|
||||||
show Component, Directive, ElementRef, Injectable, Renderer;
|
show Component, Directive, ElementRef, Injectable, Renderer;
|
||||||
|
|
||||||
|
@AngularEntrypoint("Hello World Entrypoint")
|
||||||
main() {
|
main() {
|
||||||
bootstrap(HelloCmp);
|
bootstrap(HelloCmp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ const _INJECTABLES = const [
|
||||||
|
|
||||||
const _DIRECTIVES = const [
|
const _DIRECTIVES = const [
|
||||||
const ClassDescriptor(
|
const ClassDescriptor(
|
||||||
'Directive', 'package:angular2/src/core/metadatada/directive.dart',
|
'Directive', 'package:angular2/src/core/metadata/directive.dart',
|
||||||
superClass: 'Injectable'),
|
superClass: 'Injectable'),
|
||||||
const ClassDescriptor('Directive', 'package:angular2/src/core/metadata.dart',
|
const ClassDescriptor('Directive', 'package:angular2/src/core/metadata.dart',
|
||||||
superClass: 'Injectable'),
|
superClass: 'Injectable'),
|
||||||
|
@ -57,6 +57,19 @@ const _VIEWS = const [
|
||||||
const ClassDescriptor('View', 'package:angular2/src/core/metadata.dart'),
|
const ClassDescriptor('View', 'package:angular2/src/core/metadata.dart'),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const _ENTRYPOINTS = const [
|
||||||
|
const ClassDescriptor('AngularEntrypoint', 'package:angular2/angular2.dart'),
|
||||||
|
const ClassDescriptor('AngularEntrypoint', 'package:angular2/bootstrap.dart'),
|
||||||
|
const ClassDescriptor(
|
||||||
|
'AngularEntrypoint', 'package:angular2/bootstrap_static.dart'),
|
||||||
|
const ClassDescriptor(
|
||||||
|
'AngularEntrypoint', 'package:angular2/platform/browser.dart'),
|
||||||
|
const ClassDescriptor(
|
||||||
|
'AngularEntrypoint', 'package:angular2/platform/browser_static.dart'),
|
||||||
|
const ClassDescriptor(
|
||||||
|
'AngularEntrypoint', 'package:angular2/src/core/angular_entrypoint.dart'),
|
||||||
|
];
|
||||||
|
|
||||||
/// Checks if a given [Annotation] matches any of the given
|
/// Checks if a given [Annotation] matches any of the given
|
||||||
/// [ClassDescriptors].
|
/// [ClassDescriptors].
|
||||||
class AnnotationMatcher extends ClassMatcherBase {
|
class AnnotationMatcher extends ClassMatcherBase {
|
||||||
|
@ -67,7 +80,8 @@ class AnnotationMatcher extends ClassMatcherBase {
|
||||||
..addAll(_COMPONENTS)
|
..addAll(_COMPONENTS)
|
||||||
..addAll(_DIRECTIVES)
|
..addAll(_DIRECTIVES)
|
||||||
..addAll(_INJECTABLES)
|
..addAll(_INJECTABLES)
|
||||||
..addAll(_VIEWS));
|
..addAll(_VIEWS)
|
||||||
|
..addAll(_ENTRYPOINTS));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _implementsWithWarning(Annotation annotation, AssetId assetId,
|
bool _implementsWithWarning(Annotation annotation, AssetId assetId,
|
||||||
|
@ -94,4 +108,8 @@ class AnnotationMatcher extends ClassMatcherBase {
|
||||||
/// Checks if an [Annotation] node implements [View].
|
/// Checks if an [Annotation] node implements [View].
|
||||||
bool isView(Annotation annotation, AssetId assetId) =>
|
bool isView(Annotation annotation, AssetId assetId) =>
|
||||||
_implementsWithWarning(annotation, assetId, _VIEWS);
|
_implementsWithWarning(annotation, assetId, _VIEWS);
|
||||||
|
|
||||||
|
/// Checks if an [Annotation] node implements [AngularEntrypoint]
|
||||||
|
bool isEntrypoint(Annotation annotation, AssetId assetId) =>
|
||||||
|
_implementsWithWarning(annotation, assetId, _ENTRYPOINTS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
library angular2.transform.reflection_remover.entrypoint_matcher;
|
||||||
|
|
||||||
|
import 'package:analyzer/analyzer.dart';
|
||||||
|
import 'package:barback/barback.dart';
|
||||||
|
|
||||||
|
import 'package:angular2/src/transform/common/annotation_matcher.dart';
|
||||||
|
import 'package:angular2/src/transform/common/naive_eval.dart';
|
||||||
|
|
||||||
|
/// Determines if a [FunctionDeclaration] or [MethodDeclaration] is an
|
||||||
|
/// `AngularEntrypoint`.
|
||||||
|
class EntrypointMatcher {
|
||||||
|
final AssetId _assetId;
|
||||||
|
final AnnotationMatcher _annotationMatcher;
|
||||||
|
|
||||||
|
EntrypointMatcher(this._assetId, this._annotationMatcher) {
|
||||||
|
if (_assetId == null) {
|
||||||
|
throw new ArgumentError.notNull('AssetId');
|
||||||
|
}
|
||||||
|
if (_annotationMatcher == null) {
|
||||||
|
throw new ArgumentError.notNull('AnnotationMatcher');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEntrypoint(AnnotatedNode node) {
|
||||||
|
if (node == null ||
|
||||||
|
(node is! FunctionDeclaration && node is! MethodDeclaration)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return node.metadata
|
||||||
|
.any((a) => _annotationMatcher.isEntrypoint(a, _assetId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the name assigned to the `AngularEntrypoint`.
|
||||||
|
///
|
||||||
|
/// This method assumes the name is the first argument to `AngularEntrypoint`;
|
||||||
|
String getName(AnnotatedNode node) {
|
||||||
|
final annotation = node.metadata.firstWhere(
|
||||||
|
(a) => _annotationMatcher.isEntrypoint(a, _assetId),
|
||||||
|
orElse: () => null);
|
||||||
|
if (annotation == null) return null;
|
||||||
|
if (annotation.arguments == null ||
|
||||||
|
annotation.arguments.arguments == null ||
|
||||||
|
annotation.arguments.arguments.isEmpty) {
|
||||||
|
return _defaultEntrypointName;
|
||||||
|
}
|
||||||
|
final entryPointName = naiveEval(annotation.arguments.arguments.first);
|
||||||
|
if (entryPointName == NOT_A_CONSTANT) {
|
||||||
|
throw new ArgumentError(
|
||||||
|
'Could not evaluate "${node}" as parameter to @AngularEntrypoint');
|
||||||
|
}
|
||||||
|
if (entryPointName is! String) {
|
||||||
|
throw new ArgumentError('Unexpected type "${entryPointName.runtimeType}" '
|
||||||
|
'as first parameter to @AngularEntrypoint');
|
||||||
|
}
|
||||||
|
return entryPointName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const _defaultEntrypointName = "(no name provided)";
|
|
@ -2,11 +2,14 @@ library angular2.transform.reflection_remover.remove_reflection_capabilities;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:analyzer/analyzer.dart';
|
import 'package:analyzer/analyzer.dart';
|
||||||
import 'package:angular2/src/transform/common/asset_reader.dart';
|
|
||||||
import 'package:angular2/src/transform/common/mirror_mode.dart';
|
|
||||||
import 'package:barback/barback.dart';
|
import 'package:barback/barback.dart';
|
||||||
|
|
||||||
|
import 'package:angular2/src/transform/common/annotation_matcher.dart';
|
||||||
|
import 'package:angular2/src/transform/common/asset_reader.dart';
|
||||||
|
import 'package:angular2/src/transform/common/mirror_mode.dart';
|
||||||
|
|
||||||
import 'codegen.dart';
|
import 'codegen.dart';
|
||||||
|
import 'entrypoint_matcher.dart';
|
||||||
import 'rewriter.dart';
|
import 'rewriter.dart';
|
||||||
|
|
||||||
/// Finds the call to the Angular2 `ReflectionCapabilities` constructor
|
/// Finds the call to the Angular2 `ReflectionCapabilities` constructor
|
||||||
|
@ -15,14 +18,15 @@ import 'rewriter.dart';
|
||||||
///
|
///
|
||||||
/// This only searches the code in `reflectionEntryPoint`, not `part`s,
|
/// This only searches the code in `reflectionEntryPoint`, not `part`s,
|
||||||
/// `import`s, `export`s, etc.
|
/// `import`s, `export`s, etc.
|
||||||
Future<String> removeReflectionCapabilities(
|
Future<String> removeReflectionCapabilities(AssetReader reader,
|
||||||
AssetReader reader, AssetId reflectionEntryPoint,
|
AssetId reflectionEntryPoint, AnnotationMatcher annotationMatcher,
|
||||||
{MirrorMode mirrorMode: MirrorMode.none,
|
{MirrorMode mirrorMode: MirrorMode.none,
|
||||||
bool writeStaticInit: true}) async {
|
bool writeStaticInit: true}) async {
|
||||||
var code = await reader.readAsString(reflectionEntryPoint);
|
var code = await reader.readAsString(reflectionEntryPoint);
|
||||||
|
|
||||||
var codegen = new Codegen(reflectionEntryPoint);
|
var codegen = new Codegen(reflectionEntryPoint);
|
||||||
return new Rewriter(code, codegen,
|
return new Rewriter(code, codegen,
|
||||||
|
new EntrypointMatcher(reflectionEntryPoint, annotationMatcher),
|
||||||
mirrorMode: mirrorMode, writeStaticInit: writeStaticInit)
|
mirrorMode: mirrorMode, writeStaticInit: writeStaticInit)
|
||||||
.rewrite(parseCompilationUnit(code, name: reflectionEntryPoint.path));
|
.rewrite(parseCompilationUnit(code, name: reflectionEntryPoint.path));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,43 @@
|
||||||
library angular2.transform.reflection_remover.rewriter;
|
library angular2.transform.reflection_remover.rewriter;
|
||||||
|
|
||||||
import 'package:analyzer/src/generated/ast.dart';
|
import 'package:analyzer/src/generated/ast.dart';
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
import 'package:angular2/src/transform/common/logging.dart';
|
import 'package:angular2/src/transform/common/logging.dart';
|
||||||
import 'package:angular2/src/transform/common/mirror_matcher.dart';
|
import 'package:angular2/src/transform/common/mirror_matcher.dart';
|
||||||
import 'package:angular2/src/transform/common/mirror_mode.dart';
|
import 'package:angular2/src/transform/common/mirror_mode.dart';
|
||||||
import 'package:angular2/src/transform/common/names.dart';
|
import 'package:angular2/src/transform/common/names.dart';
|
||||||
import 'package:path/path.dart' as path;
|
|
||||||
|
|
||||||
import 'codegen.dart';
|
import 'codegen.dart';
|
||||||
|
import 'entrypoint_matcher.dart';
|
||||||
|
|
||||||
class Rewriter {
|
class Rewriter {
|
||||||
final String _code;
|
final String _code;
|
||||||
final Codegen _codegen;
|
final Codegen _codegen;
|
||||||
|
final EntrypointMatcher _entrypointMatcher;
|
||||||
final MirrorMatcher _mirrorMatcher;
|
final MirrorMatcher _mirrorMatcher;
|
||||||
final MirrorMode _mirrorMode;
|
final MirrorMode _mirrorMode;
|
||||||
final bool _writeStaticInit;
|
final bool _writeStaticInit;
|
||||||
|
|
||||||
Rewriter(this._code, this._codegen,
|
Rewriter(this._code, this._codegen, this._entrypointMatcher,
|
||||||
{MirrorMatcher mirrorMatcher,
|
{MirrorMatcher mirrorMatcher,
|
||||||
MirrorMode mirrorMode: MirrorMode.none,
|
MirrorMode mirrorMode: MirrorMode.none,
|
||||||
bool writeStaticInit: true})
|
bool writeStaticInit: true})
|
||||||
: _mirrorMode = mirrorMode,
|
: _mirrorMode = mirrorMode,
|
||||||
_writeStaticInit = writeStaticInit,
|
_writeStaticInit = writeStaticInit,
|
||||||
_mirrorMatcher =
|
_mirrorMatcher =
|
||||||
mirrorMatcher == null ? const MirrorMatcher() : mirrorMatcher;
|
mirrorMatcher == null ? const MirrorMatcher() : mirrorMatcher {
|
||||||
|
if (_codegen == null) {
|
||||||
|
throw new ArgumentError.notNull('Codegen');
|
||||||
|
}
|
||||||
|
if (_entrypointMatcher == null) {
|
||||||
|
throw new ArgumentError.notNull('EntrypointMatcher');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Rewrites the provided code removing imports of the
|
/// Rewrites the provided code to remove dart:mirrors.
|
||||||
|
///
|
||||||
|
/// Specifically, removes imports of the
|
||||||
/// {@link ReflectionCapabilities} library and instantiations of
|
/// {@link ReflectionCapabilities} library and instantiations of
|
||||||
/// {@link ReflectionCapabilities}, as detected by the (potentially) provided
|
/// {@link ReflectionCapabilities}, as detected by the (potentially) provided
|
||||||
/// {@link MirrorMatcher}.
|
/// {@link MirrorMatcher}.
|
||||||
|
@ -51,7 +63,7 @@ class Rewriter {
|
||||||
class _RewriterVisitor extends Object with RecursiveAstVisitor<Object> {
|
class _RewriterVisitor extends Object with RecursiveAstVisitor<Object> {
|
||||||
final Rewriter _rewriter;
|
final Rewriter _rewriter;
|
||||||
final buf = new StringBuffer();
|
final buf = new StringBuffer();
|
||||||
final reflectionCapabilityAssignments = [];
|
final reflectionCapabilityAssignments = <AssignmentExpression>[];
|
||||||
|
|
||||||
int _currentIndex = 0;
|
int _currentIndex = 0;
|
||||||
bool _setupAdded = false;
|
bool _setupAdded = false;
|
||||||
|
@ -105,6 +117,45 @@ class _RewriterVisitor extends Object with RecursiveAstVisitor<Object> {
|
||||||
return super.visitMethodInvocation(node);
|
return super.visitMethodInvocation(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object visitMethodDeclaration(MethodDeclaration node) {
|
||||||
|
if (_rewriter._entrypointMatcher.isEntrypoint(node)) {
|
||||||
|
if (_rewriter._writeStaticInit) {
|
||||||
|
_rewriteEntrypointFunctionBody(node.body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.visitMethodDeclaration(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object visitFunctionDeclaration(FunctionDeclaration node) {
|
||||||
|
if (_rewriter._entrypointMatcher.isEntrypoint(node)) {
|
||||||
|
if (_rewriter._writeStaticInit) {
|
||||||
|
_rewriteEntrypointFunctionBody(node.functionExpression.body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.visitFunctionDeclaration(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _rewriteEntrypointFunctionBody(FunctionBody node) {
|
||||||
|
if (node is BlockFunctionBody) {
|
||||||
|
final insertOffset = node.block.leftBracket.end;
|
||||||
|
buf.write(_rewriter._code.substring(_currentIndex, insertOffset));
|
||||||
|
buf.write(_getStaticReflectorInitBlock());
|
||||||
|
_currentIndex = insertOffset;
|
||||||
|
} else if (node is ExpressionFunctionBody) {
|
||||||
|
// TODO(kegluneq): Add support, see issue #5474.
|
||||||
|
throw new ArgumentError(
|
||||||
|
'Arrow syntax is not currently supported as `@AngularEntrypoint`s');
|
||||||
|
} else if (node is NativeFunctionBody) {
|
||||||
|
throw new ArgumentError('Native functions and methods are not supported '
|
||||||
|
'as `@AngularEntrypoint`s');
|
||||||
|
} else if (node is EmptyFunctionBody) {
|
||||||
|
throw new ArgumentError('Empty functions and methods are not supported '
|
||||||
|
'as `@AngularEntrypoint`s');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String outputRewrittenCode() {
|
String outputRewrittenCode() {
|
||||||
if (_currentIndex < _rewriter._code.length) {
|
if (_currentIndex < _rewriter._code.length) {
|
||||||
buf.write(_rewriter._code.substring(_currentIndex));
|
buf.write(_rewriter._code.substring(_currentIndex));
|
||||||
|
|
|
@ -52,8 +52,11 @@ class ReflectionRemover extends Transformer implements LazyTransformer {
|
||||||
}
|
}
|
||||||
|
|
||||||
var transformedCode = await removeReflectionCapabilities(
|
var transformedCode = await removeReflectionCapabilities(
|
||||||
new AssetReader.fromTransform(transform), primaryId,
|
new AssetReader.fromTransform(transform),
|
||||||
mirrorMode: mirrorMode, writeStaticInit: writeStaticInit);
|
primaryId,
|
||||||
|
options.annotationMatcher,
|
||||||
|
mirrorMode: mirrorMode,
|
||||||
|
writeStaticInit: writeStaticInit);
|
||||||
transform.addOutput(new Asset.fromString(primaryId, transformedCode));
|
transform.addOutput(new Asset.fromString(primaryId, transformedCode));
|
||||||
}, log: transform.logger);
|
}, log: transform.logger);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
library web_foo;
|
||||||
|
|
||||||
|
import 'package:angular2/bootstrap.dart';
|
||||||
|
|
||||||
|
abstract class TestBootstrapper {
|
||||||
|
@AngularEntrypoint()
|
||||||
|
void testBootstrap();
|
||||||
|
}
|
|
@ -1,62 +1,123 @@
|
||||||
library angular2.test.transform.reflection_remover;
|
library angular2.test.transform.reflection_remover;
|
||||||
|
|
||||||
import 'package:analyzer/analyzer.dart';
|
import 'package:analyzer/analyzer.dart';
|
||||||
import 'package:angular2/src/transform/common/mirror_mode.dart';
|
|
||||||
import 'package:angular2/src/transform/reflection_remover/codegen.dart';
|
|
||||||
import 'package:angular2/src/transform/reflection_remover/rewriter.dart';
|
|
||||||
import 'package:barback/barback.dart';
|
import 'package:barback/barback.dart';
|
||||||
import 'package:guinness/guinness.dart';
|
import 'package:guinness/guinness.dart';
|
||||||
|
|
||||||
import 'reflection_remover_files/expected/index.dart' as expected;
|
import 'package:angular2/src/transform/common/annotation_matcher.dart';
|
||||||
import 'debug_mirrors_files/expected/index.dart' as debug_mirrors;
|
import 'package:angular2/src/transform/common/mirror_mode.dart';
|
||||||
import 'log_mirrors_files/expected/index.dart' as log_mirrors;
|
import 'package:angular2/src/transform/reflection_remover/codegen.dart';
|
||||||
import 'verbose_files/expected/index.dart' as verbose_mirrors;
|
import 'package:angular2/src/transform/reflection_remover/entrypoint_matcher.dart';
|
||||||
import 'bootstrap_files/expected/index.dart' as bootstrap_expected;
|
import 'package:angular2/src/transform/reflection_remover/rewriter.dart';
|
||||||
|
|
||||||
import '../common/read_file.dart';
|
import '../common/read_file.dart';
|
||||||
|
import 'bootstrap_files/expected/index.dart' as bootstrap_expected;
|
||||||
|
import 'debug_mirrors_files/expected/index.dart' as debug_mirrors;
|
||||||
|
import 'function_annotation_files/expected/index.dart'
|
||||||
|
as func_annotation_expected;
|
||||||
|
import 'log_mirrors_files/expected/index.dart' as log_mirrors;
|
||||||
|
import 'method_annotation_files/expected/index.dart'
|
||||||
|
as method_annotation_expected;
|
||||||
|
import 'reflection_remover_files/expected/index.dart' as expected;
|
||||||
|
import 'verbose_files/expected/index.dart' as verbose_mirrors;
|
||||||
|
|
||||||
main() => allTests();
|
main() => allTests();
|
||||||
|
|
||||||
void allTests() {
|
void allTests() {
|
||||||
var assetId = new AssetId('a', 'web/index.dart');
|
var entrypointMatcher, assetId, codegen, code;
|
||||||
var codegen = new Codegen(assetId);
|
|
||||||
var code = readFile('reflection_remover/index.dart').replaceAll('\r\n', '\n');
|
beforeEach(() {
|
||||||
var bootstrapCode = readFile('reflection_remover/bootstrap_files/index.dart')
|
assetId = new AssetId('a', 'web/index.dart');
|
||||||
.replaceAll('\r\n', '\n');
|
codegen = new Codegen(assetId);
|
||||||
|
code = readFile('reflection_remover/index.dart').replaceAll('\r\n', '\n');
|
||||||
|
entrypointMatcher = new EntrypointMatcher(assetId, new AnnotationMatcher());
|
||||||
|
});
|
||||||
|
|
||||||
it(
|
it(
|
||||||
'should remove uses of mirrors & '
|
'should remove uses of mirrors & '
|
||||||
'insert calls to generated code by default.', () {
|
'insert calls to generated code by default.', () {
|
||||||
var output =
|
var output = new Rewriter(code, codegen, entrypointMatcher)
|
||||||
new Rewriter(code, codegen).rewrite(parseCompilationUnit(code));
|
.rewrite(parseCompilationUnit(code));
|
||||||
expect(output).toEqual(expected.code);
|
expect(output).toEqual(expected.code);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(
|
it(
|
||||||
'should replace uses of mirrors with the debug implementation & '
|
'should replace uses of mirrors with the debug implementation & '
|
||||||
'insert calls to generated code in `MirrorMode.debug`.', () {
|
'insert calls to generated code in `MirrorMode.debug`.', () {
|
||||||
var output = new Rewriter(code, codegen, mirrorMode: MirrorMode.debug)
|
var output = new Rewriter(code, codegen, entrypointMatcher,
|
||||||
.rewrite(parseCompilationUnit(code));
|
mirrorMode: MirrorMode.debug).rewrite(parseCompilationUnit(code));
|
||||||
expect(output).toEqual(debug_mirrors.code);
|
expect(output).toEqual(debug_mirrors.code);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(
|
it(
|
||||||
'should replace uses of mirrors with the verbose implementation '
|
'should replace uses of mirrors with the verbose implementation '
|
||||||
'in `MirrorMode.verbose`.', () {
|
'in `MirrorMode.verbose`.', () {
|
||||||
var output = new Rewriter(code, codegen, mirrorMode: MirrorMode.verbose)
|
var output = new Rewriter(code, codegen, entrypointMatcher,
|
||||||
.rewrite(parseCompilationUnit(code));
|
mirrorMode: MirrorMode.verbose).rewrite(parseCompilationUnit(code));
|
||||||
expect(output).toEqual(verbose_mirrors.code);
|
expect(output).toEqual(verbose_mirrors.code);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not initialize the reflector when `writeStaticInit` is `false`.',
|
it('should not initialize the reflector when `writeStaticInit` is `false`.',
|
||||||
() {
|
() {
|
||||||
var output = new Rewriter(code, codegen, writeStaticInit: false)
|
var output = new Rewriter(code, codegen, entrypointMatcher,
|
||||||
.rewrite(parseCompilationUnit(code));
|
writeStaticInit: false).rewrite(parseCompilationUnit(code));
|
||||||
expect(output).toEqual(log_mirrors.code);
|
expect(output).toEqual(log_mirrors.code);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should rewrite bootstrap.', () {
|
it('should rewrite bootstrap.', () {
|
||||||
var output = new Rewriter(bootstrapCode, codegen, writeStaticInit: true)
|
final bootstrapCode =
|
||||||
.rewrite(parseCompilationUnit(bootstrapCode));
|
readFile('reflection_remover/bootstrap_files/index.dart')
|
||||||
|
.replaceAll('\r\n', '\n');
|
||||||
|
var output = new Rewriter(bootstrapCode, codegen, entrypointMatcher,
|
||||||
|
writeStaticInit: true).rewrite(parseCompilationUnit(bootstrapCode));
|
||||||
expect(output).toEqual(bootstrap_expected.code);
|
expect(output).toEqual(bootstrap_expected.code);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('AngularEntrypoint annotation', () {
|
||||||
|
it('should add a call to `initReflector` at the beginning of the function',
|
||||||
|
() {
|
||||||
|
code = readFile('reflection_remover/function_annotation_files/index.dart')
|
||||||
|
.replaceAll('\r\n', '\n');
|
||||||
|
final output = new Rewriter(code, codegen, entrypointMatcher)
|
||||||
|
.rewrite(parseCompilationUnit(code));
|
||||||
|
expect(output).toEqual(func_annotation_expected.code);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should `throw` for entrypoints implemented as arrow functions', () {
|
||||||
|
code = readFile('reflection_remover/arrow_annotation_files/index.dart')
|
||||||
|
.replaceAll('\r\n', '\n');
|
||||||
|
expect(() {
|
||||||
|
new Rewriter(code, codegen, entrypointMatcher)
|
||||||
|
.rewrite(parseCompilationUnit(code));
|
||||||
|
}).toThrowWith(anInstanceOf: ArgumentError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should `throw` for native functions annotated as entry points', () {
|
||||||
|
code = readFile('reflection_remover/native_annotation_files/index.dart')
|
||||||
|
.replaceAll('\r\n', '\n');
|
||||||
|
expect(() {
|
||||||
|
new Rewriter(code, codegen, entrypointMatcher)
|
||||||
|
.rewrite(parseCompilationUnit(code));
|
||||||
|
}).toThrowWith(anInstanceOf: ArgumentError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should `throw` for abstract functions annotated as entry points', () {
|
||||||
|
code = readFile(
|
||||||
|
'reflection_remover/abstract_method_annotation_files/index.dart')
|
||||||
|
.replaceAll('\r\n', '\n');
|
||||||
|
expect(() {
|
||||||
|
new Rewriter(code, codegen, entrypointMatcher)
|
||||||
|
.rewrite(parseCompilationUnit(code));
|
||||||
|
}).toThrowWith(anInstanceOf: ArgumentError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add a call to `initReflector` at the beginning of the method',
|
||||||
|
() {
|
||||||
|
code = readFile('reflection_remover/method_annotation_files/index.dart')
|
||||||
|
.replaceAll('\r\n', '\n');
|
||||||
|
final output = new Rewriter(code, codegen, entrypointMatcher)
|
||||||
|
.rewrite(parseCompilationUnit(code));
|
||||||
|
expect(output).toEqual(method_annotation_expected.code);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
library web_foo;
|
||||||
|
|
||||||
|
import 'package:angular2/bootstrap.dart';
|
||||||
|
import 'package:angular2/src/core/reflection/reflection.dart';
|
||||||
|
import 'package:angular2/src/core/reflection/reflection_capabilities.dart';
|
||||||
|
|
||||||
|
@AngularEntrypoint()
|
||||||
|
main() => bootstrap(MyComponent);
|
|
@ -0,0 +1,23 @@
|
||||||
|
library angular2.test.transform.reflection_remover.function_annotation_files;
|
||||||
|
|
||||||
|
// This file is intentionally formatted as a string to avoid having the
|
||||||
|
// automatic transformer prettify it.
|
||||||
|
//
|
||||||
|
// This file represents transformed user code. Because this code will be
|
||||||
|
// linked to output by a source map, we cannot change line numbers from the
|
||||||
|
// original code and we therefore add our generated code on the same line as
|
||||||
|
// those we are removing.
|
||||||
|
|
||||||
|
const code = """
|
||||||
|
library web_foo;
|
||||||
|
|
||||||
|
import 'package:angular2/bootstrap_static.dart';import 'index.ng_deps.dart' as ngStaticInit;
|
||||||
|
import 'package:angular2/src/core/reflection/reflection.dart';
|
||||||
|
/*import 'package:angular2/src/core/reflection/reflection_capabilities.dart';*/
|
||||||
|
|
||||||
|
@AngularEntrypoint()
|
||||||
|
void main() {ngStaticInit.initReflector();
|
||||||
|
ngStaticInit.initReflector();/*reflector.reflectionCapabilities = new ReflectionCapabilities();*/
|
||||||
|
bootstrapStatic(MyComponent);
|
||||||
|
}
|
||||||
|
""";
|
|
@ -0,0 +1,11 @@
|
||||||
|
library web_foo;
|
||||||
|
|
||||||
|
import 'package:angular2/bootstrap.dart';
|
||||||
|
import 'package:angular2/src/core/reflection/reflection.dart';
|
||||||
|
import 'package:angular2/src/core/reflection/reflection_capabilities.dart';
|
||||||
|
|
||||||
|
@AngularEntrypoint()
|
||||||
|
void main() {
|
||||||
|
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||||
|
bootstrap(MyComponent);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
library angular2.test.transform.reflection_remover.method_annotation_files;
|
||||||
|
|
||||||
|
// This file is intentionally formatted as a string to avoid having the
|
||||||
|
// automatic transformer prettify it.
|
||||||
|
//
|
||||||
|
// This file represents transformed user code. Because this code will be
|
||||||
|
// linked to output by a source map, we cannot change line numbers from the
|
||||||
|
// original code and we therefore add our generated code on the same line as
|
||||||
|
// those we are removing.
|
||||||
|
|
||||||
|
const code = """
|
||||||
|
library web_foo;
|
||||||
|
|
||||||
|
import 'package:angular2/bootstrap_static.dart';import 'index.ng_deps.dart' as ngStaticInit;
|
||||||
|
|
||||||
|
class TestBootstrapper {
|
||||||
|
@AngularEntrypoint("Method entrypoint")
|
||||||
|
void testBootstrap() {ngStaticInit.initReflector();}
|
||||||
|
}
|
||||||
|
""";
|
|
@ -0,0 +1,8 @@
|
||||||
|
library web_foo;
|
||||||
|
|
||||||
|
import 'package:angular2/bootstrap.dart';
|
||||||
|
|
||||||
|
class TestBootstrapper {
|
||||||
|
@AngularEntrypoint("Method entrypoint")
|
||||||
|
void testBootstrap() {}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
library web_foo;
|
||||||
|
|
||||||
|
import 'package:angular2/bootstrap.dart';
|
||||||
|
import 'package:angular2/src/core/reflection/reflection.dart';
|
||||||
|
import 'package:angular2/src/core/reflection/reflection_capabilities.dart';
|
||||||
|
|
||||||
|
@AngularEntrypoint()
|
||||||
|
main() native "MainMethod";
|
Loading…
Reference in New Issue