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:
Victor Berchet
2015-08-31 18:32:32 -07:00
parent 67b9414268
commit 8302afffb4
42 changed files with 311 additions and 842 deletions

View File

@ -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");

View File

@ -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) =>

View File

@ -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,

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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');

View File

@ -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]));
}

View File

@ -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 {}

View File

@ -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]));
}

View File

@ -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 {}

View File

@ -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(),

View File

@ -14,6 +14,6 @@ void initReflector() {
OnChangeSoupComponent,
new _ngRef.ReflectionInfo(const [
const Component(
selector: '[soup]', lifecycle: const [LifecycleEvent.OnChanges])
selector: '[soup]')
], const [], () => new OnChangeSoupComponent()));
}