refactor(dart/transform): Remove unnecessary getter/setter codegen
Currently the transformer generates all getters and setters even when creating pre-generated change detectors, which remove the need for them. Generate getters and setters via the model provided by `ProtoViewDto`, which contains enough information to allow omitting unnecessary getters and setters from code output. Allow generating getters, setters, and method names which are Dart pseudo keywords. Closes #3489
This commit is contained in:
parent
ba2c077b01
commit
104302a958
|
@ -490,14 +490,11 @@ export class _ParseAST {
|
||||||
new MethodCall(receiver, id, fn, args);
|
new MethodCall(receiver, id, fn, args);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
let getter = this.reflector.getter(id);
|
|
||||||
let setter = this.reflector.setter(id);
|
|
||||||
|
|
||||||
if (isSafe) {
|
if (isSafe) {
|
||||||
if (this.optionalOperator("=")) {
|
if (this.optionalOperator("=")) {
|
||||||
this.error("The '?.' operator cannot be used in the assignment");
|
this.error("The '?.' operator cannot be used in the assignment");
|
||||||
} else {
|
} else {
|
||||||
return new SafePropertyRead(receiver, id, getter);
|
return new SafePropertyRead(receiver, id, this.reflector.getter(id));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.optionalOperator("=")) {
|
if (this.optionalOperator("=")) {
|
||||||
|
@ -506,9 +503,9 @@ export class _ParseAST {
|
||||||
}
|
}
|
||||||
|
|
||||||
let value = this.parseConditional();
|
let value = this.parseConditional();
|
||||||
return new PropertyWrite(receiver, id, setter, value);
|
return new PropertyWrite(receiver, id, this.reflector.setter(id), value);
|
||||||
} else {
|
} else {
|
||||||
return new PropertyRead(receiver, id, getter);
|
return new PropertyRead(receiver, id, this.reflector.getter(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ import {ChangeDetector, ChangeDetectorRef} from 'angular2/src/change_detection/c
|
||||||
import {QueryList} from './query_list';
|
import {QueryList} from './query_list';
|
||||||
import {reflector} from 'angular2/src/reflection/reflection';
|
import {reflector} from 'angular2/src/reflection/reflection';
|
||||||
import {RenderDirectiveMetadata} from 'angular2/src/render/api';
|
import {RenderDirectiveMetadata} from 'angular2/src/render/api';
|
||||||
|
import {EventConfig} from 'angular2/src/render/dom/util';
|
||||||
import {PipeBinding} from '../pipes/pipe_binding';
|
import {PipeBinding} from '../pipes/pipe_binding';
|
||||||
|
|
||||||
var _staticKeys;
|
var _staticKeys;
|
||||||
|
@ -303,18 +304,8 @@ function _createEventEmitterAccessors(bwv: BindingWithVisibility): EventEmitterA
|
||||||
if (!(binding instanceof DirectiveBinding)) return [];
|
if (!(binding instanceof DirectiveBinding)) return [];
|
||||||
var db = <DirectiveBinding>binding;
|
var db = <DirectiveBinding>binding;
|
||||||
return ListWrapper.map(db.eventEmitters, eventConfig => {
|
return ListWrapper.map(db.eventEmitters, eventConfig => {
|
||||||
let fieldName;
|
var parsedEvent = EventConfig.parse(eventConfig);
|
||||||
let eventName;
|
return new EventEmitterAccessor(parsedEvent.eventName, reflector.getter(parsedEvent.fieldName));
|
||||||
var colonIdx = eventConfig.indexOf(':');
|
|
||||||
if (colonIdx > -1) {
|
|
||||||
// long format: 'fieldName: eventName'
|
|
||||||
fieldName = StringWrapper.substring(eventConfig, 0, colonIdx).trim();
|
|
||||||
eventName = StringWrapper.substring(eventConfig, colonIdx + 1).trim();
|
|
||||||
} else {
|
|
||||||
// short format: 'name' when fieldName and eventName are the same
|
|
||||||
fieldName = eventName = eventConfig;
|
|
||||||
}
|
|
||||||
return new EventEmitterAccessor(eventName, reflector.getter(fieldName));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {CompileElement} from './compile_element';
|
||||||
import {CompileControl} from './compile_control';
|
import {CompileControl} from './compile_control';
|
||||||
|
|
||||||
import {RenderDirectiveMetadata} from '../../api';
|
import {RenderDirectiveMetadata} from '../../api';
|
||||||
import {dashCaseToCamelCase, camelCaseToDashCase, EVENT_TARGET_SEPARATOR} from '../util';
|
import {EventConfig, dashCaseToCamelCase, camelCaseToDashCase} from '../util';
|
||||||
import {DirectiveBuilder, ElementBinderBuilder} from '../view/proto_view_builder';
|
import {DirectiveBuilder, ElementBinderBuilder} from '../view/proto_view_builder';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -146,12 +146,9 @@ export class DirectiveParser implements CompileStep {
|
||||||
|
|
||||||
_bindDirectiveEvent(eventName, action, compileElement, directiveBinderBuilder) {
|
_bindDirectiveEvent(eventName, action, compileElement, directiveBinderBuilder) {
|
||||||
var ast = this._parser.parseAction(action, compileElement.elementDescription);
|
var ast = this._parser.parseAction(action, compileElement.elementDescription);
|
||||||
if (StringWrapper.contains(eventName, EVENT_TARGET_SEPARATOR)) {
|
var parsedEvent = EventConfig.parse(eventName);
|
||||||
var parts = eventName.split(EVENT_TARGET_SEPARATOR);
|
var targetName = parsedEvent.isLongForm ? parsedEvent.fieldName : null;
|
||||||
directiveBinderBuilder.bindEvent(parts[1], ast, parts[0]);
|
directiveBinderBuilder.bindEvent(parsedEvent.eventName, ast, targetName);
|
||||||
} else {
|
|
||||||
directiveBinderBuilder.bindEvent(eventName, ast);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_bindHostProperty(hostPropertyName, expression, compileElement, directiveBinderBuilder) {
|
_bindHostProperty(hostPropertyName, expression, compileElement, directiveBinderBuilder) {
|
||||||
|
|
|
@ -29,6 +29,27 @@ export function dashCaseToCamelCase(input: string): string {
|
||||||
(m) => { return m[1].toUpperCase(); });
|
(m) => { return m[1].toUpperCase(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class EventConfig {
|
||||||
|
constructor(public fieldName: string, public eventName: string, public isLongForm: boolean) {}
|
||||||
|
|
||||||
|
static parse(eventConfig: string): EventConfig {
|
||||||
|
var fieldName = eventConfig, eventName = eventConfig, isLongForm = false;
|
||||||
|
var separatorIdx = eventConfig.indexOf(EVENT_TARGET_SEPARATOR);
|
||||||
|
if (separatorIdx > -1) {
|
||||||
|
// long format: 'fieldName: eventName'
|
||||||
|
fieldName = StringWrapper.substring(eventConfig, 0, separatorIdx).trim();
|
||||||
|
eventName = StringWrapper.substring(eventConfig, separatorIdx + 1).trim();
|
||||||
|
isLongForm = true;
|
||||||
|
}
|
||||||
|
return new EventConfig(fieldName, eventName, isLongForm);
|
||||||
|
}
|
||||||
|
|
||||||
|
getFullName(): string {
|
||||||
|
return this.isLongForm ? `${this.fieldName}${EVENT_TARGET_SEPARATOR}${this.eventName}` :
|
||||||
|
this.eventName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Attention: This is on the hot path, so don't use closures or default values!
|
// Attention: This is on the hot path, so don't use closures or default values!
|
||||||
export function queryBoundElements(templateContent: Node, isSingleElementChild: boolean):
|
export function queryBoundElements(templateContent: Node, isSingleElementChild: boolean):
|
||||||
Element[] {
|
Element[] {
|
||||||
|
|
|
@ -262,7 +262,7 @@ export class DirectiveBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EventBuilder extends AstTransformer {
|
class EventBuilder extends AstTransformer {
|
||||||
locals: List<AST> = [];
|
locals: List<AST> = [];
|
||||||
localEvents: List<Event> = [];
|
localEvents: List<Event> = [];
|
||||||
globalEvents: List<Event> = [];
|
globalEvents: List<Event> = [];
|
||||||
|
|
|
@ -31,7 +31,7 @@ Future<String> createNgSettersAndGetters(
|
||||||
return '$out';
|
return '$out';
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(kegluneq): De-dupe from template_compiler/generator.dart.
|
// TODO(kegluneq): De-dupe from template_compiler/generator.dart, #3589.
|
||||||
|
|
||||||
/// Consumes the map generated by {@link _createPropertiesMap} to codegen
|
/// Consumes the map generated by {@link _createPropertiesMap} to codegen
|
||||||
/// setters.
|
/// setters.
|
||||||
|
|
|
@ -3,7 +3,10 @@ library angular2.transform.common.property_utils;
|
||||||
import 'package:analyzer/src/generated/scanner.dart' show Keyword;
|
import 'package:analyzer/src/generated/scanner.dart' show Keyword;
|
||||||
|
|
||||||
/// Whether `name` is a valid property name.
|
/// Whether `name` is a valid property name.
|
||||||
bool isValid(String name) => !Keyword.keywords.containsKey(name);
|
bool isValid(String name) {
|
||||||
|
var keyword = Keyword.keywords[name];
|
||||||
|
return keyword == null || keyword.isPseudoKeyword;
|
||||||
|
}
|
||||||
|
|
||||||
/// Prepares `name` to be emitted inside a string.
|
/// Prepares `name` to be emitted inside a string.
|
||||||
String sanitize(String name) => name.replaceAll('\$', '\\\$');
|
String sanitize(String name) => name.replaceAll('\$', '\\\$');
|
||||||
|
|
|
@ -23,8 +23,9 @@ import 'package:barback/barback.dart';
|
||||||
|
|
||||||
import 'change_detector_codegen.dart' as change;
|
import 'change_detector_codegen.dart' as change;
|
||||||
import 'compile_step_factory.dart';
|
import 'compile_step_factory.dart';
|
||||||
import 'reflection_capabilities.dart';
|
import 'reflection/codegen.dart' as reg;
|
||||||
import 'reflector_register_codegen.dart' as reg;
|
import 'reflection/processor.dart' as reg;
|
||||||
|
import 'reflection/reflection_capabilities.dart';
|
||||||
import 'view_definition_creator.dart';
|
import 'view_definition_creator.dart';
|
||||||
|
|
||||||
/// Reads the `.ng_deps.dart` file represented by `entryPoint` and parses any
|
/// Reads the `.ng_deps.dart` file represented by `entryPoint` and parses any
|
||||||
|
@ -42,23 +43,22 @@ Future<String> processTemplates(AssetReader reader, AssetId entryPoint,
|
||||||
var extractor = new _TemplateExtractor(new DomElementSchemaRegistry(),
|
var extractor = new _TemplateExtractor(new DomElementSchemaRegistry(),
|
||||||
new TemplateCloner(-1), new XhrImpl(reader, entryPoint));
|
new TemplateCloner(-1), new XhrImpl(reader, entryPoint));
|
||||||
|
|
||||||
var registrations = new reg.Codegen();
|
final processor = new reg.Processor();
|
||||||
|
|
||||||
var changeDetectorClasses = new change.Codegen();
|
var changeDetectorClasses = new change.Codegen();
|
||||||
for (var rType in viewDefResults.viewDefinitions.keys) {
|
for (var rType in viewDefResults.viewDefinitions.keys) {
|
||||||
var viewDefEntry = viewDefResults.viewDefinitions[rType];
|
var viewDefEntry = viewDefResults.viewDefinitions[rType];
|
||||||
var result = await extractor.extractTemplates(viewDefEntry.viewDef);
|
var protoView = await extractor.extractTemplates(viewDefEntry.viewDef);
|
||||||
if (result == null) continue;
|
if (protoView == null) continue;
|
||||||
|
|
||||||
if (generateRegistrations) {
|
if (generateRegistrations) {
|
||||||
// TODO(kegluneq): Generate these getters & setters based on the
|
processor.process(viewDefEntry, protoView);
|
||||||
// `ProtoViewDto` rather than querying the `ReflectionCapabilities`.
|
|
||||||
registrations.generate(result.recording);
|
|
||||||
}
|
}
|
||||||
if (result.protoView != null && generateChangeDetectors) {
|
if (generateChangeDetectors) {
|
||||||
var saved = reflector.reflectionCapabilities;
|
var saved = reflector.reflectionCapabilities;
|
||||||
reflector.reflectionCapabilities = const NullReflectionCapabilities();
|
reflector.reflectionCapabilities = const NullReflectionCapabilities();
|
||||||
var defs = getChangeDetectorDefinitions(viewDefEntry.hostMetadata,
|
var defs = getChangeDetectorDefinitions(viewDefEntry.hostMetadata,
|
||||||
result.protoView, viewDefEntry.viewDef.directives);
|
protoView, viewDefEntry.viewDef.directives);
|
||||||
for (var i = 0; i < defs.length; ++i) {
|
for (var i = 0; i < defs.length; ++i) {
|
||||||
changeDetectorClasses.generate('${rType.typeName}',
|
changeDetectorClasses.generate('${rType.typeName}',
|
||||||
'_${rType.typeName}_ChangeDetector$i', defs[i]);
|
'_${rType.typeName}_ChangeDetector$i', defs[i]);
|
||||||
|
@ -67,6 +67,10 @@ Future<String> processTemplates(AssetReader reader, AssetId entryPoint,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(kegluneq): Do not hard-code `false` here once i/3436 is fixed.
|
||||||
|
final registrations = new reg.Codegen(generateChangeDetectors: false);
|
||||||
|
registrations.generate(processor);
|
||||||
|
|
||||||
var code = viewDefResults.ngDeps.code;
|
var code = viewDefResults.ngDeps.code;
|
||||||
if (registrations.isEmpty && changeDetectorClasses.isEmpty) return code;
|
if (registrations.isEmpty && changeDetectorClasses.isEmpty) return code;
|
||||||
var importInjectIdx =
|
var importInjectIdx =
|
||||||
|
@ -93,19 +97,16 @@ class _TemplateExtractor {
|
||||||
ElementSchemaRegistry _schemaRegistry;
|
ElementSchemaRegistry _schemaRegistry;
|
||||||
TemplateCloner _templateCloner;
|
TemplateCloner _templateCloner;
|
||||||
|
|
||||||
_TemplateExtractor(ElementSchemaRegistry schemaRegistry,
|
_TemplateExtractor(this._schemaRegistry, this._templateCloner, XHR xhr)
|
||||||
TemplateCloner templateCloner, XHR xhr)
|
|
||||||
: _factory = new CompileStepFactory(new ng.Parser(new ng.Lexer())) {
|
: _factory = new CompileStepFactory(new ng.Parser(new ng.Lexer())) {
|
||||||
var urlResolver = new UrlResolver();
|
var urlResolver = new UrlResolver();
|
||||||
var styleUrlResolver = new StyleUrlResolver(urlResolver);
|
var styleUrlResolver = new StyleUrlResolver(urlResolver);
|
||||||
var styleInliner = new StyleInliner(xhr, styleUrlResolver, urlResolver);
|
var styleInliner = new StyleInliner(xhr, styleUrlResolver, urlResolver);
|
||||||
|
|
||||||
_loader = new ViewLoader(xhr, styleInliner, styleUrlResolver);
|
_loader = new ViewLoader(xhr, styleInliner, styleUrlResolver);
|
||||||
_schemaRegistry = schemaRegistry;
|
|
||||||
_templateCloner = templateCloner;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<_ExtractResult> extractTemplates(ViewDefinition viewDef) async {
|
Future<ProtoViewDto> extractTemplates(ViewDefinition viewDef) async {
|
||||||
// Check for "imperative views".
|
// Check for "imperative views".
|
||||||
if (viewDef.template == null && viewDef.templateAbsUrl == null) return null;
|
if (viewDef.template == null && viewDef.templateAbsUrl == null) return null;
|
||||||
|
|
||||||
|
@ -115,8 +116,7 @@ class _TemplateExtractor {
|
||||||
// operations between saving and restoring it, otherwise we can get into
|
// operations between saving and restoring it, otherwise we can get into
|
||||||
// a bad state. See issue #2359 for additional context.
|
// a bad state. See issue #2359 for additional context.
|
||||||
var savedReflectionCapabilities = reflector.reflectionCapabilities;
|
var savedReflectionCapabilities = reflector.reflectionCapabilities;
|
||||||
var recordingCapabilities = new RecordingReflectionCapabilities();
|
reflector.reflectionCapabilities = const NullReflectionCapabilities();
|
||||||
reflector.reflectionCapabilities = recordingCapabilities;
|
|
||||||
|
|
||||||
var pipeline = new CompilePipeline(_factory.createSteps(viewDef));
|
var pipeline = new CompilePipeline(_factory.createSteps(viewDef));
|
||||||
|
|
||||||
|
@ -130,13 +130,6 @@ class _TemplateExtractor {
|
||||||
|
|
||||||
reflector.reflectionCapabilities = savedReflectionCapabilities;
|
reflector.reflectionCapabilities = savedReflectionCapabilities;
|
||||||
|
|
||||||
return new _ExtractResult(recordingCapabilities, protoViewDto);
|
return protoViewDto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ExtractResult {
|
|
||||||
final RecordingReflectionCapabilities recording;
|
|
||||||
final ProtoViewDto protoView;
|
|
||||||
|
|
||||||
_ExtractResult(this.recording, this.protoView);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,25 +1,32 @@
|
||||||
library angular2.transform.template_compiler.reflector_register_codegen;
|
library angular2.transform.template_compiler.reflection.codegen;
|
||||||
|
|
||||||
import 'package:angular2/src/transform/common/names.dart';
|
import 'package:angular2/src/transform/common/names.dart';
|
||||||
import 'package:angular2/src/transform/common/property_utils.dart' as prop;
|
import 'package:angular2/src/transform/common/property_utils.dart' as prop;
|
||||||
import 'reflection_capabilities.dart';
|
|
||||||
|
import 'model.dart';
|
||||||
|
|
||||||
class Codegen {
|
class Codegen {
|
||||||
final StringBuffer _buf = new StringBuffer();
|
final StringBuffer _buf = new StringBuffer();
|
||||||
|
|
||||||
void generate(RecordingReflectionCapabilities recording) {
|
/// Whether we are pre-generating change detectors.
|
||||||
if (recording != null) {
|
/// If we have pre-generated change detectors, we need
|
||||||
var calls = _generateGetters(recording.getterNames);
|
final bool generateChangeDetectors;
|
||||||
|
|
||||||
|
Codegen({this.generateChangeDetectors});
|
||||||
|
|
||||||
|
void generate(CodegenModel model) {
|
||||||
|
if (model != null) {
|
||||||
|
var calls = _generateGetters(_extractNames(model.getterNames));
|
||||||
if (calls.isNotEmpty) {
|
if (calls.isNotEmpty) {
|
||||||
_buf.write('..${REGISTER_GETTERS_METHOD_NAME}'
|
_buf.write('..${REGISTER_GETTERS_METHOD_NAME}'
|
||||||
'({${calls.join(', ')}})');
|
'({${calls.join(', ')}})');
|
||||||
}
|
}
|
||||||
calls = _generateSetters(recording.setterNames);
|
calls = _generateSetters(_extractNames(model.setterNames));
|
||||||
if (calls.isNotEmpty) {
|
if (calls.isNotEmpty) {
|
||||||
_buf.write('..${REGISTER_SETTERS_METHOD_NAME}'
|
_buf.write('..${REGISTER_SETTERS_METHOD_NAME}'
|
||||||
'({${calls.join(', ')}})');
|
'({${calls.join(', ')}})');
|
||||||
}
|
}
|
||||||
calls = _generateMethods(recording.methodNames);
|
calls = _generateMethods(_extractNames(model.methodNames));
|
||||||
if (calls.isNotEmpty) {
|
if (calls.isNotEmpty) {
|
||||||
_buf.write('..${REGISTER_METHODS_METHOD_NAME}'
|
_buf.write('..${REGISTER_METHODS_METHOD_NAME}'
|
||||||
'({${calls.join(', ')}})');
|
'({${calls.join(', ')}})');
|
||||||
|
@ -27,6 +34,15 @@ class Codegen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Iterable<String> _extractNames(Iterable<ReflectiveAccessor> accessors) {
|
||||||
|
var names = accessors.where((accessor) {
|
||||||
|
return accessor.isStaticallyNecessary || !generateChangeDetectors;
|
||||||
|
}).map((accessor) => accessor.sanitizedName);
|
||||||
|
var nameList = names.toList();
|
||||||
|
nameList.sort();
|
||||||
|
return nameList;
|
||||||
|
}
|
||||||
|
|
||||||
bool get isEmpty => _buf.isEmpty;
|
bool get isEmpty => _buf.isEmpty;
|
||||||
|
|
||||||
@override
|
@override
|
|
@ -0,0 +1,49 @@
|
||||||
|
library angular2.transform.template_compiler.reflection.model;
|
||||||
|
|
||||||
|
import 'package:angular2/src/render/dom/util.dart';
|
||||||
|
|
||||||
|
/// Defines the names of getters, setters, and methods which need to be
|
||||||
|
/// available to Angular 2 via the `reflector` at runtime.
|
||||||
|
/// See [angular2.src.reflection.reflector] for details.
|
||||||
|
abstract class CodegenModel {
|
||||||
|
Iterable<ReflectiveAccessor> get getterNames;
|
||||||
|
Iterable<ReflectiveAccessor> get methodNames;
|
||||||
|
Iterable<ReflectiveAccessor> get setterNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wraps a getter, setter, or method that we may need to access reflectively in
|
||||||
|
/// an Angular2 app.
|
||||||
|
/// This is essentially a wrapper for `sanitizedName`, which is the name of the
|
||||||
|
/// actual getter, setter, or method that will be registered. Note that
|
||||||
|
/// `operator==` and `hashCode` basically forward to `sanitizedName`.
|
||||||
|
class ReflectiveAccessor {
|
||||||
|
/// The value in the Ast determining that we need this accessor. This is the
|
||||||
|
/// value that is actually present in the template, which may not directly
|
||||||
|
/// correspond to the model on the `Component`.
|
||||||
|
final String astValue;
|
||||||
|
|
||||||
|
/// The sanitized name of this accessor. This is the name of the getter,
|
||||||
|
/// setter, or method on the `Component`.
|
||||||
|
final String sanitizedName;
|
||||||
|
|
||||||
|
/// Whether this getter, setter, or method is still necessary when we have
|
||||||
|
/// pre-generated change detectors.
|
||||||
|
final bool isStaticallyNecessary;
|
||||||
|
|
||||||
|
ReflectiveAccessor(String astValue, {this.isStaticallyNecessary})
|
||||||
|
: this.astValue = astValue,
|
||||||
|
this.sanitizedName = sanitizePropertyName(astValue);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(other) {
|
||||||
|
if (other is! ReflectiveAccessor) return false;
|
||||||
|
return sanitizedName == other.sanitizedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => sanitizedName.hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
String sanitizePropertyName(String name) {
|
||||||
|
return dashCaseToCamelCase(EventConfig.parse(name).fieldName);
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
library angular2.transform.template_compiler.reflection.processor;
|
||||||
|
|
||||||
|
import 'package:angular2/src/change_detection/parser/ast.dart';
|
||||||
|
import 'package:angular2/src/render/api.dart';
|
||||||
|
import 'package:angular2/src/transform/template_compiler/view_definition_creator.dart';
|
||||||
|
|
||||||
|
import 'model.dart';
|
||||||
|
|
||||||
|
class Processor implements CodegenModel {
|
||||||
|
/// The names of all requested `getter`s.
|
||||||
|
final Set<ReflectiveAccessor> getterNames = new Set<ReflectiveAccessor>();
|
||||||
|
|
||||||
|
/// The names of all requested `setter`s.
|
||||||
|
final Set<ReflectiveAccessor> setterNames = new Set<ReflectiveAccessor>();
|
||||||
|
|
||||||
|
/// The names of all requested `method`s.
|
||||||
|
final Set<ReflectiveAccessor> methodNames = new Set<ReflectiveAccessor>();
|
||||||
|
|
||||||
|
_NgAstVisitor _visitor;
|
||||||
|
|
||||||
|
Processor() {
|
||||||
|
_visitor = new _NgAstVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void process(ViewDefinitionEntry viewDefEntry, ProtoViewDto protoViewDto) {
|
||||||
|
_processViewDefinition(viewDefEntry);
|
||||||
|
_processProtoViewDto(protoViewDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extracts the names of necessary getters from the events in host and
|
||||||
|
/// dependent [DirectiveMetadata].
|
||||||
|
void _processViewDefinition(ViewDefinitionEntry viewDefEntry) {
|
||||||
|
// These are necessary even with generated change detectors.
|
||||||
|
if (viewDefEntry.hostMetadata != null &&
|
||||||
|
viewDefEntry.hostMetadata.events != null) {
|
||||||
|
viewDefEntry.hostMetadata.events.forEach((eventName) {
|
||||||
|
getterNames.add(
|
||||||
|
new ReflectiveAccessor(eventName, isStaticallyNecessary: true));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _processProtoViewDto(ProtoViewDto protoViewDto) {
|
||||||
|
_visitor.isStaticallyNecessary = false;
|
||||||
|
|
||||||
|
protoViewDto.textBindings.forEach((ast) => ast.visit(_visitor));
|
||||||
|
protoViewDto.elementBinders.forEach((binder) {
|
||||||
|
binder.propertyBindings.forEach((binding) {
|
||||||
|
binding.astWithSource.visit(_visitor);
|
||||||
|
setterNames.add(new ReflectiveAccessor(binding.property,
|
||||||
|
isStaticallyNecessary: false));
|
||||||
|
});
|
||||||
|
|
||||||
|
binder.directives.forEach((directiveBinding) {
|
||||||
|
directiveBinding.propertyBindings.values
|
||||||
|
.forEach((propBinding) => propBinding.visit(_visitor));
|
||||||
|
directiveBinding.propertyBindings.keys.forEach((bindingName) {
|
||||||
|
setterNames.add(new ReflectiveAccessor(bindingName,
|
||||||
|
isStaticallyNecessary: false));
|
||||||
|
});
|
||||||
|
|
||||||
|
directiveBinding.hostPropertyBindings.forEach((elementBinding) {
|
||||||
|
elementBinding.astWithSource.visit(_visitor);
|
||||||
|
setterNames.add(new ReflectiveAccessor(elementBinding.property,
|
||||||
|
isStaticallyNecessary: false));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
binder.eventBindings
|
||||||
|
.forEach((eventBinding) => eventBinding.source.visit(_visitor));
|
||||||
|
|
||||||
|
binder.directives.forEach((directiveBinding) {
|
||||||
|
directiveBinding.eventBindings
|
||||||
|
.forEach((eventBinding) => eventBinding.source.visit(_visitor));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (binder.nestedProtoView != null) {
|
||||||
|
_processProtoViewDto(binder.nestedProtoView);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NgAstVisitor extends RecursiveAstVisitor {
|
||||||
|
final Processor _result;
|
||||||
|
|
||||||
|
/// Whether any getters or setters recorded are necessary when running
|
||||||
|
/// statically. A getter or setter that is necessary only for change detection
|
||||||
|
/// is not necessary when running statically because all accesses are handled
|
||||||
|
/// by the dedicated change detector classes.
|
||||||
|
bool isStaticallyNecessary = false;
|
||||||
|
|
||||||
|
_NgAstVisitor(this._result);
|
||||||
|
|
||||||
|
visitMethodCall(MethodCall ast) {
|
||||||
|
_result.methodNames
|
||||||
|
.add(new ReflectiveAccessor(ast.name, isStaticallyNecessary: true));
|
||||||
|
super.visitMethodCall(ast);
|
||||||
|
}
|
||||||
|
|
||||||
|
visitPropertyRead(PropertyRead ast) {
|
||||||
|
_result.getterNames.add(new ReflectiveAccessor(ast.name,
|
||||||
|
isStaticallyNecessary: isStaticallyNecessary));
|
||||||
|
super.visitPropertyRead(ast);
|
||||||
|
}
|
||||||
|
|
||||||
|
visitPropertyWrite(PropertyWrite ast) {
|
||||||
|
_result.setterNames.add(new ReflectiveAccessor(ast.name,
|
||||||
|
isStaticallyNecessary: isStaticallyNecessary));
|
||||||
|
super.visitPropertyWrite(ast);
|
||||||
|
}
|
||||||
|
|
||||||
|
visitSafeMethodCall(SafeMethodCall ast) {
|
||||||
|
_result.methodNames
|
||||||
|
.add(new ReflectiveAccessor(ast.name, isStaticallyNecessary: true));
|
||||||
|
super.visitSafeMethodCall(ast);
|
||||||
|
}
|
||||||
|
|
||||||
|
visitSafePropertyRead(SafePropertyRead ast) {
|
||||||
|
_result.getterNames.add(new ReflectiveAccessor(ast.name,
|
||||||
|
isStaticallyNecessary: isStaticallyNecessary));
|
||||||
|
super.visitSafePropertyRead(ast);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
library angular2.transform.template_compiler.reflection_capabilities;
|
library angular2.transform.template_compiler.reflection.reflection_capabilities;
|
||||||
|
|
||||||
import 'package:angular2/src/reflection/reflection_capabilities.dart';
|
import 'package:angular2/src/reflection/reflection_capabilities.dart';
|
||||||
import 'package:angular2/src/reflection/types.dart';
|
import 'package:angular2/src/reflection/types.dart';
|
||||||
|
@ -32,32 +32,3 @@ class NullReflectionCapabilities implements ReflectionCapabilities {
|
||||||
_nullGetter(Object p) => null;
|
_nullGetter(Object p) => null;
|
||||||
_nullSetter(Object p, v) => null;
|
_nullSetter(Object p, v) => null;
|
||||||
_nullMethod(Object p, List a) => null;
|
_nullMethod(Object p, List a) => null;
|
||||||
|
|
||||||
/// ReflectionCapabilities object that records requests for `getter`s,
|
|
||||||
/// `setter`s, and `method`s so these can be code generated rather than
|
|
||||||
/// reflectively accessed at runtime.
|
|
||||||
class RecordingReflectionCapabilities extends NullReflectionCapabilities {
|
|
||||||
/// The names of all requested `getter`s.
|
|
||||||
final Set<String> getterNames = new Set<String>();
|
|
||||||
|
|
||||||
/// The names of all requested `setter`s.
|
|
||||||
final Set<String> setterNames = new Set<String>();
|
|
||||||
|
|
||||||
/// The names of all requested `method`s.
|
|
||||||
final Set<String> methodNames = new Set<String>();
|
|
||||||
|
|
||||||
GetterFn getter(String name) {
|
|
||||||
getterNames.add(name);
|
|
||||||
return super.getter(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetterFn setter(String name) {
|
|
||||||
setterNames.add(name);
|
|
||||||
return super.setter(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodFn method(String name) {
|
|
||||||
methodNames.add(name);
|
|
||||||
return super.method(name);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import {EventConfig} from 'angular2/src/render/dom/util';
|
||||||
|
import {ddescribe, describe, expect, it} from 'angular2/test_lib';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe('EventConfig', () => {
|
||||||
|
describe('parse', () => {
|
||||||
|
it('should handle short form events', () => {
|
||||||
|
var eventConfig = EventConfig.parse('shortForm');
|
||||||
|
expect(eventConfig.fieldName).toEqual('shortForm');
|
||||||
|
expect(eventConfig.eventName).toEqual('shortForm');
|
||||||
|
expect(eventConfig.isLongForm).toEqual(false);
|
||||||
|
});
|
||||||
|
it('should handle long form events', () => {
|
||||||
|
var eventConfig = EventConfig.parse('fieldName: eventName');
|
||||||
|
expect(eventConfig.fieldName).toEqual('fieldName');
|
||||||
|
expect(eventConfig.eventName).toEqual('eventName');
|
||||||
|
expect(eventConfig.isLongForm).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('getFullName', () => {
|
||||||
|
it('should handle short form events', () => {
|
||||||
|
var eventConfig = new EventConfig('shortForm', 'shortForm', false);
|
||||||
|
expect(eventConfig.getFullName()).toEqual('shortForm');
|
||||||
|
});
|
||||||
|
it('should handle long form events', () => {
|
||||||
|
var eventConfig = new EventConfig('fieldName', 'eventName', true);
|
||||||
|
expect(eventConfig.getFullName()).toEqual('fieldName:eventName');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -19,8 +19,7 @@ void initReflector() {
|
||||||
const Component(selector: '[soup]'),
|
const Component(selector: '[soup]'),
|
||||||
const View(template: 'Salad: {{myNum}} is awesome')
|
const View(template: 'Salad: {{myNum}} is awesome')
|
||||||
], const [], () => new MyComponent()))
|
], const [], () => new MyComponent()))
|
||||||
..registerGetters({'myNum': (o) => o.myNum})
|
..registerGetters({'myNum': (o) => o.myNum});
|
||||||
..registerSetters({'myNum': (o, v) => o.myNum = v});
|
|
||||||
_gen.preGeneratedProtoDetectors['MyComponent_comp_0'] =
|
_gen.preGeneratedProtoDetectors['MyComponent_comp_0'] =
|
||||||
_MyComponent_ChangeDetector0.newProtoChangeDetector;
|
_MyComponent_ChangeDetector0.newProtoChangeDetector;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'package:angular2/src/transform/common/asset_reader.dart';
|
||||||
import 'package:angular2/src/transform/common/logging.dart';
|
import 'package:angular2/src/transform/common/logging.dart';
|
||||||
import 'package:angular2/src/transform/template_compiler/generator.dart';
|
import 'package:angular2/src/transform/template_compiler/generator.dart';
|
||||||
import 'package:dart_style/dart_style.dart';
|
import 'package:dart_style/dart_style.dart';
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
import 'package:guinness/guinness.dart';
|
import 'package:guinness/guinness.dart';
|
||||||
|
|
||||||
import '../common/read_file.dart';
|
import '../common/read_file.dart';
|
||||||
|
@ -31,7 +32,7 @@ void changeDetectorTests() {
|
||||||
// TODO(tbosch): This is just a temporary test that makes sure that the dart server and
|
// TODO(tbosch): This is just a temporary test that makes sure that the dart server and
|
||||||
// dart browser is in sync. Change this to "not contains notifyBinding"
|
// dart browser is in sync. Change this to "not contains notifyBinding"
|
||||||
// when https://github.com/angular/angular/issues/3019 is solved.
|
// when https://github.com/angular/angular/issues/3019 is solved.
|
||||||
it('shouldn always notifyDispatcher for template variables', () async {
|
it('should not always notifyDispatcher for template variables', () async {
|
||||||
var inputPath = 'template_compiler/ng_for_files/hello.ng_deps.dart';
|
var inputPath = 'template_compiler/ng_for_files/hello.ng_deps.dart';
|
||||||
var output = await (process(new AssetId('a', inputPath)));
|
var output = await (process(new AssetId('a', inputPath)));
|
||||||
expect(output).toContain('notifyDispatcher');
|
expect(output).toContain('notifyDispatcher');
|
||||||
|
@ -90,7 +91,7 @@ void noChangeDetectorTests() {
|
||||||
_formatThenExpectEquals(output, expected);
|
_formatThenExpectEquals(output, expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not generated duplicate getters/setters', () async {
|
it('should not generate duplicate getters/setters', () async {
|
||||||
var inputPath = 'template_compiler/duplicate_files/hello.ng_deps.dart';
|
var inputPath = 'template_compiler/duplicate_files/hello.ng_deps.dart';
|
||||||
var expected = readFile(
|
var expected = readFile(
|
||||||
'template_compiler/duplicate_files/expected/hello.ng_deps.dart');
|
'template_compiler/duplicate_files/expected/hello.ng_deps.dart');
|
||||||
|
@ -144,6 +145,15 @@ void noChangeDetectorTests() {
|
||||||
output = await process(new AssetId('a', inputPath));
|
output = await process(new AssetId('a', inputPath));
|
||||||
_formatThenExpectEquals(output, expected);
|
_formatThenExpectEquals(output, expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should generate all expected getters, setters, & methods.', () async {
|
||||||
|
var base = 'template_compiler/registrations_files';
|
||||||
|
var inputPath = path.join(base, 'registrations.ng_deps.dart');
|
||||||
|
var expected =
|
||||||
|
readFile(path.join(base, 'expected/registrations.ng_deps.dart'));
|
||||||
|
var output = await process(new AssetId('a', inputPath));
|
||||||
|
_formatThenExpectEquals(output, expected);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _formatThenExpectEquals(String actual, String expected) {
|
void _formatThenExpectEquals(String actual, String expected) {
|
||||||
|
|
|
@ -17,6 +17,5 @@ void initReflector(reflector) {
|
||||||
], const [
|
], const [
|
||||||
const []
|
const []
|
||||||
], () => new HelloCmp()))
|
], () => new HelloCmp()))
|
||||||
..registerGetters({'greeting': (o) => o.greeting})
|
..registerGetters({'greeting': (o) => o.greeting});
|
||||||
..registerSetters({'greeting': (o, v) => o.greeting = v});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,5 @@ void initReflector(reflector) {
|
||||||
const []
|
const []
|
||||||
], () => new HelloCmp()))
|
], () => new HelloCmp()))
|
||||||
..registerGetters({'b': (o) => o.b, 'greeting': (o) => o.greeting})
|
..registerGetters({'b': (o) => o.b, 'greeting': (o) => o.greeting})
|
||||||
..registerSetters(
|
..registerSetters({'a': (o, v) => o.a = v});
|
||||||
{'b': (o, v) => o.b = v, 'greeting': (o, v) => o.greeting = v});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ void initReflector(reflector) {
|
||||||
HelloCmp,
|
HelloCmp,
|
||||||
new ReflectionInfo(const [
|
new ReflectionInfo(const [
|
||||||
const Component(selector: 'hello-app'),
|
const Component(selector: 'hello-app'),
|
||||||
const View(template: '<button (click)=\"action()\">go</button>')
|
const View(template: '<button (click)="action()">go</button>')
|
||||||
], const [
|
], const [
|
||||||
const []
|
const []
|
||||||
], () => new HelloCmp()))
|
], () => new HelloCmp()))
|
||||||
|
|
|
@ -13,7 +13,7 @@ void initReflector(reflector) {
|
||||||
HelloCmp,
|
HelloCmp,
|
||||||
new ReflectionInfo(const [
|
new ReflectionInfo(const [
|
||||||
const Component(selector: 'hello-app'),
|
const Component(selector: 'hello-app'),
|
||||||
const View(template: '<button (click)=\"action()\">go</button>')
|
const View(template: '<button (click)="action()">go</button>')
|
||||||
], const [
|
], const [
|
||||||
const []
|
const []
|
||||||
], () => new HelloCmp()));
|
], () => new HelloCmp()));
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
{
|
||||||
|
"DependencyCmp": {
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"id": "DependencyCmp",
|
||||||
|
"selector": "dependency",
|
||||||
|
"compileChildren": true,
|
||||||
|
"hostProperties": {},
|
||||||
|
"hostListeners": {},
|
||||||
|
"hostActions": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"properties": null,
|
||||||
|
"readAttributes": null,
|
||||||
|
"type": null,
|
||||||
|
"exportAs": null,
|
||||||
|
"callOnDestroy": null,
|
||||||
|
"callOnCheck": null,
|
||||||
|
"callOnInit": null,
|
||||||
|
"callOnChange": null,
|
||||||
|
"callOnAllChangesDone": null,
|
||||||
|
"events": ["dependencyEventName"],
|
||||||
|
"changeDetection": null,
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DirectiveProps": {
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"id": "DirectiveProps",
|
||||||
|
"selector": "[dir-props]",
|
||||||
|
"compileChildren": true,
|
||||||
|
"hostProperties": {"hprop": "hprop"},
|
||||||
|
"hostListeners": {},
|
||||||
|
"hostActions": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"properties": ["prop"],
|
||||||
|
"readAttributes": null,
|
||||||
|
"type": null,
|
||||||
|
"exportAs": null,
|
||||||
|
"callOnDestroy": null,
|
||||||
|
"callOnCheck": null,
|
||||||
|
"callOnInit": null,
|
||||||
|
"callOnChange": null,
|
||||||
|
"callOnAllChangesDone": null,
|
||||||
|
"events": null,
|
||||||
|
"changeDetection": null,
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DirectiveEvents": {
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"id": "DirectiveEvents",
|
||||||
|
"selector": "[dir-events]",
|
||||||
|
"compileChildren": true,
|
||||||
|
"hostProperties": {},
|
||||||
|
"hostListeners": {"subevent": "doAThing()"},
|
||||||
|
"hostActions": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"properties": [],
|
||||||
|
"readAttributes": null,
|
||||||
|
"type": null,
|
||||||
|
"exportAs": null,
|
||||||
|
"callOnDestroy": null,
|
||||||
|
"callOnCheck": null,
|
||||||
|
"callOnInit": null,
|
||||||
|
"callOnChange": null,
|
||||||
|
"callOnAllChangesDone": null,
|
||||||
|
"events": null,
|
||||||
|
"changeDetection": null,
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NgFor": {
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"id": "NgFor",
|
||||||
|
"selector": "[ng-for][ng-for-of]",
|
||||||
|
"compileChildren": true,
|
||||||
|
"hostProperties": {},
|
||||||
|
"hostListeners": {},
|
||||||
|
"hostActions": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"properties": ["ngForOf"],
|
||||||
|
"readAttributes": null,
|
||||||
|
"type": null,
|
||||||
|
"exportAs": null,
|
||||||
|
"callOnDestroy": null,
|
||||||
|
"callOnCheck": true,
|
||||||
|
"callOnInit": null,
|
||||||
|
"callOnChange": null,
|
||||||
|
"callOnAllChangesDone": null,
|
||||||
|
"events": null,
|
||||||
|
"changeDetection": null,
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
library examples.hello_world.index_common_dart.ng_deps.dart;
|
||||||
|
|
||||||
|
import 'dependency.dart';
|
||||||
|
import 'dependency.ng_deps.dart' as i0;
|
||||||
|
import 'hello.dart';
|
||||||
|
import 'package:angular2/angular2.dart'
|
||||||
|
show Component, Directive, View, NgElement;
|
||||||
|
|
||||||
|
var _visited = false;
|
||||||
|
void initReflector(reflector) {
|
||||||
|
if (_visited) return;
|
||||||
|
_visited = true;
|
||||||
|
reflector
|
||||||
|
..registerType(
|
||||||
|
TextBindingsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'text'),
|
||||||
|
const View(template: '{{textBindings}}')
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new TextBindingsCmp()))
|
||||||
|
..registerType(
|
||||||
|
PropertyBindingsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'props'),
|
||||||
|
const View(template: '<div [prop-name]="propValue"></div>')
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new PropertyBindingsCmp()))
|
||||||
|
..registerType(
|
||||||
|
EventsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'events', events: const ['eventName']),
|
||||||
|
const View(template: 'Hi')
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new EventsCmp()))
|
||||||
|
..registerType(
|
||||||
|
SubEventsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'sub-events'),
|
||||||
|
const View(
|
||||||
|
template: '<dependency></dependency>',
|
||||||
|
directives: const [DependencyCmp])
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new SubEventsCmp()))
|
||||||
|
..registerType(
|
||||||
|
TemplateEventsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'template-events'),
|
||||||
|
const View(template: '<div (mouseover)="onMouseOver()"></div>')
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new TemplateEventsCmp()))
|
||||||
|
..registerType(
|
||||||
|
DirectivePropsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'directive-props-cmp'),
|
||||||
|
const View(
|
||||||
|
template: '<div dir-props prop="somevalue">',
|
||||||
|
directives: const [DirectiveProps])
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new DirectivePropsCmp()))
|
||||||
|
..registerType(
|
||||||
|
DirectiveEventsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'directive-events-cmp'),
|
||||||
|
const View(
|
||||||
|
template: '<div dir-events (subevent)="field = 10;">',
|
||||||
|
directives: const [DirectiveEvents])
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new DirectiveEventsCmp()))
|
||||||
|
..registerType(
|
||||||
|
RecursiveCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'recursive-cmp'),
|
||||||
|
const View(
|
||||||
|
template:
|
||||||
|
'<li *ng-for="#thing of things" [recursive-prop]="thing"><div>test</div></li>',
|
||||||
|
directives: const [NgFor])
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new RecursiveCmp()))
|
||||||
|
..registerGetters({
|
||||||
|
'eventName': (o) => o.eventName,
|
||||||
|
'hprop': (o) => o.hprop,
|
||||||
|
'propValue': (o) => o.propValue,
|
||||||
|
'textBindings': (o) => o.textBindings,
|
||||||
|
'thing': (o) => o.thing,
|
||||||
|
'things': (o) => o.things
|
||||||
|
})
|
||||||
|
..registerSetters({
|
||||||
|
'field': (o, v) => o.field = v,
|
||||||
|
'hprop': (o, v) => o.hprop = v,
|
||||||
|
'ngForOf': (o, v) => o.ngForOf = v,
|
||||||
|
'prop': (o, v) => o.prop = v,
|
||||||
|
'propName': (o, v) => o.propName = v,
|
||||||
|
'recursiveProp': (o, v) => o.recursiveProp = v
|
||||||
|
})
|
||||||
|
..registerMethods({
|
||||||
|
'doAThing': (o, List args) => Function.apply(o.doAThing, args),
|
||||||
|
'onMouseOver': (o, List args) => Function.apply(o.onMouseOver, args)
|
||||||
|
});
|
||||||
|
i0.initReflector();
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
library examples.hello_world.index_common_dart.ng_deps.dart;
|
||||||
|
|
||||||
|
import 'dependency.dart';
|
||||||
|
import 'dependency.ng_deps.dart' as i0;
|
||||||
|
import 'hello.dart';
|
||||||
|
import 'package:angular2/angular2.dart'
|
||||||
|
show Component, Directive, View, NgElement;
|
||||||
|
|
||||||
|
var _visited = false;
|
||||||
|
void initReflector(reflector) {
|
||||||
|
if (_visited) return;
|
||||||
|
_visited = true;
|
||||||
|
reflector
|
||||||
|
..registerType(
|
||||||
|
TextBindingsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'text'),
|
||||||
|
const View(template: '{{textBindings}}')
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new TextBindingsCmp()))
|
||||||
|
..registerType(
|
||||||
|
PropertyBindingsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'props'),
|
||||||
|
const View(template: '<div [prop-name]="propValue"></div>')
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new PropertyBindingsCmp()))
|
||||||
|
..registerType(
|
||||||
|
EventsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'events', events: const ['eventName']),
|
||||||
|
const View(template: 'Hi')
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new EventsCmp()))
|
||||||
|
..registerType(
|
||||||
|
SubEventsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'sub-events'),
|
||||||
|
const View(
|
||||||
|
template: '<dependency></dependency>',
|
||||||
|
directives: const [DependencyCmp])
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new SubEventsCmp()))
|
||||||
|
..registerType(
|
||||||
|
TemplateEventsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'template-events'),
|
||||||
|
const View(template: '<div (mouseover)="onMouseOver()"></div>')
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new TemplateEventsCmp()))
|
||||||
|
..registerType(
|
||||||
|
DirectivePropsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'directive-props-cmp'),
|
||||||
|
const View(
|
||||||
|
template: '<div dir-props prop="somevalue">',
|
||||||
|
directives: const [DirectiveProps])
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new DirectivePropsCmp()))
|
||||||
|
..registerType(
|
||||||
|
DirectiveEventsCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'directive-events-cmp'),
|
||||||
|
const View(
|
||||||
|
template: '<div dir-events (subevent)="field = 10;">',
|
||||||
|
directives: const [DirectiveEvents])
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new DirectiveEventsCmp()))
|
||||||
|
..registerType(
|
||||||
|
RecursiveCmp,
|
||||||
|
new ReflectionInfo(const [
|
||||||
|
const Component(selector: 'recursive-cmp'),
|
||||||
|
const View(
|
||||||
|
template:
|
||||||
|
'<li *ng-for="#thing of things" [recursive-prop]="thing"><div>test</div></li>',
|
||||||
|
directives: const [NgFor])
|
||||||
|
], const [
|
||||||
|
const []
|
||||||
|
], () => new RecursiveCmp()));
|
||||||
|
i0.initReflector();
|
||||||
|
}
|
|
@ -0,0 +1,194 @@
|
||||||
|
{
|
||||||
|
"TextBindingsCmp": {
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"id": "TextBindingsCmp",
|
||||||
|
"selector": "text",
|
||||||
|
"compileChildren": true,
|
||||||
|
"hostProperties": {},
|
||||||
|
"hostListeners": {},
|
||||||
|
"hostActions": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"properties": null,
|
||||||
|
"readAttributes": null,
|
||||||
|
"type": null,
|
||||||
|
"exportAs": null,
|
||||||
|
"callOnDestroy": null,
|
||||||
|
"callOnCheck": null,
|
||||||
|
"callOnInit": null,
|
||||||
|
"callOnChange": null,
|
||||||
|
"callOnAllChangesDone": null,
|
||||||
|
"events": null,
|
||||||
|
"changeDetection": null,
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PropertyBindingsCmp": {
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"id": "PropertyBindingsCmp",
|
||||||
|
"selector": "props",
|
||||||
|
"compileChildren": true,
|
||||||
|
"hostProperties": {},
|
||||||
|
"hostListeners": {},
|
||||||
|
"hostActions": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"properties": [],
|
||||||
|
"readAttributes": [],
|
||||||
|
"type": 0,
|
||||||
|
"exportAs": null,
|
||||||
|
"callOnDestroy": false,
|
||||||
|
"callOnCheck": false,
|
||||||
|
"callOnInit": false,
|
||||||
|
"callOnChange": false,
|
||||||
|
"callOnAllChangesDone": false,
|
||||||
|
"events": [],
|
||||||
|
"changeDetection": null,
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"EventsCmp": {
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"id": "EventsCmp",
|
||||||
|
"selector": "events",
|
||||||
|
"compileChildren": true,
|
||||||
|
"hostProperties": {},
|
||||||
|
"hostListeners": {},
|
||||||
|
"hostActions": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"properties": [],
|
||||||
|
"readAttributes": [],
|
||||||
|
"type": 1,
|
||||||
|
"exportAs": null,
|
||||||
|
"callOnDestroy": false,
|
||||||
|
"callOnCheck": false,
|
||||||
|
"callOnInit": false,
|
||||||
|
"callOnChange": false,
|
||||||
|
"callOnAllChangesDone": false,
|
||||||
|
"events": ["eventName"],
|
||||||
|
"changeDetection": null,
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SubEventsCmp": {
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"id": "SubEventsCmp",
|
||||||
|
"selector": "events",
|
||||||
|
"compileChildren": true,
|
||||||
|
"hostProperties": {},
|
||||||
|
"hostListeners": {},
|
||||||
|
"hostActions": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"properties": [],
|
||||||
|
"readAttributes": [],
|
||||||
|
"type": 1,
|
||||||
|
"exportAs": null,
|
||||||
|
"callOnDestroy": false,
|
||||||
|
"callOnCheck": false,
|
||||||
|
"callOnInit": false,
|
||||||
|
"callOnChange": false,
|
||||||
|
"callOnAllChangesDone": false,
|
||||||
|
"events": [],
|
||||||
|
"changeDetection": null,
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TemplateEventsCmp": {
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"id": "TemplateEventsCmp",
|
||||||
|
"selector": "template-events",
|
||||||
|
"compileChildren": true,
|
||||||
|
"hostProperties": {},
|
||||||
|
"hostListeners": {},
|
||||||
|
"hostActions": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"properties": [],
|
||||||
|
"readAttributes": [],
|
||||||
|
"type": 1,
|
||||||
|
"exportAs": null,
|
||||||
|
"callOnDestroy": false,
|
||||||
|
"callOnCheck": false,
|
||||||
|
"callOnInit": false,
|
||||||
|
"callOnChange": false,
|
||||||
|
"callOnAllChangesDone": false,
|
||||||
|
"events": [],
|
||||||
|
"changeDetection": null,
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DirectivePropsCmp": {
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"id": "DirectivePropsCmp",
|
||||||
|
"selector": "directive-props-cmp",
|
||||||
|
"compileChildren": true,
|
||||||
|
"hostProperties": {},
|
||||||
|
"hostListeners": {},
|
||||||
|
"hostActions": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"properties": [],
|
||||||
|
"readAttributes": [],
|
||||||
|
"type": 1,
|
||||||
|
"exportAs": null,
|
||||||
|
"callOnDestroy": false,
|
||||||
|
"callOnCheck": false,
|
||||||
|
"callOnInit": false,
|
||||||
|
"callOnChange": false,
|
||||||
|
"callOnAllChangesDone": false,
|
||||||
|
"events": [],
|
||||||
|
"changeDetection": null,
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DirectiveEventsCmp": {
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"id": "DirectiveEventsCmp",
|
||||||
|
"selector": "directive-events-cmp",
|
||||||
|
"compileChildren": true,
|
||||||
|
"hostProperties": {},
|
||||||
|
"hostListeners": {},
|
||||||
|
"hostActions": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"properties": [],
|
||||||
|
"readAttributes": [],
|
||||||
|
"type": 1,
|
||||||
|
"exportAs": null,
|
||||||
|
"callOnDestroy": false,
|
||||||
|
"callOnCheck": false,
|
||||||
|
"callOnInit": false,
|
||||||
|
"callOnChange": false,
|
||||||
|
"callOnAllChangesDone": false,
|
||||||
|
"events": [],
|
||||||
|
"changeDetection": null,
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"RecursiveCmp": {
|
||||||
|
"kind": "type",
|
||||||
|
"value": {
|
||||||
|
"id": "RecursiveCmp",
|
||||||
|
"selector": "recursive-cmp",
|
||||||
|
"compileChildren": true,
|
||||||
|
"hostProperties": {},
|
||||||
|
"hostListeners": {},
|
||||||
|
"hostActions": {},
|
||||||
|
"hostAttributes": {},
|
||||||
|
"properties": [],
|
||||||
|
"readAttributes": [],
|
||||||
|
"type": 1,
|
||||||
|
"exportAs": null,
|
||||||
|
"callOnDestroy": false,
|
||||||
|
"callOnCheck": false,
|
||||||
|
"callOnInit": false,
|
||||||
|
"callOnChange": false,
|
||||||
|
"callOnAllChangesDone": false,
|
||||||
|
"events": [],
|
||||||
|
"changeDetection": null,
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,5 @@ void initReflector(reflector) {
|
||||||
], const [
|
], const [
|
||||||
const []
|
const []
|
||||||
], () => new HelloCmp()))
|
], () => new HelloCmp()))
|
||||||
..registerGetters({'greeting': (o) => o.greeting})
|
..registerGetters({'greeting': (o) => o.greeting});
|
||||||
..registerSetters({'greeting': (o, v) => o.greeting = v});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,5 @@ void initReflector(reflector) {
|
||||||
], const [
|
], const [
|
||||||
const []
|
const []
|
||||||
], () => new GoodbyeCmp()))
|
], () => new GoodbyeCmp()))
|
||||||
..registerGetters({'name': (o) => o.name})
|
..registerGetters({'name': (o) => o.name});
|
||||||
..registerSetters({'name': (o, v) => o.name = v});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,5 @@ void initReflector(reflector) {
|
||||||
], const [
|
], const [
|
||||||
const []
|
const []
|
||||||
], () => new MyApp()))
|
], () => new MyApp()))
|
||||||
..registerGetters({'name': (o) => o.name})
|
..registerGetters({'name': (o) => o.name});
|
||||||
..registerSetters({'name': (o, v) => o.name = v});
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue