refactor(LifecycleEvent): remove LifecycleEvent
fixes #3924 BREAKING CHANGE The `lifecycle` configuration for directive has been dropped. Before // Dart @Component({lifecycle: const [LifecycleEvent.OnChanges], ...}) class MyComponent implements OnChanges { void onChanges() {...} } // Typescript @Component({lifecycle: [LifecycleEvent.OnChanges], ...}) class MyComponent implements OnChanges { onChanges(): void {...} } // ES5 var MyComponent = ng. Component({lifecycle: [LifecycleEvent.OnChanges], ...}). Class({ onChanges: function() {...} }); After // Dart @Component({...}) class MyComponent implements OnChanges { void onChanges() {...} } // Typescript @Component({...}) class MyComponent implements OnChanges { onChanges(): void {...} } // ES5 var MyComponent = ng .Component({...}) .Class({ onChanges: function() { } });
This commit is contained in:
@ -61,7 +61,7 @@ class _DirectiveMetadataVisitor extends Object
|
||||
String _exportAs;
|
||||
bool _callOnDestroy;
|
||||
bool _callOnChange;
|
||||
bool _callOnCheck;
|
||||
bool _callDoCheck;
|
||||
bool _callOnInit;
|
||||
bool _callAfterContentInit;
|
||||
bool _callAfterContentChecked;
|
||||
@ -84,7 +84,7 @@ class _DirectiveMetadataVisitor extends Object
|
||||
_exportAs = null;
|
||||
_callOnDestroy = false;
|
||||
_callOnChange = false;
|
||||
_callOnCheck = false;
|
||||
_callDoCheck = false;
|
||||
_callOnInit = false;
|
||||
_callAfterContentInit = false;
|
||||
_callAfterContentChecked = false;
|
||||
@ -104,7 +104,7 @@ class _DirectiveMetadataVisitor extends Object
|
||||
exportAs: _exportAs,
|
||||
callOnDestroy: _callOnDestroy,
|
||||
callOnChanges: _callOnChange,
|
||||
callDoCheck: _callOnCheck,
|
||||
callDoCheck: _callDoCheck,
|
||||
callOnInit: _callOnInit,
|
||||
callAfterContentInit: _callAfterContentInit,
|
||||
callAfterContentChecked: _callAfterContentChecked,
|
||||
@ -170,6 +170,7 @@ class _DirectiveMetadataVisitor extends Object
|
||||
case 'host':
|
||||
_populateHost(node.expression);
|
||||
break;
|
||||
// TODO(vicb) should come from the interfaces on the class
|
||||
case 'lifecycle':
|
||||
_populateLifecycle(node.expression);
|
||||
break;
|
||||
@ -281,7 +282,7 @@ class _DirectiveMetadataVisitor extends Object
|
||||
var lifecycleEvents = l.elements.map((s) => s.toSource().split('.').last);
|
||||
_callOnDestroy = lifecycleEvents.contains("OnDestroy");
|
||||
_callOnChange = lifecycleEvents.contains("OnChanges");
|
||||
_callOnCheck = lifecycleEvents.contains("DoCheck");
|
||||
_callDoCheck = lifecycleEvents.contains("DoCheck");
|
||||
_callOnInit = lifecycleEvents.contains("OnInit");
|
||||
_callAfterContentInit = lifecycleEvents.contains("AfterContentInit");
|
||||
_callAfterContentChecked = lifecycleEvents.contains("AfterContentChecked");
|
||||
|
@ -21,7 +21,7 @@ const _ON_DESTROY_INTERFACES = const [
|
||||
const ClassDescriptor(
|
||||
'OnDestroy', 'package:angular2/src/core/compiler/interfaces.dart'),
|
||||
];
|
||||
const _ON_CHECK_INTERFACES = const [
|
||||
const _DO_CHECK_INTERFACES = const [
|
||||
const ClassDescriptor('DoCheck', 'package:angular2/angular2.dart'),
|
||||
const ClassDescriptor('DoCheck', 'package:angular2/metadata.dart'),
|
||||
const ClassDescriptor(
|
||||
@ -71,7 +71,7 @@ class InterfaceMatcher extends ClassMatcherBase {
|
||||
return new InterfaceMatcher._([]
|
||||
..addAll(_ON_CHANGE_INTERFACES)
|
||||
..addAll(_ON_DESTROY_INTERFACES)
|
||||
..addAll(_ON_CHECK_INTERFACES)
|
||||
..addAll(_DO_CHECK_INTERFACES)
|
||||
..addAll(_ON_INIT_INTERFACES)
|
||||
..addAll(_ON_AFTER_CONTENT_INIT_INTERFACES)
|
||||
..addAll(_ON_AFTER_CONTENT_CHECKED_INTERFACES)
|
||||
@ -88,8 +88,8 @@ class InterfaceMatcher extends ClassMatcherBase {
|
||||
implements(firstMatch(typeName, assetId), _ON_DESTROY_INTERFACES);
|
||||
|
||||
/// Checks if an [Identifier] implements [DoCheck].
|
||||
bool isOnCheck(Identifier typeName, AssetId assetId) =>
|
||||
implements(firstMatch(typeName, assetId), _ON_CHECK_INTERFACES);
|
||||
bool isDoCheck(Identifier typeName, AssetId assetId) =>
|
||||
implements(firstMatch(typeName, assetId), _DO_CHECK_INTERFACES);
|
||||
|
||||
/// Checks if an [Identifier] implements [OnInit].
|
||||
bool isOnInit(Identifier typeName, AssetId assetId) =>
|
||||
|
@ -298,8 +298,7 @@ class _NgDepsDeclarationsVisitor extends Object with SimpleAstVisitor<Object> {
|
||||
_factoryVisitor = new FactoryTransformVisitor(writer),
|
||||
_paramsVisitor = new ParameterTransformVisitor(writer),
|
||||
_metaVisitor = new AnnotationsTransformVisitor(
|
||||
writer, xhr, annotationMatcher, interfaceMatcher, assetId,
|
||||
inlineViews: inlineViews),
|
||||
writer, xhr, annotationMatcher, assetId, inlineViews: inlineViews),
|
||||
_annotationMatcher = annotationMatcher,
|
||||
_interfaceMatcher = interfaceMatcher,
|
||||
this.assetId = assetId,
|
||||
|
@ -3,11 +3,9 @@ library angular2.transform.directive_processor.visitors;
|
||||
import 'dart:async';
|
||||
import 'package:analyzer/analyzer.dart';
|
||||
import 'package:analyzer/src/generated/java_core.dart';
|
||||
import 'package:angular2/metadata.dart' show LifecycleEvent;
|
||||
import 'package:angular2/src/core/render/xhr.dart' show XHR;
|
||||
import 'package:angular2/src/transform/common/annotation_matcher.dart';
|
||||
import 'package:angular2/src/transform/common/async_string_writer.dart';
|
||||
import 'package:angular2/src/transform/common/interface_matcher.dart';
|
||||
import 'package:angular2/src/transform/common/logging.dart';
|
||||
import 'package:barback/barback.dart';
|
||||
|
||||
@ -214,92 +212,24 @@ class AnnotationsTransformVisitor extends ToSourceVisitor {
|
||||
final AsyncStringWriter writer;
|
||||
final XHR _xhr;
|
||||
final AnnotationMatcher _annotationMatcher;
|
||||
final InterfaceMatcher _interfaceMatcher;
|
||||
final AssetId _assetId;
|
||||
final bool _inlineViews;
|
||||
final ConstantEvaluator _evaluator = new ConstantEvaluator();
|
||||
final Set<String> _ifaceLifecycleEntries = new Set<String>();
|
||||
bool _isLifecycleWritten = false;
|
||||
bool _isProcessingView = false;
|
||||
bool _isProcessingDirective = false;
|
||||
String _ifaceLifecyclePrefix = '';
|
||||
|
||||
AnnotationsTransformVisitor(AsyncStringWriter writer, this._xhr,
|
||||
this._annotationMatcher, this._interfaceMatcher, this._assetId,
|
||||
{bool inlineViews})
|
||||
: this.writer = writer,
|
||||
this._annotationMatcher, this._assetId, {bool inlineViews})
|
||||
: writer = writer,
|
||||
_inlineViews = inlineViews,
|
||||
super(writer);
|
||||
|
||||
/// Determines if the `node` has interface-based lifecycle methods and
|
||||
/// populates `_lifecycleValue` with the appropriate values if so. If none are
|
||||
/// present, `_lifecycleValue` is not modified.
|
||||
void _populateLifecycleValue(ClassDeclaration node) {
|
||||
var populateImport = (Identifier name) {
|
||||
if (_ifaceLifecyclePrefix.isNotEmpty) return;
|
||||
var import = _interfaceMatcher.getMatchingImport(name, _assetId);
|
||||
_ifaceLifecyclePrefix =
|
||||
import != null && import.prefix != null ? '${import.prefix}.' : '';
|
||||
};
|
||||
|
||||
var namesToTest = [];
|
||||
|
||||
if (node.implementsClause != null &&
|
||||
node.implementsClause.interfaces != null &&
|
||||
node.implementsClause.interfaces.isNotEmpty) {
|
||||
namesToTest.addAll(node.implementsClause.interfaces.map((i) => i.name));
|
||||
}
|
||||
|
||||
if (node.extendsClause != null) {
|
||||
namesToTest.add(node.extendsClause.superclass.name);
|
||||
}
|
||||
|
||||
namesToTest.forEach((name) {
|
||||
if (_interfaceMatcher.isOnChange(name, _assetId)) {
|
||||
_ifaceLifecycleEntries.add('${LifecycleEvent.OnChanges}');
|
||||
populateImport(name);
|
||||
}
|
||||
if (_interfaceMatcher.isOnDestroy(name, _assetId)) {
|
||||
_ifaceLifecycleEntries.add('${LifecycleEvent.OnDestroy}');
|
||||
populateImport(name);
|
||||
}
|
||||
if (_interfaceMatcher.isOnCheck(name, _assetId)) {
|
||||
_ifaceLifecycleEntries.add('${LifecycleEvent.DoCheck}');
|
||||
populateImport(name);
|
||||
}
|
||||
if (_interfaceMatcher.isOnInit(name, _assetId)) {
|
||||
_ifaceLifecycleEntries.add('${LifecycleEvent.OnInit}');
|
||||
populateImport(name);
|
||||
}
|
||||
if (_interfaceMatcher.isAfterContentInit(name, _assetId)) {
|
||||
_ifaceLifecycleEntries.add('${LifecycleEvent.AfterContentInit}');
|
||||
populateImport(name);
|
||||
}
|
||||
if (_interfaceMatcher.isAfterContentChecked(name, _assetId)) {
|
||||
_ifaceLifecycleEntries.add('${LifecycleEvent.AfterContentChecked}');
|
||||
populateImport(name);
|
||||
}
|
||||
if (_interfaceMatcher.isAfterViewInit(name, _assetId)) {
|
||||
_ifaceLifecycleEntries.add('${LifecycleEvent.AfterViewInit}');
|
||||
populateImport(name);
|
||||
}
|
||||
if (_interfaceMatcher.isAfterViewChecked(name, _assetId)) {
|
||||
_ifaceLifecycleEntries.add('${LifecycleEvent.AfterViewChecked}');
|
||||
populateImport(name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _resetState() {
|
||||
_isLifecycleWritten = _isProcessingView = _isProcessingDirective = false;
|
||||
_ifaceLifecycleEntries.clear();
|
||||
_ifaceLifecyclePrefix = '';
|
||||
_isProcessingView = _isProcessingDirective = false;
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitClassDeclaration(ClassDeclaration node) {
|
||||
_populateLifecycleValue(node);
|
||||
|
||||
writer.print('const [');
|
||||
var size = node.metadata.length;
|
||||
for (var i = 0; i < size; ++i) {
|
||||
@ -338,28 +268,11 @@ class AnnotationsTransformVisitor extends ToSourceVisitor {
|
||||
}
|
||||
args[i].accept(this);
|
||||
}
|
||||
if (!_isLifecycleWritten && _isProcessingDirective) {
|
||||
var lifecycleValue = _getLifecycleValue();
|
||||
if (lifecycleValue.isNotEmpty) {
|
||||
writer.print(', lifecycle: $lifecycleValue');
|
||||
_isLifecycleWritten = true;
|
||||
}
|
||||
}
|
||||
writer.print(')');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String _getLifecycleValue() {
|
||||
if (_ifaceLifecycleEntries.isNotEmpty) {
|
||||
var entries = _ifaceLifecycleEntries.toList();
|
||||
entries.sort();
|
||||
return 'const [${_ifaceLifecyclePrefix}'
|
||||
'${entries.join(", ${_ifaceLifecyclePrefix}")}]';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/// These correspond to the annotation parameters.
|
||||
@override
|
||||
Object visitNamedExpression(NamedExpression node) {
|
||||
@ -375,37 +288,9 @@ class AnnotationsTransformVisitor extends ToSourceVisitor {
|
||||
var isSuccess = this._inlineView(keyString, node.expression);
|
||||
if (isSuccess) return null;
|
||||
}
|
||||
if (_isProcessingDirective && keyString == 'lifecycle') {
|
||||
var isSuccess = _populateLifecycleFromNamedExpression(node.expression);
|
||||
if (isSuccess) {
|
||||
_isLifecycleWritten = true;
|
||||
writer.print('lifecycle: ${_getLifecycleValue()}');
|
||||
return null;
|
||||
} else {
|
||||
logger.warning('Failed to parse `lifecycle` value. '
|
||||
'The following `LifecycleEvent`s may not be called: '
|
||||
'(${_ifaceLifecycleEntries.join(', ')})');
|
||||
_isLifecycleWritten = true;
|
||||
// Do not return -- we will use the default processing here, maintaining
|
||||
// the original value for `lifecycle`.
|
||||
}
|
||||
}
|
||||
return super.visitNamedExpression(node);
|
||||
}
|
||||
|
||||
/// Populates the lifecycle values from explicitly declared values.
|
||||
/// Returns whether `node` was successfully processed.
|
||||
bool _populateLifecycleFromNamedExpression(AstNode node) {
|
||||
var nodeVal = node.toSource();
|
||||
for (var evt in LifecycleEvent.values) {
|
||||
var evtStr = '$evt';
|
||||
if (nodeVal.contains(evtStr)) {
|
||||
_ifaceLifecycleEntries.add(evtStr);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Inlines the template and/or style refered to by `keyString`.
|
||||
/// Returns whether the `keyString` value was successfully processed.
|
||||
bool _inlineView(String keyString, AstNode node) {
|
||||
|
@ -2,7 +2,7 @@ library examples.hello_world.index_common_dart.ng_deps.dart;
|
||||
|
||||
import 'hello.dart';
|
||||
import 'package:angular2/angular2.dart'
|
||||
show Component, Directive, View, NgElement, LifecycleEvent, ChangeDetectionStrategy;
|
||||
show Component, Directive, View, NgElement, ChangeDetectionStrategy;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector(reflector) {
|
||||
|
@ -2,7 +2,7 @@ library examples.hello_world.index_common_dart.ng_deps.dart;
|
||||
|
||||
import 'hello.dart';
|
||||
import 'package:angular2/angular2.dart'
|
||||
show Component, Directive, View, NgElement, LifecycleEvent;
|
||||
show Component, Directive, View, NgElement;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector(reflector) {
|
||||
|
@ -2,7 +2,7 @@ library examples.hello_world.index_common_dart.ng_deps.dart;
|
||||
|
||||
import 'hello.dart';
|
||||
import 'package:angular2/angular2.dart'
|
||||
show Component, Directive, View, NgElement, LifecycleEvent;
|
||||
show Component, Directive, View, NgElement;
|
||||
|
||||
var _visited = false;
|
||||
void initReflector(reflector) {
|
||||
|
@ -104,10 +104,6 @@ void allTests() {
|
||||
_testProcessor('should not include superclasses in `interfaces`.',
|
||||
'superclass_files/soup.dart');
|
||||
|
||||
_testProcessor(
|
||||
'should populate `lifecycle` when lifecycle interfaces are present.',
|
||||
'interface_lifecycle_files/soup.dart');
|
||||
|
||||
_testProcessor('should populate multiple `lifecycle` values when necessary.',
|
||||
'multiple_interface_lifecycle_files/soup.dart');
|
||||
|
||||
|
@ -1,99 +0,0 @@
|
||||
library dinner.soup.ng_deps.dart;
|
||||
|
||||
import 'soup.dart';
|
||||
export 'soup.dart';
|
||||
import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
||||
import 'package:angular2/metadata.dart';
|
||||
|
||||
var _visited = false;
|
||||
void initReflector() {
|
||||
if (_visited) return;
|
||||
_visited = true;
|
||||
_ngRef.reflector
|
||||
..registerType(
|
||||
OnChangeSoupComponent,
|
||||
new _ngRef.ReflectionInfo(
|
||||
const [
|
||||
const Component(
|
||||
selector: '[soup]',
|
||||
lifecycle: const [LifecycleEvent.OnChanges])
|
||||
],
|
||||
const [],
|
||||
() => new OnChangeSoupComponent(),
|
||||
const [OnChanges]))
|
||||
..registerType(
|
||||
OnDestroySoupComponent,
|
||||
new _ngRef.ReflectionInfo(
|
||||
const [
|
||||
const Component(
|
||||
selector: '[soup]',
|
||||
lifecycle: const [LifecycleEvent.OnDestroy])
|
||||
],
|
||||
const [],
|
||||
() => new OnDestroySoupComponent(),
|
||||
const [OnDestroy]))
|
||||
..registerType(
|
||||
OnCheckSoupComponent,
|
||||
new _ngRef.ReflectionInfo(
|
||||
const [
|
||||
const Component(
|
||||
selector: '[soup]', lifecycle: const [LifecycleEvent.DoCheck])
|
||||
],
|
||||
const [],
|
||||
() => new OnCheckSoupComponent(),
|
||||
const [DoCheck]))
|
||||
..registerType(
|
||||
OnInitSoupComponent,
|
||||
new _ngRef.ReflectionInfo(
|
||||
const [
|
||||
const Component(
|
||||
selector: '[soup]', lifecycle: const [LifecycleEvent.OnInit])
|
||||
],
|
||||
const [],
|
||||
() => new OnInitSoupComponent(),
|
||||
const [OnInit]))
|
||||
..registerType(
|
||||
AfterContentInitSoupComponent,
|
||||
new _ngRef.ReflectionInfo(
|
||||
const [
|
||||
const Component(
|
||||
selector: '[soup]',
|
||||
lifecycle: const [LifecycleEvent.AfterContentInit])
|
||||
],
|
||||
const [],
|
||||
() => new AfterContentInitSoupComponent(),
|
||||
const [AfterContentInit]))
|
||||
..registerType(
|
||||
AfterContentCheckedSoupComponent,
|
||||
new _ngRef.ReflectionInfo(
|
||||
const [
|
||||
const Component(
|
||||
selector: '[soup]',
|
||||
lifecycle: const [LifecycleEvent.AfterContentChecked])
|
||||
],
|
||||
const [],
|
||||
() => new AfterContentCheckedSoupComponent(),
|
||||
const [AfterContentChecked]))
|
||||
..registerType(
|
||||
AfterViewInitSoupComponent,
|
||||
new _ngRef.ReflectionInfo(
|
||||
const [
|
||||
const Component(
|
||||
selector: '[soup]',
|
||||
lifecycle: const [LifecycleEvent.AfterViewInit])
|
||||
],
|
||||
const [],
|
||||
() => new AfterViewInitSoupComponent(),
|
||||
const [AfterViewInit]))
|
||||
..registerType(
|
||||
AfterViewCheckedSoupComponent,
|
||||
new _ngRef.ReflectionInfo(
|
||||
const [
|
||||
const Component(
|
||||
selector: '[soup]',
|
||||
lifecycle: const [LifecycleEvent.AfterViewChecked])
|
||||
],
|
||||
const [],
|
||||
() => new AfterViewCheckedSoupComponent(),
|
||||
const [AfterViewChecked]));
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
library dinner.soup;
|
||||
|
||||
import 'package:angular2/metadata.dart';
|
||||
|
||||
@Component(selector: '[soup]')
|
||||
class OnChangeSoupComponent implements OnChanges {}
|
||||
|
||||
@Component(selector: '[soup]')
|
||||
class OnDestroySoupComponent implements OnDestroy {}
|
||||
|
||||
@Component(selector: '[soup]')
|
||||
class OnCheckSoupComponent implements DoCheck {}
|
||||
|
||||
@Component(selector: '[soup]')
|
||||
class OnInitSoupComponent implements OnInit {}
|
||||
|
||||
@Component(selector: '[soup]')
|
||||
class AfterContentInitSoupComponent implements AfterContentInit {}
|
||||
|
||||
@Component(selector: '[soup]')
|
||||
class AfterContentCheckedSoupComponent implements AfterContentChecked {}
|
||||
|
||||
@Component(selector: '[soup]')
|
||||
class AfterViewInitSoupComponent implements AfterViewInit {}
|
||||
|
||||
@Component(selector: '[soup]')
|
||||
class AfterViewCheckedSoupComponent implements AfterViewChecked {}
|
@ -14,40 +14,9 @@ void initReflector() {
|
||||
MultiSoupComponent,
|
||||
new _ngRef.ReflectionInfo(
|
||||
const [
|
||||
const Component(
|
||||
selector: '[soup]',
|
||||
lifecycle: const [
|
||||
LifecycleEvent.OnChanges,
|
||||
LifecycleEvent.OnDestroy,
|
||||
LifecycleEvent.OnInit
|
||||
])
|
||||
const Component(selector: '[soup]')
|
||||
],
|
||||
const [],
|
||||
() => new MultiSoupComponent(),
|
||||
const [OnChanges, OnDestroy, OnInit]))
|
||||
..registerType(
|
||||
MixedSoupComponent,
|
||||
new _ngRef.ReflectionInfo(
|
||||
const [
|
||||
const Component(
|
||||
selector: '[soup]',
|
||||
lifecycle: const [
|
||||
LifecycleEvent.DoCheck,
|
||||
LifecycleEvent.OnChanges
|
||||
])
|
||||
],
|
||||
const [],
|
||||
() => new MixedSoupComponent(),
|
||||
const [OnChanges]))
|
||||
..registerType(
|
||||
MatchedSoupComponent,
|
||||
new _ngRef.ReflectionInfo(
|
||||
const [
|
||||
const Component(
|
||||
selector: '[soup]',
|
||||
lifecycle: const [LifecycleEvent.OnChanges])
|
||||
],
|
||||
const [],
|
||||
() => new MatchedSoupComponent(),
|
||||
const [OnChanges]));
|
||||
const [OnChanges, OnDestroy, OnInit]));
|
||||
}
|
||||
|
@ -4,9 +4,3 @@ import 'package:angular2/metadata.dart';
|
||||
|
||||
@Component(selector: '[soup]')
|
||||
class MultiSoupComponent implements OnChanges, OnDestroy, OnInit {}
|
||||
|
||||
@Component(selector: '[soup]', lifecycle: const [LifecycleEvent.DoCheck])
|
||||
class MixedSoupComponent implements OnChanges {}
|
||||
|
||||
@Component(selector: '[soup]', lifecycle: const [LifecycleEvent.OnChanges])
|
||||
class MatchedSoupComponent implements OnChanges {}
|
||||
|
@ -15,8 +15,7 @@ void initReflector() {
|
||||
new _ngRef.ReflectionInfo(
|
||||
const [
|
||||
const prefix.Component(
|
||||
selector: '[soup]',
|
||||
lifecycle: const [prefix.LifecycleEvent.OnChanges])
|
||||
selector: '[soup]')
|
||||
],
|
||||
const [],
|
||||
() => new OnChangeSoupComponent(),
|
||||
|
@ -14,6 +14,6 @@ void initReflector() {
|
||||
OnChangeSoupComponent,
|
||||
new _ngRef.ReflectionInfo(const [
|
||||
const Component(
|
||||
selector: '[soup]', lifecycle: const [LifecycleEvent.OnChanges])
|
||||
selector: '[soup]')
|
||||
], const [], () => new OnChangeSoupComponent()));
|
||||
}
|
||||
|
Reference in New Issue
Block a user