feat(bootstrap): remove the need for explicit reflection setup in bootstrap code
BREAKING CHANGES: Dart applications and TypeScript applications meant to transpile to Dart must now import `package:angular2/bootstrap.dart` instead of `package:angular2/angular2.dart` in their bootstrap code. `package:angular2/angular2.dart` no longer export the bootstrap function. The transformer rewrites imports of `bootstrap.dart` and calls to `bootstrap` to `bootstrap_static.dart` and `bootstrapStatic` respectively.
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
library angular2;
|
||||
|
||||
/**
|
||||
* An all-in-one place to import Angular 2 stuff.
|
||||
*
|
||||
* This library does not include `bootstrap`. Import `bootstrap.dart` instead.
|
||||
*/
|
||||
export 'package:angular2/angular2_exports.dart';
|
||||
@@ -1,6 +1,12 @@
|
||||
/**
|
||||
* The `angular2` is the single place to import all of the individual types.
|
||||
*/
|
||||
export {commonBootstrap as bootstrap} from 'angular2/src/core/application_common';
|
||||
|
||||
// TODO(someone familiar with systemjs): the exports below are copied from
|
||||
// angular2_exports.ts. Re-exporting from angular2_exports.ts causes systemjs
|
||||
// to resolve imports very very very slowly. See also a similar notice in
|
||||
// bootstrap.ts
|
||||
export * from 'angular2/annotations';
|
||||
export * from 'angular2/core';
|
||||
|
||||
@@ -28,34 +34,7 @@ export {
|
||||
|
||||
export * from './di';
|
||||
export * from './forms';
|
||||
|
||||
export * from './directives';
|
||||
|
||||
export {
|
||||
AbstractControl,
|
||||
AbstractControlDirective,
|
||||
Control,
|
||||
ControlGroup,
|
||||
ControlArray,
|
||||
NgControlName,
|
||||
NgFormControl,
|
||||
NgModel,
|
||||
NgControl,
|
||||
NgControlGroup,
|
||||
NgFormModel,
|
||||
NgForm,
|
||||
ControlValueAccessor,
|
||||
DefaultValueAccessor,
|
||||
CheckboxControlValueAccessor,
|
||||
SelectControlValueAccessor,
|
||||
formDirectives,
|
||||
Validators,
|
||||
NgValidator,
|
||||
NgRequiredValidator,
|
||||
FormBuilder,
|
||||
formInjectables
|
||||
} from './forms';
|
||||
|
||||
export * from './http';
|
||||
export {
|
||||
RenderEventDispatcher,
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
export * from 'angular2/annotations';
|
||||
export * from 'angular2/core';
|
||||
|
||||
export {
|
||||
DehydratedException,
|
||||
ExpressionChangedAfterItHasBeenChecked,
|
||||
ChangeDetectionError,
|
||||
|
||||
ON_PUSH,
|
||||
DEFAULT,
|
||||
|
||||
ChangeDetectorRef,
|
||||
|
||||
Pipes,
|
||||
WrappedValue,
|
||||
Pipe,
|
||||
PipeFactory,
|
||||
NullPipe,
|
||||
NullPipeFactory,
|
||||
defaultPipes,
|
||||
BasePipe,
|
||||
|
||||
Locals
|
||||
} from './change_detection';
|
||||
|
||||
export * from './di';
|
||||
export * from './forms';
|
||||
export * from './directives';
|
||||
export * from './http';
|
||||
export {
|
||||
RenderEventDispatcher,
|
||||
Renderer,
|
||||
RenderElementRef,
|
||||
RenderViewRef,
|
||||
RenderProtoViewRef,
|
||||
RenderFragmentRef,
|
||||
RenderViewWithFragments
|
||||
} from 'angular2/src/render/api';
|
||||
export {
|
||||
DomRenderer,
|
||||
DOCUMENT_TOKEN,
|
||||
DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES
|
||||
} from 'angular2/src/render/dom/dom_renderer';
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Contains everything you need to bootstrap your application.
|
||||
*/
|
||||
export {bootstrap} from 'angular2/src/core/application';
|
||||
|
||||
// TODO(someone familiar with systemjs): the exports below are copied from
|
||||
// angular2_exports.ts. Re-exporting from angular2_exports.ts causes systemjs
|
||||
// to resolve imports very very very slowly. See also a similar notice in
|
||||
// angular2.ts
|
||||
export * from 'angular2/annotations';
|
||||
export * from 'angular2/core';
|
||||
|
||||
export {
|
||||
DehydratedException,
|
||||
ExpressionChangedAfterItHasBeenChecked,
|
||||
ChangeDetectionError,
|
||||
|
||||
ON_PUSH,
|
||||
DEFAULT,
|
||||
|
||||
ChangeDetectorRef,
|
||||
|
||||
Pipes,
|
||||
WrappedValue,
|
||||
Pipe,
|
||||
PipeFactory,
|
||||
NullPipe,
|
||||
NullPipeFactory,
|
||||
defaultPipes,
|
||||
BasePipe,
|
||||
|
||||
Locals
|
||||
} from './change_detection';
|
||||
|
||||
export * from './di';
|
||||
export * from './forms';
|
||||
export * from './directives';
|
||||
export * from './http';
|
||||
export {
|
||||
RenderEventDispatcher,
|
||||
Renderer,
|
||||
RenderElementRef,
|
||||
RenderViewRef,
|
||||
RenderProtoViewRef,
|
||||
RenderFragmentRef,
|
||||
RenderViewWithFragments
|
||||
} from 'angular2/src/render/api';
|
||||
export {
|
||||
DomRenderer,
|
||||
DOCUMENT_TOKEN,
|
||||
DOM_REFLECT_PROPERTIES_AS_ATTRIBUTES
|
||||
} from 'angular2/src/render/dom/dom_renderer';
|
||||
@@ -0,0 +1,4 @@
|
||||
library angular2.bootstrap_static;
|
||||
|
||||
export 'angular2_exports.dart';
|
||||
export 'src/core/application_static.dart';
|
||||
@@ -3,8 +3,8 @@
|
||||
* @description
|
||||
* Define angular core API here.
|
||||
*/
|
||||
export {bootstrap, ApplicationRef} from 'angular2/src/core/application';
|
||||
export {appComponentTypeToken} from 'angular2/src/core/application_tokens';
|
||||
export {ApplicationRef} from 'angular2/src/core/application_common';
|
||||
|
||||
|
||||
// Compiler Related Dependencies.
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
library angular2.application;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:angular2/src/reflection/reflection.dart' show reflector;
|
||||
import 'package:angular2/src/reflection/reflection_capabilities.dart' show ReflectionCapabilities;
|
||||
import 'application_common.dart';
|
||||
|
||||
export 'application_common.dart' show ApplicationRef;
|
||||
|
||||
/// Starts an application from a root component. This implementation uses
|
||||
/// mirrors. Angular 2 transformer automatically replaces this method with a
|
||||
/// static implementation (see `application_static.dart`) that does not use
|
||||
/// mirrors and produces a faster and more compact JS code.
|
||||
///
|
||||
/// See [commonBootstrap] for detailed documentation.
|
||||
Future<ApplicationRef> bootstrap(Type appComponentType,
|
||||
[List componentInjectableBindings, Function errorReporter]) {
|
||||
reflector.reflectionCapabilities = new ReflectionCapabilities();
|
||||
return commonBootstrap(appComponentType, componentInjectableBindings, errorReporter);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,14 @@
|
||||
library angular2.application_static;
|
||||
|
||||
import 'dart:async';
|
||||
import 'application_common.dart';
|
||||
|
||||
/// Starts an application from a root component.
|
||||
///
|
||||
/// See [commonBootstrap] for detailed documentation.
|
||||
Future<ApplicationRef> bootstrapStatic(
|
||||
Type appComponentType,
|
||||
[List componentInjectableBindings,
|
||||
Function errorReporter]) {
|
||||
return commonBootstrap(appComponentType, componentInjectableBindings, errorReporter);
|
||||
}
|
||||
@@ -1,13 +1,6 @@
|
||||
import {Directive} from 'angular2/annotations';
|
||||
import {
|
||||
ViewContainerRef,
|
||||
ViewRef,
|
||||
TemplateRef,
|
||||
Pipes,
|
||||
LifecycleEvent,
|
||||
Pipe,
|
||||
ChangeDetectorRef
|
||||
} from 'angular2/angular2';
|
||||
import {Directive, LifecycleEvent} from 'angular2/annotations';
|
||||
import {ViewContainerRef, ViewRef, TemplateRef} from 'angular2/core';
|
||||
import {ChangeDetectorRef, Pipe, Pipes} from 'angular2/change_detection';
|
||||
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Directive, LifecycleEvent} from 'angular2/angular2';
|
||||
import {Directive, LifecycleEvent} from 'angular2/annotations';
|
||||
import {Inject, Ancestor, forwardRef, Binding} from 'angular2/di';
|
||||
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
|
||||
@@ -2,7 +2,8 @@ import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
|
||||
import {List, StringMap} from 'angular2/src/facade/collection';
|
||||
|
||||
import {Directive, LifecycleEvent, Query, QueryList} from 'angular2/angular2';
|
||||
import {QueryList} from 'angular2/core';
|
||||
import {Query, Directive, LifecycleEvent} from 'angular2/annotations';
|
||||
import {forwardRef, Ancestor, Binding, Inject} from 'angular2/di';
|
||||
|
||||
import {ControlContainer} from './control_container';
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
|
||||
|
||||
import {Directive, LifecycleEvent, Query, QueryList} from 'angular2/angular2';
|
||||
import {QueryList} from 'angular2/core';
|
||||
import {Query, Directive, LifecycleEvent} from 'angular2/annotations';
|
||||
import {forwardRef, Ancestor, Binding} from 'angular2/di';
|
||||
|
||||
import {NgControl} from './ng_control';
|
||||
|
||||
@@ -2,7 +2,7 @@ import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {ObservableWrapper, EventEmitter} from 'angular2/src/facade/async';
|
||||
|
||||
import {Directive, LifecycleEvent} from 'angular2/angular2';
|
||||
import {Directive, LifecycleEvent} from 'angular2/annotations';
|
||||
import {forwardRef, Binding} from 'angular2/di';
|
||||
import {NgControl} from './ng_control';
|
||||
import {NgControlGroup} from './ng_control_group';
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||
import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
|
||||
|
||||
import {Directive, LifecycleEvent, QueryList, Query} from 'angular2/angular2';
|
||||
import {QueryList} from 'angular2/core';
|
||||
import {Query, Directive, LifecycleEvent} from 'angular2/annotations';
|
||||
import {forwardRef, Ancestor, Binding} from 'angular2/di';
|
||||
|
||||
import {NgControl} from './ng_control';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {Renderer} from 'angular2/render';
|
||||
import {ElementRef, QueryList, Directive, Query} from 'angular2/angular2';
|
||||
import {ElementRef, QueryList} from 'angular2/core';
|
||||
import {Query, Directive} from 'angular2/annotations';
|
||||
|
||||
import {NgControl} from './ng_control';
|
||||
import {ControlValueAccessor} from './control_value_accessor';
|
||||
|
||||
@@ -84,7 +84,7 @@ function _getAppBindings() {
|
||||
|
||||
// The document is only available in browser environment
|
||||
try {
|
||||
appDoc = DOM.defaultDoc();
|
||||
appDoc = DOM.createHtmlDocument();
|
||||
} catch (e) {
|
||||
appDoc = null;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ const INJECTABLES = const [
|
||||
'Injectable', 'package:angular2/src/di/decorators.dart'),
|
||||
const ClassDescriptor('Injectable', 'package:angular2/di.dart'),
|
||||
const ClassDescriptor('Injectable', 'package:angular2/angular2.dart'),
|
||||
const ClassDescriptor('Injectable', 'package:angular2/bootstrap_static.dart'),
|
||||
];
|
||||
|
||||
const DIRECTIVES = const [
|
||||
@@ -32,6 +33,8 @@ const DIRECTIVES = const [
|
||||
superClass: 'Injectable'),
|
||||
const ClassDescriptor('Directive', 'package:angular2/core.dart',
|
||||
superClass: 'Injectable'),
|
||||
const ClassDescriptor('Directive', 'package:angular2/bootstrap_static.dart',
|
||||
superClass: 'Injectable'),
|
||||
];
|
||||
|
||||
const COMPONENTS = const [
|
||||
@@ -48,6 +51,8 @@ const COMPONENTS = const [
|
||||
superClass: 'Directive'),
|
||||
const ClassDescriptor('Component', 'package:angular2/angular2.dart',
|
||||
superClass: 'Directive'),
|
||||
const ClassDescriptor('Component', 'package:angular2/bootstrap_static.dart',
|
||||
superClass: 'Directive'),
|
||||
const ClassDescriptor('Component', 'package:angular2/core.dart',
|
||||
superClass: 'Directive'),
|
||||
];
|
||||
@@ -55,6 +60,7 @@ const COMPONENTS = const [
|
||||
const VIEWS = const [
|
||||
const ClassDescriptor('View', 'package:angular2/view.dart'),
|
||||
const ClassDescriptor('View', 'package:angular2/angular2.dart'),
|
||||
const ClassDescriptor('View', 'package:angular2/bootstrap_static.dart'),
|
||||
const ClassDescriptor('View', 'package:angular2/core.dart'),
|
||||
const ClassDescriptor(
|
||||
'View', 'package:angular2/src/core/annotations/view.dart'),
|
||||
@@ -75,24 +81,29 @@ class AnnotationMatcher extends ClassMatcherBase {
|
||||
..addAll(VIEWS));
|
||||
}
|
||||
|
||||
bool _implementsWithWarning(
|
||||
ClassDescriptor descriptor, List<ClassDescriptor> interfaces) =>
|
||||
implements(descriptor, interfaces,
|
||||
bool _implementsWithWarning(Annotation annotation, AssetId assetId,
|
||||
List<ClassDescriptor> interfaces) {
|
||||
ClassDescriptor descriptor = firstMatch(annotation.name, assetId);
|
||||
if (descriptor == null) {
|
||||
throw 'Unable to locate descriptor for ${annotation.name} in ${assetId}';
|
||||
}
|
||||
return implements(descriptor, interfaces,
|
||||
missingSuperClassWarning: 'Missing `custom_annotation` entry for `${descriptor.superClass}`.');
|
||||
}
|
||||
|
||||
/// Checks if an [Annotation] node implements [Injectable].
|
||||
bool isInjectable(Annotation annotation, AssetId assetId) =>
|
||||
_implementsWithWarning(firstMatch(annotation.name, assetId), INJECTABLES);
|
||||
_implementsWithWarning(annotation, assetId, INJECTABLES);
|
||||
|
||||
/// Checks if an [Annotation] node implements [Directive].
|
||||
bool isDirective(Annotation annotation, AssetId assetId) =>
|
||||
_implementsWithWarning(firstMatch(annotation.name, assetId), DIRECTIVES);
|
||||
_implementsWithWarning(annotation, assetId, DIRECTIVES);
|
||||
|
||||
/// Checks if an [Annotation] node implements [Component].
|
||||
bool isComponent(Annotation annotation, AssetId assetId) =>
|
||||
_implementsWithWarning(firstMatch(annotation.name, assetId), COMPONENTS);
|
||||
_implementsWithWarning(annotation, assetId, COMPONENTS);
|
||||
|
||||
/// Checks if an [Annotation] node implements [View].
|
||||
bool isView(Annotation annotation, AssetId assetId) =>
|
||||
_implementsWithWarning(firstMatch(annotation.name, assetId), VIEWS);
|
||||
_implementsWithWarning(annotation, assetId, VIEWS);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
library angular2.transform.common.names;
|
||||
|
||||
const BOOTSTRAP_NAME = 'bootstrap';
|
||||
const SETUP_METHOD_NAME = 'initReflector';
|
||||
const REFLECTOR_VAR_NAME = 'reflector';
|
||||
const TRANSFORM_DYNAMIC_MODE = 'transform_dynamic';
|
||||
|
||||
@@ -15,6 +15,10 @@ class AstTester {
|
||||
bool isReflectionCapabilitiesImport(ImportDirective node) {
|
||||
return node.uri.stringValue.endsWith("reflection_capabilities.dart");
|
||||
}
|
||||
|
||||
bool isBootstrapImport(ImportDirective node) {
|
||||
return node.uri.stringValue.endsWith("/bootstrap.dart");
|
||||
}
|
||||
}
|
||||
|
||||
/// An object that checks for {@link ReflectionCapabilities} using a fully resolved
|
||||
@@ -32,4 +36,8 @@ class ResolvedTester implements AstTester {
|
||||
bool isReflectionCapabilitiesImport(ImportDirective node) {
|
||||
return node.uriElement == _forbiddenClass.library;
|
||||
}
|
||||
|
||||
bool isBootstrapImport(ImportDirective node) {
|
||||
throw 'Not implemented';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
library angular2.transform.reflection_remover.codegen;
|
||||
|
||||
import 'package:analyzer/src/generated/ast.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import 'package:angular2/src/transform/common/names.dart';
|
||||
@@ -36,45 +35,10 @@ class Codegen {
|
||||
|
||||
/// 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 {@link 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';
|
||||
}
|
||||
|
||||
String codegenSetupReflectionCall() {
|
||||
var count = 0;
|
||||
return importUris
|
||||
.map((_) => '${prefix}${count++}.${SETUP_METHOD_NAME}();')
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,96 +32,11 @@ class Rewriter {
|
||||
String rewrite(CompilationUnit node) {
|
||||
if (node == null) throw new ArgumentError.notNull('node');
|
||||
|
||||
var visitor = new _FindReflectionCapabilitiesVisitor(_tester);
|
||||
var visitor = new _RewriterVisitor(this);
|
||||
|
||||
node.accept(visitor);
|
||||
if (visitor.reflectionCapabilityImports.isEmpty) {
|
||||
logger.error('Failed to find ${REFLECTION_CAPABILITIES_NAME} import.');
|
||||
return _code;
|
||||
}
|
||||
if (visitor.reflectionCapabilityAssignments.isEmpty) {
|
||||
logger.error('Failed to find ${REFLECTION_CAPABILITIES_NAME} '
|
||||
'instantiation.');
|
||||
return _code;
|
||||
}
|
||||
|
||||
var compare = (AstNode a, AstNode b) => a.offset - b.offset;
|
||||
visitor.reflectionCapabilityImports.sort(compare);
|
||||
visitor.reflectionCapabilityAssignments.sort(compare);
|
||||
|
||||
var importAdded = false;
|
||||
var buf = new StringBuffer();
|
||||
var idx = visitor.reflectionCapabilityImports.fold(0,
|
||||
(int lastIdx, ImportDirective node) {
|
||||
buf.write(_code.substring(lastIdx, node.offset));
|
||||
if ('${node.prefix}' == _codegen.prefix) {
|
||||
logger.warning(
|
||||
'Found import prefix "${_codegen.prefix}" in source file.'
|
||||
' Transform may not succeed.');
|
||||
}
|
||||
if (_mirrorMode != MirrorMode.none) {
|
||||
buf.write(_importDebugReflectionCapabilities(node));
|
||||
} else {
|
||||
buf.write(_commentedNode(node));
|
||||
}
|
||||
if (!importAdded && _writeStaticInit) {
|
||||
buf.write(_codegen.codegenImport());
|
||||
importAdded = true;
|
||||
}
|
||||
return node.end;
|
||||
});
|
||||
|
||||
var setupAdded = false;
|
||||
idx = visitor.reflectionCapabilityAssignments.fold(idx,
|
||||
(int lastIdx, AssignmentExpression assignNode) {
|
||||
var node = assignNode;
|
||||
while (node.parent is ExpressionStatement) {
|
||||
node = node.parent;
|
||||
}
|
||||
buf.write(_code.substring(lastIdx, node.offset));
|
||||
switch (_mirrorMode) {
|
||||
case MirrorMode.debug:
|
||||
buf.write(node);
|
||||
break;
|
||||
case MirrorMode.verbose:
|
||||
buf.write(_instantiateVerboseReflectionCapabilities(assignNode));
|
||||
break;
|
||||
case MirrorMode.none:
|
||||
default:
|
||||
buf.write(_commentedNode(node));
|
||||
break;
|
||||
}
|
||||
if (!setupAdded && _writeStaticInit) {
|
||||
buf.write(_codegen.codegenSetupReflectionCall(
|
||||
reflectorAssignment: assignNode));
|
||||
setupAdded = true;
|
||||
}
|
||||
return node.end;
|
||||
});
|
||||
if (idx < _code.length) buf.write(_code.substring(idx));
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
String _instantiateVerboseReflectionCapabilities(
|
||||
AssignmentExpression assignNode) {
|
||||
if (assignNode.rightHandSide is! InstanceCreationExpression) {
|
||||
return '$assignNode;';
|
||||
}
|
||||
var rhs = (assignNode.rightHandSide as InstanceCreationExpression);
|
||||
return '${assignNode.leftHandSide} ${assignNode.operator} '
|
||||
'new ${rhs.constructorName}(verbose: true);';
|
||||
}
|
||||
|
||||
String _importDebugReflectionCapabilities(ImportDirective node) {
|
||||
var uri = '${node.uri}';
|
||||
uri = path
|
||||
.join(path.dirname(uri), 'debug_${path.basename(uri)}')
|
||||
.replaceAll('\\', '/');
|
||||
var asClause = node.prefix != null ? ' as ${node.prefix}' : '';
|
||||
return 'import $uri$asClause;';
|
||||
}
|
||||
|
||||
String _commentedNode(AstNode node) {
|
||||
return '/*${_code.substring(node.offset, node.end)}*/';
|
||||
return visitor.outputRewrittenCode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,18 +45,31 @@ class Rewriter {
|
||||
///
|
||||
/// This breaks our dependency on dart:mirrors, which enables smaller code
|
||||
/// size and better performance.
|
||||
class _FindReflectionCapabilitiesVisitor extends Object
|
||||
class _RewriterVisitor extends Object
|
||||
with RecursiveAstVisitor<Object> {
|
||||
final reflectionCapabilityImports = new List<ImportDirective>();
|
||||
final reflectionCapabilityAssignments = new List<AssignmentExpression>();
|
||||
final AstTester _tester;
|
||||
final Rewriter _rewriter;
|
||||
final buf = new StringBuffer();
|
||||
final reflectionCapabilityAssignments = [];
|
||||
|
||||
_FindReflectionCapabilitiesVisitor(this._tester);
|
||||
int _currentIndex = 0;
|
||||
bool _setupAdded = false;
|
||||
bool _importAdded = false;
|
||||
|
||||
_RewriterVisitor(this._rewriter);
|
||||
|
||||
@override
|
||||
Object visitImportDirective(ImportDirective node) {
|
||||
if (_tester.isReflectionCapabilitiesImport(node)) {
|
||||
reflectionCapabilityImports.add(node);
|
||||
buf.write(_rewriter._code.substring(_currentIndex, node.offset));
|
||||
_currentIndex = node.offset;
|
||||
if (_rewriter._tester.isReflectionCapabilitiesImport(node)) {
|
||||
_rewriteReflectionCapabilitiesImport(node);
|
||||
} else if (_rewriter._tester.isBootstrapImport(node)) {
|
||||
_rewriteBootstrapImportToStatic(node);
|
||||
}
|
||||
if (!_importAdded && _rewriter._writeStaticInit) {
|
||||
// Add imports for ng_deps (once)
|
||||
buf.write(_rewriter._codegen.codegenImport());
|
||||
_importAdded = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -149,19 +77,130 @@ class _FindReflectionCapabilitiesVisitor extends Object
|
||||
@override
|
||||
Object visitAssignmentExpression(AssignmentExpression node) {
|
||||
if (node.rightHandSide is InstanceCreationExpression &&
|
||||
_tester.isNewReflectionCapabilities(node.rightHandSide)) {
|
||||
_rewriter._tester.isNewReflectionCapabilities(node.rightHandSide)) {
|
||||
reflectionCapabilityAssignments.add(node);
|
||||
_rewriteReflectionCapabilitiesAssignment(node);
|
||||
}
|
||||
return super.visitAssignmentExpression(node);
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitInstanceCreationExpression(InstanceCreationExpression node) {
|
||||
if (_tester.isNewReflectionCapabilities(node) &&
|
||||
if (_rewriter._tester.isNewReflectionCapabilities(node) &&
|
||||
!reflectionCapabilityAssignments.contains(node.parent)) {
|
||||
logger.error('Unexpected format in creation of '
|
||||
'${REFLECTION_CAPABILITIES_NAME}');
|
||||
}
|
||||
return super.visitInstanceCreationExpression(node);
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitMethodInvocation(MethodInvocation node) {
|
||||
if (node.methodName.toString() == BOOTSTRAP_NAME) {
|
||||
_rewriteBootstrapCallToStatic(node);
|
||||
}
|
||||
return super.visitMethodInvocation(node);
|
||||
}
|
||||
|
||||
String outputRewrittenCode() {
|
||||
if (_currentIndex < _rewriter._code.length) {
|
||||
buf.write(_rewriter._code.substring(_currentIndex));
|
||||
}
|
||||
return '$buf';
|
||||
}
|
||||
|
||||
_rewriteBootstrapImportToStatic(ImportDirective node) {
|
||||
if (_rewriter._writeStaticInit) {
|
||||
// rewrite `bootstrap.dart` to `bootstrap_static.dart`
|
||||
buf.write(_rewriter._code.substring(_currentIndex, node.offset));
|
||||
// TODO(yjbanov): handle import "..." show/hide ...
|
||||
buf.write("import 'package:angular2/bootstrap_static.dart';");
|
||||
} else {
|
||||
// leave it as is
|
||||
buf.write(_rewriter._code.substring(_currentIndex, node.end));
|
||||
}
|
||||
_currentIndex = node.end;
|
||||
}
|
||||
|
||||
_rewriteBootstrapCallToStatic(MethodInvocation node) {
|
||||
if (_rewriter._writeStaticInit) {
|
||||
buf.write(_rewriter._code.substring(_currentIndex, node.offset));
|
||||
_writeStaticReflectorInitOnce();
|
||||
// rewrite `bootstrap(...)` to `bootstrapStatic(...)`
|
||||
buf.write('bootstrapStatic${node.argumentList}');
|
||||
} else {
|
||||
// leave it as is
|
||||
buf.write(_rewriter._code.substring(_currentIndex, node.end));
|
||||
}
|
||||
_currentIndex = node.end;
|
||||
}
|
||||
|
||||
_writeStaticReflectorInitOnce() {
|
||||
if (!_setupAdded) {
|
||||
buf.write(_rewriter._codegen.codegenSetupReflectionCall());
|
||||
_setupAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
_rewriteReflectionCapabilitiesImport(ImportDirective node) {
|
||||
buf.write(_rewriter._code.substring(_currentIndex, node.offset));
|
||||
if ('${node.prefix}' == _rewriter._codegen.prefix) {
|
||||
logger.warning(
|
||||
'Found import prefix "${_rewriter._codegen.prefix}" in source file.'
|
||||
' Transform may not succeed.');
|
||||
}
|
||||
if (_rewriter._mirrorMode != MirrorMode.none) {
|
||||
buf.write(_importDebugReflectionCapabilities(node));
|
||||
} else {
|
||||
buf.write(_commentedNode(node));
|
||||
}
|
||||
_currentIndex = node.end;
|
||||
}
|
||||
|
||||
_rewriteReflectionCapabilitiesAssignment(AssignmentExpression assignNode) {
|
||||
var node = assignNode;
|
||||
while (node.parent is ExpressionStatement) {
|
||||
node = node.parent;
|
||||
}
|
||||
buf.write(_rewriter._code.substring(_currentIndex, node.offset));
|
||||
if (_rewriter._writeStaticInit) {
|
||||
_writeStaticReflectorInitOnce();
|
||||
}
|
||||
switch (_rewriter._mirrorMode) {
|
||||
case MirrorMode.debug:
|
||||
buf.write(node);
|
||||
break;
|
||||
case MirrorMode.verbose:
|
||||
buf.write(_instantiateVerboseReflectionCapabilities(assignNode));
|
||||
break;
|
||||
case MirrorMode.none:
|
||||
default:
|
||||
buf.write(_commentedNode(node));
|
||||
break;
|
||||
}
|
||||
_currentIndex = node.end;
|
||||
}
|
||||
|
||||
String _commentedNode(AstNode node) {
|
||||
return '/*${_rewriter._code.substring(node.offset, node.end)}*/';
|
||||
}
|
||||
}
|
||||
|
||||
String _importDebugReflectionCapabilities(ImportDirective node) {
|
||||
var uri = '${node.uri}';
|
||||
uri = path
|
||||
.join(path.dirname(uri), 'debug_${path.basename(uri)}')
|
||||
.replaceAll('\\', '/');
|
||||
var asClause = node.prefix != null ? ' as ${node.prefix}' : '';
|
||||
return 'import $uri$asClause;';
|
||||
}
|
||||
|
||||
String _instantiateVerboseReflectionCapabilities(
|
||||
AssignmentExpression assignNode) {
|
||||
if (assignNode.rightHandSide is! InstanceCreationExpression) {
|
||||
return '$assignNode;';
|
||||
}
|
||||
var rhs = (assignNode.rightHandSide as InstanceCreationExpression);
|
||||
return '${assignNode.leftHandSide} ${assignNode.operator} '
|
||||
'new ${rhs.constructorName}(verbose: true);';
|
||||
}
|
||||
|
||||
@@ -40,13 +40,13 @@ main() {
|
||||
const indexCommonContents = '''
|
||||
library examples.src.hello_world.index_common;
|
||||
|
||||
import "package:angular2/angular2.dart"
|
||||
show bootstrap, Component, Decorator, Template, NgElement;
|
||||
import "package:angular2/bootstrap.dart"
|
||||
show bootstrap, Component, Directive, View, ElementRef;
|
||||
import "package:angular2/di.dart" show Injectable;
|
||||
|
||||
@Component(selector: "hello-app", services: const [GreetingService])
|
||||
@Template(
|
||||
inline: '<div class="greeting">{{greeting}} <span red>world</span>!</div>'
|
||||
@View(
|
||||
template: '<div class="greeting">{{greeting}} <span red>world</span>!</div>'
|
||||
'<button class="changeButton" (click)="changeGreeting()">'
|
||||
'change greeting</button><ng-content></ng-content>',
|
||||
directives: const [RedDec])
|
||||
@@ -60,10 +60,10 @@ class HelloCmp {
|
||||
}
|
||||
}
|
||||
|
||||
@Decorator(selector: "[red]")
|
||||
@Directive(selector: "[red]")
|
||||
class RedDec {
|
||||
RedDec(NgElement el) {
|
||||
el.domElement.style.color = "red";
|
||||
RedDec(ElementRef el) {
|
||||
el.nativeElement.style.color = "red";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ Future runBenchmark() async {
|
||||
const indexContents = '''
|
||||
library web_foo;
|
||||
|
||||
import 'package:angular2/src/core/application.dart';
|
||||
import 'package:angular2/bootstrap.dart';
|
||||
import 'package:angular2/src/reflection/reflection.dart';
|
||||
import 'package:angular2/src/reflection/reflection_capabilities.dart';
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
xit,
|
||||
} from 'angular2/test_lib';
|
||||
|
||||
import {bootstrap} from 'angular2/core';
|
||||
import {bootstrap} from 'angular2/bootstrap';
|
||||
import {Component, Directive, View} from 'angular2/annotations';
|
||||
import {DOM} from 'angular2/src/dom/dom_adapter';
|
||||
import {bind} from 'angular2/di';
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
library web_foo.ng_deps.dart;
|
||||
|
||||
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/src/core/application.dart';
|
||||
import 'package:angular2/bootstrap_static.dart';
|
||||
import 'package:angular2/src/reflection/reflection_capabilities.dart';
|
||||
import 'bar.dart';
|
||||
import 'bar.ng_deps.dart' as i0;
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
library web_foo.ng_deps.dart;
|
||||
|
||||
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/src/core/application.dart';
|
||||
import 'package:angular2/bootstrap_static.dart';
|
||||
import 'package:angular2/src/reflection/reflection_capabilities.dart';
|
||||
import 'bar.dart';
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
library web_foo.ng_deps.dart;
|
||||
|
||||
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/src/core/application.dart';
|
||||
import 'package:angular2/bootstrap_static.dart';
|
||||
import 'package:angular2/src/reflection/reflection_capabilities.dart';
|
||||
import 'bar.dart';
|
||||
import 'bar.ng_deps.dart' as i0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
library web_foo.ng_deps.dart;
|
||||
|
||||
import 'package:angular2/src/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/src/core/application.dart';
|
||||
import 'package:angular2/bootstrap_static.dart';
|
||||
import 'package:angular2/src/reflection/reflection_capabilities.dart';
|
||||
import 'bar.dart';
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user