feat(transformers): collect data needed for the template compiler
Closes #7299
This commit is contained in:
parent
1779caf5f8
commit
ebe531bf92
|
@ -2,8 +2,10 @@ import {
|
|||
isPresent,
|
||||
isBlank,
|
||||
normalizeBool,
|
||||
normalizeBlank,
|
||||
serializeEnum,
|
||||
Type,
|
||||
isString,
|
||||
RegExpWrapper,
|
||||
StringWrapper
|
||||
} from 'angular2/src/facade/lang';
|
||||
|
@ -22,7 +24,17 @@ import {LifecycleHooks, LIFECYCLE_HOOKS_VALUES} from 'angular2/src/core/linker/i
|
|||
// group 2: "event" from "(event)"
|
||||
var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
|
||||
|
||||
export abstract class CompileMetadataWithType {
|
||||
export abstract class CompileMetadataWithIdentifier {
|
||||
static fromJson(data: {[key: string]: any}): CompileMetadataWithIdentifier {
|
||||
return _COMPILE_METADATA_FROM_JSON[data['class']](data);
|
||||
}
|
||||
|
||||
abstract toJson(): {[key: string]: any};
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return unimplemented(); }
|
||||
}
|
||||
|
||||
export abstract class CompileMetadataWithType extends CompileMetadataWithIdentifier {
|
||||
static fromJson(data: {[key: string]: any}): CompileMetadataWithType {
|
||||
return _COMPILE_METADATA_FROM_JSON[data['class']](data);
|
||||
}
|
||||
|
@ -30,37 +42,241 @@ export abstract class CompileMetadataWithType {
|
|||
abstract toJson(): {[key: string]: any};
|
||||
|
||||
get type(): CompileTypeMetadata { return unimplemented(); }
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return unimplemented(); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Metadata regarding compilation of a type.
|
||||
*/
|
||||
export class CompileTypeMetadata {
|
||||
runtime: Type;
|
||||
export class CompileIdentifierMetadata implements CompileMetadataWithIdentifier {
|
||||
runtime: any;
|
||||
name: string;
|
||||
prefix: string;
|
||||
moduleUrl: string;
|
||||
isHost: boolean;
|
||||
constructor({runtime, name, moduleUrl, isHost}:
|
||||
{runtime?: Type, name?: string, moduleUrl?: string, isHost?: boolean} = {}) {
|
||||
constConstructor: boolean;
|
||||
constructor({runtime, name, moduleUrl, prefix, constConstructor}: {
|
||||
runtime?: any,
|
||||
name?: string,
|
||||
moduleUrl?: string,
|
||||
prefix?: string,
|
||||
constConstructor?: boolean
|
||||
} = {}) {
|
||||
this.runtime = runtime;
|
||||
this.name = name;
|
||||
this.prefix = prefix;
|
||||
this.moduleUrl = moduleUrl;
|
||||
this.isHost = normalizeBool(isHost);
|
||||
this.constConstructor = constConstructor;
|
||||
}
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileTypeMetadata {
|
||||
return new CompileTypeMetadata(
|
||||
{name: data['name'], moduleUrl: data['moduleUrl'], isHost: data['isHost']});
|
||||
static fromJson(data: {[key: string]: any}): CompileIdentifierMetadata {
|
||||
return new CompileIdentifierMetadata({
|
||||
name: data['name'],
|
||||
prefix: data['prefix'],
|
||||
moduleUrl: data['moduleUrl'],
|
||||
constConstructor: data['constConstructor']
|
||||
});
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
// Note: Runtime type can't be serialized...
|
||||
'class': 'Identifier',
|
||||
'name': this.name,
|
||||
'moduleUrl': this.moduleUrl,
|
||||
'isHost': this.isHost
|
||||
'prefix': this.prefix,
|
||||
'constConstructor': this.constConstructor
|
||||
};
|
||||
}
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return this; }
|
||||
}
|
||||
|
||||
export class CompileDiDependencyMetadata {
|
||||
isAttribute: boolean;
|
||||
isSelf: boolean;
|
||||
isHost: boolean;
|
||||
isSkipSelf: boolean;
|
||||
isOptional: boolean;
|
||||
query: CompileQueryMetadata;
|
||||
viewQuery: CompileQueryMetadata;
|
||||
token: CompileIdentifierMetadata | string;
|
||||
|
||||
constructor({isAttribute, isSelf, isHost, isSkipSelf, isOptional, query, viewQuery, token}: {
|
||||
isAttribute?: boolean,
|
||||
isSelf?: boolean,
|
||||
isHost?: boolean,
|
||||
isSkipSelf?: boolean,
|
||||
isOptional?: boolean,
|
||||
query?: CompileQueryMetadata,
|
||||
viewQuery?: CompileQueryMetadata,
|
||||
token?: CompileIdentifierMetadata | string
|
||||
} = {}) {
|
||||
this.isAttribute = normalizeBool(isAttribute);
|
||||
this.isSelf = normalizeBool(isSelf);
|
||||
this.isHost = normalizeBool(isHost);
|
||||
this.isSkipSelf = normalizeBool(isSkipSelf);
|
||||
this.isOptional = normalizeBool(isOptional);
|
||||
this.query = query;
|
||||
this.viewQuery = viewQuery;
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileDiDependencyMetadata {
|
||||
return new CompileDiDependencyMetadata(
|
||||
{token: objFromJson(data['token'], CompileIdentifierMetadata.fromJson)});
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
// Note: Runtime type can't be serialized...
|
||||
'token': objToJson(this.token)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class CompileProviderMetadata {
|
||||
token: CompileIdentifierMetadata | string;
|
||||
useClass: CompileTypeMetadata;
|
||||
useValue: any;
|
||||
useExisting: CompileIdentifierMetadata | string;
|
||||
useFactory: CompileFactoryMetadata;
|
||||
deps: CompileDiDependencyMetadata[];
|
||||
multi: boolean;
|
||||
|
||||
constructor({token, useClass, useValue, useExisting, useFactory, deps, multi}: {
|
||||
token?: CompileIdentifierMetadata | string,
|
||||
useClass?: CompileTypeMetadata,
|
||||
useValue?: any,
|
||||
useExisting?: CompileIdentifierMetadata | string,
|
||||
useFactory?: CompileFactoryMetadata,
|
||||
deps?: CompileDiDependencyMetadata[],
|
||||
multi?: boolean
|
||||
}) {
|
||||
this.token = token;
|
||||
this.useClass = useClass;
|
||||
this.useValue = useValue;
|
||||
this.useExisting = useExisting;
|
||||
this.useFactory = useFactory;
|
||||
this.deps = deps;
|
||||
this.multi = multi;
|
||||
}
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileProviderMetadata {
|
||||
return new CompileProviderMetadata({
|
||||
token: objFromJson(data['token'], CompileIdentifierMetadata.fromJson),
|
||||
useClass: objFromJson(data['useClass'], CompileTypeMetadata.fromJson)
|
||||
});
|
||||
}
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
// Note: Runtime type can't be serialized...
|
||||
'token': objToJson(this.token),
|
||||
'useClass': objToJson(this.useClass)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class CompileFactoryMetadata implements CompileIdentifierMetadata {
|
||||
runtime: Function;
|
||||
name: string;
|
||||
prefix: string;
|
||||
moduleUrl: string;
|
||||
constConstructor: boolean;
|
||||
diDeps: CompileDiDependencyMetadata[];
|
||||
|
||||
constructor({runtime, name, moduleUrl, constConstructor, diDeps}: {
|
||||
runtime?: Function,
|
||||
name?: string,
|
||||
moduleUrl?: string,
|
||||
constConstructor?: boolean,
|
||||
diDeps?: CompileDiDependencyMetadata[]
|
||||
}) {
|
||||
this.runtime = runtime;
|
||||
this.name = name;
|
||||
this.moduleUrl = moduleUrl;
|
||||
this.diDeps = diDeps;
|
||||
this.constConstructor = constConstructor;
|
||||
}
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return this; }
|
||||
|
||||
toJson() { return null; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Metadata regarding compilation of a type.
|
||||
*/
|
||||
export class CompileTypeMetadata implements CompileIdentifierMetadata, CompileMetadataWithType {
|
||||
runtime: Type;
|
||||
name: string;
|
||||
prefix: string;
|
||||
moduleUrl: string;
|
||||
isHost: boolean;
|
||||
constConstructor: boolean;
|
||||
diDeps: CompileDiDependencyMetadata[];
|
||||
|
||||
constructor({runtime, name, moduleUrl, prefix, isHost, constConstructor, diDeps}: {
|
||||
runtime?: Type,
|
||||
name?: string,
|
||||
moduleUrl?: string,
|
||||
prefix?: string,
|
||||
isHost?: boolean,
|
||||
constConstructor?: boolean,
|
||||
diDeps?: CompileDiDependencyMetadata[]
|
||||
} = {}) {
|
||||
this.runtime = runtime;
|
||||
this.name = name;
|
||||
this.moduleUrl = moduleUrl;
|
||||
this.prefix = prefix;
|
||||
this.isHost = normalizeBool(isHost);
|
||||
this.constConstructor = constConstructor;
|
||||
this.diDeps = normalizeBlank(diDeps);
|
||||
}
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileTypeMetadata {
|
||||
return new CompileTypeMetadata({
|
||||
name: data['name'],
|
||||
moduleUrl: data['moduleUrl'],
|
||||
prefix: data['prefix'],
|
||||
isHost: data['isHost'],
|
||||
constConstructor: data['constConstructor'],
|
||||
diDeps: arrayFromJson(data['diDeps'], CompileDiDependencyMetadata.fromJson)
|
||||
});
|
||||
}
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return this; }
|
||||
get type(): CompileTypeMetadata { return this; }
|
||||
|
||||
toJson(): {[key: string]: any} {
|
||||
return {
|
||||
// Note: Runtime type can't be serialized...
|
||||
'class': 'Type',
|
||||
'name': this.name,
|
||||
'moduleUrl': this.moduleUrl,
|
||||
'prefix': this.prefix,
|
||||
'isHost': this.isHost,
|
||||
'constConstructor': this.constConstructor,
|
||||
'diDeps': arrayToJson(this.diDeps)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class CompileQueryMetadata {
|
||||
selectors: Array<CompileIdentifierMetadata | string>;
|
||||
descendants: boolean;
|
||||
first: boolean;
|
||||
propertyName: string;
|
||||
|
||||
constructor({selectors, descendants, first, propertyName}: {
|
||||
selectors?: Array<CompileIdentifierMetadata | string>,
|
||||
descendants?: boolean,
|
||||
first?: boolean,
|
||||
propertyName?: string
|
||||
} = {}) {
|
||||
this.selectors = selectors;
|
||||
this.descendants = descendants;
|
||||
this.first = first;
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,7 +336,8 @@ export class CompileTemplateMetadata {
|
|||
*/
|
||||
export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
||||
static create({type, isComponent, dynamicLoadable, selector, exportAs, changeDetection, inputs,
|
||||
outputs, host, lifecycleHooks, template}: {
|
||||
outputs, host, lifecycleHooks, providers, viewProviders, queries, viewQueries,
|
||||
template}: {
|
||||
type?: CompileTypeMetadata,
|
||||
isComponent?: boolean,
|
||||
dynamicLoadable?: boolean,
|
||||
|
@ -131,6 +348,10 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||
outputs?: string[],
|
||||
host?: {[key: string]: string},
|
||||
lifecycleHooks?: LifecycleHooks[],
|
||||
providers?: Array<CompileProviderMetadata | CompileTypeMetadata | any[]>,
|
||||
viewProviders?: Array<CompileProviderMetadata | CompileTypeMetadata | any[]>,
|
||||
queries?: CompileQueryMetadata[],
|
||||
viewQueries?: CompileQueryMetadata[],
|
||||
template?: CompileTemplateMetadata
|
||||
} = {}): CompileDirectiveMetadata {
|
||||
var hostListeners: {[key: string]: string} = {};
|
||||
|
@ -180,10 +401,13 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||
hostProperties: hostProperties,
|
||||
hostAttributes: hostAttributes,
|
||||
lifecycleHooks: isPresent(lifecycleHooks) ? lifecycleHooks : [],
|
||||
providers: providers,
|
||||
viewProviders: viewProviders,
|
||||
queries: queries,
|
||||
viewQueries: viewQueries,
|
||||
template: template
|
||||
});
|
||||
}
|
||||
|
||||
type: CompileTypeMetadata;
|
||||
isComponent: boolean;
|
||||
dynamicLoadable: boolean;
|
||||
|
@ -196,9 +420,14 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||
hostProperties: {[key: string]: string};
|
||||
hostAttributes: {[key: string]: string};
|
||||
lifecycleHooks: LifecycleHooks[];
|
||||
providers: Array<CompileProviderMetadata | CompileTypeMetadata | any[]>;
|
||||
viewProviders: Array<CompileProviderMetadata | CompileTypeMetadata | any[]>;
|
||||
queries: CompileQueryMetadata[];
|
||||
viewQueries: CompileQueryMetadata[];
|
||||
template: CompileTemplateMetadata;
|
||||
constructor({type, isComponent, dynamicLoadable, selector, exportAs, changeDetection, inputs,
|
||||
outputs, hostListeners, hostProperties, hostAttributes, lifecycleHooks, template}: {
|
||||
outputs, hostListeners, hostProperties, hostAttributes, lifecycleHooks, providers,
|
||||
viewProviders, queries, viewQueries, template}: {
|
||||
type?: CompileTypeMetadata,
|
||||
isComponent?: boolean,
|
||||
dynamicLoadable?: boolean,
|
||||
|
@ -211,6 +440,10 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||
hostProperties?: {[key: string]: string},
|
||||
hostAttributes?: {[key: string]: string},
|
||||
lifecycleHooks?: LifecycleHooks[],
|
||||
providers?: Array<CompileProviderMetadata | CompileTypeMetadata | any[]>,
|
||||
viewProviders?: Array<CompileProviderMetadata | CompileTypeMetadata | any[]>,
|
||||
queries?: CompileQueryMetadata[],
|
||||
viewQueries?: CompileQueryMetadata[],
|
||||
template?: CompileTemplateMetadata
|
||||
} = {}) {
|
||||
this.type = type;
|
||||
|
@ -225,9 +458,15 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||
this.hostProperties = hostProperties;
|
||||
this.hostAttributes = hostAttributes;
|
||||
this.lifecycleHooks = lifecycleHooks;
|
||||
this.providers = normalizeBlank(providers);
|
||||
this.viewProviders = normalizeBlank(viewProviders);
|
||||
this.queries = queries;
|
||||
this.viewQueries = viewQueries;
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
get identifier(): CompileIdentifierMetadata { return this.type; }
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompileDirectiveMetadata {
|
||||
return new CompileDirectiveMetadata({
|
||||
isComponent: data['isComponent'],
|
||||
|
@ -246,7 +485,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||
lifecycleHooks:
|
||||
(<any[]>data['lifecycleHooks']).map(hookValue => LIFECYCLE_HOOKS_VALUES[hookValue]),
|
||||
template: isPresent(data['template']) ? CompileTemplateMetadata.fromJson(data['template']) :
|
||||
data['template']
|
||||
data['template'],
|
||||
providers: arrayFromJson(data['providers'], CompileProviderMetadata.fromJson)
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -266,7 +506,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
|
|||
'hostProperties': this.hostProperties,
|
||||
'hostAttributes': this.hostAttributes,
|
||||
'lifecycleHooks': this.lifecycleHooks.map(hook => serializeEnum(hook)),
|
||||
'template': isPresent(this.template) ? this.template.toJson() : this.template
|
||||
'template': isPresent(this.template) ? this.template.toJson() : this.template,
|
||||
'providers': arrayToJson(this.providers)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -293,7 +534,11 @@ export function createHostComponentMeta(componentType: CompileTypeMetadata,
|
|||
lifecycleHooks: [],
|
||||
isComponent: true,
|
||||
dynamicLoadable: false,
|
||||
selector: '*'
|
||||
selector: '*',
|
||||
providers: [],
|
||||
viewProviders: [],
|
||||
queries: [],
|
||||
viewQueries: []
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -308,6 +553,7 @@ export class CompilePipeMetadata implements CompileMetadataWithType {
|
|||
this.name = name;
|
||||
this.pure = normalizeBool(pure);
|
||||
}
|
||||
get identifier(): CompileIdentifierMetadata { return this.type; }
|
||||
|
||||
static fromJson(data: {[key: string]: any}): CompilePipeMetadata {
|
||||
return new CompilePipeMetadata({
|
||||
|
@ -329,5 +575,23 @@ export class CompilePipeMetadata implements CompileMetadataWithType {
|
|||
|
||||
var _COMPILE_METADATA_FROM_JSON = {
|
||||
'Directive': CompileDirectiveMetadata.fromJson,
|
||||
'Pipe': CompilePipeMetadata.fromJson
|
||||
'Pipe': CompilePipeMetadata.fromJson,
|
||||
'Type': CompileTypeMetadata.fromJson,
|
||||
'Identifier': CompileIdentifierMetadata.fromJson
|
||||
};
|
||||
|
||||
function arrayFromJson(obj: any[], fn: (a: {[key: string]: any}) => any): any {
|
||||
return isBlank(obj) ? null : obj.map(fn);
|
||||
}
|
||||
|
||||
function arrayToJson(obj: any[]): string | {[key: string]: any} {
|
||||
return isBlank(obj) ? null : obj.map(o => o.toJson());
|
||||
}
|
||||
|
||||
function objFromJson(obj: any, fn: (a: {[key: string]: any}) => any): any {
|
||||
return (isString(obj) || isBlank(obj)) ? obj : fn(obj);
|
||||
}
|
||||
|
||||
function objToJson(obj: any): string | {[key: string]: any} {
|
||||
return (isString(obj) || isBlank(obj)) ? obj : obj.toJson();
|
||||
}
|
|
@ -109,6 +109,7 @@ export class TemplateCompiler {
|
|||
hostProperties: directive.hostProperties,
|
||||
hostAttributes: directive.hostAttributes,
|
||||
lifecycleHooks: directive.lifecycleHooks,
|
||||
providers: directive.providers,
|
||||
template: normalizedTemplate
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import {ChangeDetector} from './interfaces';
|
||||
import {ChangeDetectionStrategy} from './constants';
|
||||
import {Injectable} from 'angular2/src/core/di';
|
||||
|
||||
@Injectable()
|
||||
export abstract class ChangeDetectorRef {
|
||||
/**
|
||||
* Marks all {@link ChangeDetectionStrategy#OnPush} ancestors as to be checked.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {unimplemented} from 'angular2/src/facade/exceptions';
|
||||
import {Injectable} from 'angular2/src/core/di';
|
||||
import {AppElement} from './element';
|
||||
|
||||
/**
|
||||
|
@ -11,6 +12,7 @@ import {AppElement} from './element';
|
|||
* An `ElementRef` is backed by a render-specific element. In the browser, this is usually a DOM
|
||||
* element.
|
||||
*/
|
||||
@Injectable()
|
||||
export abstract class ElementRef {
|
||||
/**
|
||||
* The underlying native element or `null` if direct access to native elements is not supported
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {ElementRef, ElementRef_} from './element_ref';
|
||||
import {Injectable} from 'angular2/src/core/di';
|
||||
|
||||
/**
|
||||
* Represents an Embedded Template that can be used to instantiate Embedded Views.
|
||||
|
@ -12,6 +13,7 @@ import {ElementRef, ElementRef_} from './element_ref';
|
|||
* {@link ViewContainerRef#createEmbeddedView}, which will create the View and attach it to the
|
||||
* View Container.
|
||||
*/
|
||||
@Injectable()
|
||||
export abstract class TemplateRef {
|
||||
/**
|
||||
* The location in the View where the Embedded View logically belongs to.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {unimplemented} from 'angular2/src/facade/exceptions';
|
||||
import {ResolvedProvider} from 'angular2/src/core/di';
|
||||
import {ResolvedProvider, Injectable} from 'angular2/src/core/di';
|
||||
import {isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||
|
||||
import {AppElement} from './element';
|
||||
|
@ -36,6 +36,7 @@ import {
|
|||
*
|
||||
* <!-- TODO(i): we are also considering ElementRef#viewContainer api -->
|
||||
*/
|
||||
@Injectable()
|
||||
export abstract class ViewContainerRef {
|
||||
/**
|
||||
* Anchor element that specifies the location of this container in the containing View.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
|
||||
import {Injector} from 'angular2/src/core/di/injector';
|
||||
import {Injector, Injectable} from 'angular2/src/core/di';
|
||||
|
||||
export class RenderComponentType {
|
||||
constructor(public id: string, public encapsulation: ViewEncapsulation,
|
||||
|
@ -13,6 +13,7 @@ export class RenderDebugInfo {
|
|||
|
||||
export interface ParentRenderer { renderComponent(componentType: RenderComponentType): Renderer; }
|
||||
|
||||
@Injectable()
|
||||
export abstract class Renderer implements ParentRenderer {
|
||||
abstract renderComponent(componentType: RenderComponentType): Renderer;
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ let _resolveToFalse = PromiseWrapper.resolve(false);
|
|||
* `Instruction`.
|
||||
* The router uses the `RouteRegistry` to get an `Instruction`.
|
||||
*/
|
||||
@Injectable()
|
||||
export class Router {
|
||||
navigating: boolean = false;
|
||||
lastNavigationAttempt: string;
|
||||
|
|
|
@ -15,7 +15,8 @@ import {
|
|||
import {
|
||||
CompileDirectiveMetadata,
|
||||
CompileTypeMetadata,
|
||||
CompileTemplateMetadata
|
||||
CompileTemplateMetadata,
|
||||
CompileProviderMetadata
|
||||
} from 'angular2/src/compiler/directive_metadata';
|
||||
import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
|
||||
import {ChangeDetectionStrategy} from 'angular2/src/core/change_detection';
|
||||
|
@ -28,8 +29,8 @@ export function main() {
|
|||
var fullDirectiveMeta: CompileDirectiveMetadata;
|
||||
|
||||
beforeEach(() => {
|
||||
fullTypeMeta =
|
||||
new CompileTypeMetadata({name: 'SomeType', moduleUrl: 'someUrl', isHost: true});
|
||||
fullTypeMeta = new CompileTypeMetadata(
|
||||
{name: 'SomeType', moduleUrl: 'someUrl', isHost: true, diDeps: []});
|
||||
fullTemplateMeta = new CompileTemplateMetadata({
|
||||
encapsulation: ViewEncapsulation.Emulated,
|
||||
template: '<a></a>',
|
||||
|
@ -48,7 +49,8 @@ export function main() {
|
|||
inputs: ['someProp'],
|
||||
outputs: ['someEvent'],
|
||||
host: {'(event1)': 'handler1', '[prop1]': 'expr1', 'attr1': 'attrValue2'},
|
||||
lifecycleHooks: [LifecycleHooks.OnChanges]
|
||||
lifecycleHooks: [LifecycleHooks.OnChanges],
|
||||
providers: [new CompileProviderMetadata({token: 'token', useClass: fullTypeMeta})]
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -530,6 +530,15 @@ var NG_COMPILER = [
|
|||
"CompileDirectiveMetadata.template=",
|
||||
"CompileDirectiveMetadata.type",
|
||||
"CompileDirectiveMetadata.type=",
|
||||
"CompileDirectiveMetadata.identifier",
|
||||
"CompileDirectiveMetadata.providers",
|
||||
"CompileDirectiveMetadata.providers=",
|
||||
"CompileDirectiveMetadata.queries",
|
||||
"CompileDirectiveMetadata.queries=",
|
||||
"CompileDirectiveMetadata.viewProviders",
|
||||
"CompileDirectiveMetadata.viewProviders=",
|
||||
"CompileDirectiveMetadata.viewQueries",
|
||||
"CompileDirectiveMetadata.viewQueries=",
|
||||
"CompileTemplateMetadata.encapsulation",
|
||||
"CompileTemplateMetadata.encapsulation=",
|
||||
"CompileTemplateMetadata.ngContentSelectors",
|
||||
|
@ -550,6 +559,14 @@ var NG_COMPILER = [
|
|||
"CompileTypeMetadata.name=",
|
||||
"CompileTypeMetadata.runtime",
|
||||
"CompileTypeMetadata.runtime=",
|
||||
"CompileTypeMetadata.diDeps",
|
||||
"CompileTypeMetadata.diDeps=",
|
||||
"CompileTypeMetadata.type",
|
||||
"CompileTypeMetadata.identifier",
|
||||
"CompileTypeMetadata.prefix",
|
||||
"CompileTypeMetadata.prefix=",
|
||||
"CompileTypeMetadata.constConstructor",
|
||||
"CompileTypeMetadata.constConstructor=",
|
||||
"DirectiveAst.directive",
|
||||
"DirectiveAst.directive=",
|
||||
"DirectiveAst.exportAsVars",
|
||||
|
|
|
@ -127,6 +127,7 @@ export class MdDialog {
|
|||
/**
|
||||
* Reference to an opened dialog.
|
||||
*/
|
||||
@Injectable()
|
||||
export class MdDialogRef {
|
||||
// Reference to the MdDialogContainer component.
|
||||
containerRef: ComponentRef;
|
||||
|
|
|
@ -67,6 +67,7 @@ class ReflectionInfoVisitor extends RecursiveAstVisitor<ReflectionInfoModel> {
|
|||
|
||||
@override
|
||||
ReflectionInfoModel visitClassDeclaration(ClassDeclaration node) {
|
||||
if (node.isAbstract) return null;
|
||||
if (!node.metadata
|
||||
.any((a) => _annotationMatcher.hasMatch(a.name, assetId))) {
|
||||
return null;
|
||||
|
|
|
@ -33,9 +33,9 @@ class NgMeta {
|
|||
static const _TYPE_VALUE = 'type';
|
||||
static const _VALUE_KEY = 'value';
|
||||
|
||||
/// Metadata for each type annotated as a directive/pipe.
|
||||
/// Type: [CompileDirectiveMetadata]/[CompilePipeMetadata]
|
||||
final Map<String, dynamic> types;
|
||||
/// Metadata for each identifier
|
||||
/// Type: [CompileDirectiveMetadata]|[CompilePipeMetadata]|[CompileTypeMetadata]|[CompileIdentifierMetadata]
|
||||
final Map<String, dynamic> identifiers;
|
||||
|
||||
/// List of other types and names associated with a given name.
|
||||
final Map<String, List<String>> aliases;
|
||||
|
@ -43,12 +43,13 @@ class NgMeta {
|
|||
// The NgDeps generated from
|
||||
final NgDepsModel ngDeps;
|
||||
|
||||
NgMeta(
|
||||
{Map<String, dynamic> types,
|
||||
Map<String, List<String>> aliases,
|
||||
this.ngDeps: null})
|
||||
: this.types = types != null ? types : {},
|
||||
this.aliases = aliases != null ? aliases : {};
|
||||
bool definesAlias;
|
||||
|
||||
NgMeta({Map<String, List<String>> aliases,
|
||||
Map<String, dynamic> identifiers,
|
||||
this.ngDeps: null, this.definesAlias: false})
|
||||
:this.aliases = aliases != null ? aliases : {},
|
||||
this.identifiers = identifiers != null ? identifiers : {};
|
||||
|
||||
NgMeta.empty() : this();
|
||||
|
||||
|
@ -69,13 +70,22 @@ class NgMeta {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool get isEmpty => types.isEmpty && aliases.isEmpty && isNgDepsEmpty;
|
||||
bool get isEmpty => identifiers.isEmpty && aliases.isEmpty && isNgDepsEmpty;
|
||||
|
||||
List<String> get linkingUris {
|
||||
final r = ngDeps.exports.map((r) => r.uri).toList();
|
||||
if (definesAlias) {
|
||||
r.addAll(ngDeps.imports.map((r) => r.uri));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/// Parse from the serialized form produced by [toJson].
|
||||
factory NgMeta.fromJson(Map json) {
|
||||
var ngDeps = null;
|
||||
final types = {};
|
||||
final aliases = {};
|
||||
final identifiers = {};
|
||||
var definesAlias = false;
|
||||
for (var key in json.keys) {
|
||||
if (key == _NG_DEPS_KEY) {
|
||||
var ngDepsJsonMap = json[key];
|
||||
|
@ -85,7 +95,11 @@ class NgMeta {
|
|||
'Unexpected value $ngDepsJsonMap for key "$key" in NgMeta.');
|
||||
continue;
|
||||
}
|
||||
ngDeps = new NgDepsModel()..mergeFromJsonMap(ngDepsJsonMap);
|
||||
ngDeps = new NgDepsModel()
|
||||
..mergeFromJsonMap(ngDepsJsonMap);
|
||||
} else if (key == 'definesAlias') {
|
||||
definesAlias = json[key];
|
||||
|
||||
} else {
|
||||
var entry = json[key];
|
||||
if (entry is! Map) {
|
||||
|
@ -93,13 +107,13 @@ class NgMeta {
|
|||
continue;
|
||||
}
|
||||
if (entry[_KIND_KEY] == _TYPE_VALUE) {
|
||||
types[key] = CompileMetadataWithType.fromJson(entry[_VALUE_KEY]);
|
||||
identifiers[key] = CompileMetadataWithIdentifier.fromJson(entry[_VALUE_KEY]);
|
||||
} else if (entry[_KIND_KEY] == _ALIAS_VALUE) {
|
||||
aliases[key] = entry[_VALUE_KEY];
|
||||
}
|
||||
}
|
||||
}
|
||||
return new NgMeta(types: types, aliases: aliases, ngDeps: ngDeps);
|
||||
return new NgMeta(identifiers: identifiers, aliases: aliases, ngDeps: ngDeps, definesAlias: definesAlias);
|
||||
}
|
||||
|
||||
/// Serialized representation of this instance.
|
||||
|
@ -107,41 +121,44 @@ class NgMeta {
|
|||
var result = {};
|
||||
result[_NG_DEPS_KEY] = isNgDepsEmpty ? null : ngDeps.writeToJsonMap();
|
||||
|
||||
types.forEach((k, v) {
|
||||
identifiers.forEach((k, v) {
|
||||
result[k] = {_KIND_KEY: _TYPE_VALUE, _VALUE_KEY: v.toJson()};
|
||||
});
|
||||
|
||||
aliases.forEach((k, v) {
|
||||
result[k] = {_KIND_KEY: _ALIAS_VALUE, _VALUE_KEY: v};
|
||||
});
|
||||
|
||||
result['definesAlias'] = definesAlias;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Merge into this instance all information from [other].
|
||||
/// This does not include `ngDeps`.
|
||||
void addAll(NgMeta other) {
|
||||
types.addAll(other.types);
|
||||
aliases.addAll(other.aliases);
|
||||
identifiers.addAll(other.identifiers);
|
||||
}
|
||||
|
||||
/// Returns the metadata for every type associated with the given [alias].
|
||||
List<dynamic> flatten(String alias) {
|
||||
var result = [];
|
||||
var seen = new Set();
|
||||
helper(name) {
|
||||
if (!seen.add(name)) {
|
||||
log.warning('Circular alias dependency for "$name".');
|
||||
helper(name, path) {
|
||||
final newPath = []..addAll(path)..add(name);
|
||||
if (path.contains(name)) {
|
||||
log.error('Circular alias dependency for "$name". Cycle: ${newPath.join(' -> ')}.');
|
||||
return;
|
||||
}
|
||||
if (types.containsKey(name)) {
|
||||
result.add(types[name]);
|
||||
if (identifiers.containsKey(name)) {
|
||||
result.add(identifiers[name]);
|
||||
} else if (aliases.containsKey(name)) {
|
||||
aliases[name].forEach(helper);
|
||||
aliases[name].forEach((n) => helper(n, newPath));
|
||||
} else {
|
||||
log.warning('Unknown alias: "$name".');
|
||||
log.error('Unknown alias: ${newPath.join(' -> ')}. Make sure you export ${name} from the file where ${path.last} is defined.');
|
||||
}
|
||||
}
|
||||
helper(alias);
|
||||
helper(alias, []);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,22 +21,24 @@ import 'url_resolver.dart';
|
|||
class TypeMetadataReader {
|
||||
final _DirectiveMetadataVisitor _directiveVisitor;
|
||||
final _PipeMetadataVisitor _pipeVisitor;
|
||||
final _CompileTypeMetadataVisitor _typeVisitor;
|
||||
final TemplateCompiler _templateCompiler;
|
||||
|
||||
TypeMetadataReader._(
|
||||
this._directiveVisitor, this._pipeVisitor, this._templateCompiler);
|
||||
this._directiveVisitor, this._pipeVisitor, this._templateCompiler, this._typeVisitor);
|
||||
|
||||
/// Accepts an [AnnotationMatcher] which tests that an [Annotation]
|
||||
/// is a [Directive], [Component], or [View].
|
||||
factory TypeMetadataReader(AnnotationMatcher annotationMatcher,
|
||||
InterfaceMatcher interfaceMatcher, TemplateCompiler templateCompiler) {
|
||||
var lifecycleVisitor = new _LifecycleHookVisitor(interfaceMatcher);
|
||||
var typeVisitor = new _CompileTypeMetadataVisitor(annotationMatcher);
|
||||
var directiveVisitor =
|
||||
new _DirectiveMetadataVisitor(annotationMatcher, lifecycleVisitor);
|
||||
new _DirectiveMetadataVisitor(annotationMatcher, lifecycleVisitor, typeVisitor);
|
||||
var pipeVisitor = new _PipeMetadataVisitor(annotationMatcher);
|
||||
|
||||
return new TypeMetadataReader._(
|
||||
directiveVisitor, pipeVisitor, templateCompiler);
|
||||
directiveVisitor, pipeVisitor, templateCompiler, typeVisitor);
|
||||
}
|
||||
|
||||
/// Reads *un-normalized* [CompileDirectiveMetadata]/[CompilePipeMetadata] from the
|
||||
|
@ -52,13 +54,19 @@ class TypeMetadataReader {
|
|||
Future<dynamic> readTypeMetadata(ClassDeclaration node, AssetId assetId) {
|
||||
_directiveVisitor.reset(assetId);
|
||||
_pipeVisitor.reset(assetId);
|
||||
_typeVisitor.reset(assetId);
|
||||
|
||||
node.accept(_directiveVisitor);
|
||||
node.accept(_pipeVisitor);
|
||||
node.accept(_typeVisitor);
|
||||
|
||||
if (_directiveVisitor.hasMetadata) {
|
||||
final metadata = _directiveVisitor.createMetadata();
|
||||
return _templateCompiler.normalizeDirectiveMetadata(metadata);
|
||||
} else if (_pipeVisitor.hasMetadata) {
|
||||
return new Future.value(_pipeVisitor.createMetadata());
|
||||
} else if (_typeVisitor.isInjectable) {
|
||||
return new Future.value(_typeVisitor.type);
|
||||
} else {
|
||||
return new Future.value(null);
|
||||
}
|
||||
|
@ -124,6 +132,67 @@ bool _expressionToBool(Expression node, String nodeDescription) {
|
|||
return value;
|
||||
}
|
||||
|
||||
class _CompileTypeMetadataVisitor extends Object
|
||||
with RecursiveAstVisitor<CompileTypeMetadata> {
|
||||
|
||||
bool _isInjectable = false;
|
||||
CompileTypeMetadata _type;
|
||||
AssetId _assetId;
|
||||
final AnnotationMatcher _annotationMatcher;
|
||||
|
||||
_CompileTypeMetadataVisitor(this._annotationMatcher);
|
||||
|
||||
bool get isInjectable => _isInjectable;
|
||||
|
||||
CompileTypeMetadata get type => _type;
|
||||
|
||||
void reset(AssetId assetId) {
|
||||
this._assetId = assetId;
|
||||
this._isInjectable = false;
|
||||
this._type = null;
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitAnnotation(Annotation node) {
|
||||
final isComponent = _annotationMatcher.isComponent(node, _assetId);
|
||||
final isDirective = _annotationMatcher.isDirective(node, _assetId);
|
||||
final isInjectable = _annotationMatcher.isInjectable(node, _assetId);
|
||||
|
||||
_isInjectable = _isInjectable || isComponent || isDirective || isInjectable;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitClassDeclaration(ClassDeclaration node) {
|
||||
node.metadata.accept(this);
|
||||
if (this._isInjectable) {
|
||||
_type = new CompileTypeMetadata(
|
||||
moduleUrl: toAssetUri(_assetId),
|
||||
name: node.name.toString(),
|
||||
diDeps: _getCompileDiDependencyMetadata(node),
|
||||
runtime: null // Intentionally `null`, cannot be provided here.
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
List<CompileDiDependencyMetadata> _getCompileDiDependencyMetadata(ClassDeclaration node) {
|
||||
final constructor = node.getConstructor(null);
|
||||
if (constructor == null) return [];
|
||||
|
||||
return constructor.parameters.parameters.map((p) {
|
||||
final typeToken = p is SimpleFormalParameter && p.type != null ? _readIdentifier(p.type.name) : null;
|
||||
final injectTokens = p.metadata.where((m) => m.name.toString() == "Inject").map((m) => _readIdentifier(m.arguments.arguments[0]));
|
||||
final token = injectTokens.isNotEmpty ? injectTokens.first : typeToken;
|
||||
return new CompileDiDependencyMetadata(token: token);
|
||||
}).toList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// Visitor responsible for processing a [Directive] annotated
|
||||
/// [ClassDeclaration] and creating a [CompileDirectiveMetadata] object.
|
||||
class _DirectiveMetadataVisitor extends Object
|
||||
|
@ -134,10 +203,12 @@ class _DirectiveMetadataVisitor extends Object
|
|||
|
||||
final _LifecycleHookVisitor _lifecycleVisitor;
|
||||
|
||||
final _CompileTypeMetadataVisitor _typeVisitor;
|
||||
|
||||
/// The [AssetId] we are currently processing.
|
||||
AssetId _assetId;
|
||||
|
||||
_DirectiveMetadataVisitor(this._annotationMatcher, this._lifecycleVisitor) {
|
||||
_DirectiveMetadataVisitor(this._annotationMatcher, this._lifecycleVisitor, this._typeVisitor) {
|
||||
reset(null);
|
||||
}
|
||||
|
||||
|
@ -154,12 +225,14 @@ class _DirectiveMetadataVisitor extends Object
|
|||
List<String> _inputs;
|
||||
List<String> _outputs;
|
||||
Map<String, String> _host;
|
||||
List<CompileProviderMetadata> _providers;
|
||||
List<LifecycleHooks> _lifecycleHooks;
|
||||
CompileTemplateMetadata _cmpTemplate;
|
||||
CompileTemplateMetadata _viewTemplate;
|
||||
|
||||
void reset(AssetId assetId) {
|
||||
_lifecycleVisitor.reset(assetId);
|
||||
_typeVisitor.reset(assetId);
|
||||
_assetId = assetId;
|
||||
|
||||
_type = null;
|
||||
|
@ -171,6 +244,7 @@ class _DirectiveMetadataVisitor extends Object
|
|||
_inputs = <String>[];
|
||||
_outputs = <String>[];
|
||||
_host = <String, String>{};
|
||||
_providers = <CompileProviderMetadata>[];
|
||||
_lifecycleHooks = null;
|
||||
_cmpTemplate = null;
|
||||
_viewTemplate = null;
|
||||
|
@ -192,6 +266,7 @@ class _DirectiveMetadataVisitor extends Object
|
|||
inputs: _inputs,
|
||||
outputs: _outputs,
|
||||
host: _host,
|
||||
providers: _providers,
|
||||
lifecycleHooks: _lifecycleHooks,
|
||||
template: _template);
|
||||
}
|
||||
|
@ -316,6 +391,41 @@ class _DirectiveMetadataVisitor extends Object
|
|||
}
|
||||
}
|
||||
|
||||
void _populateProviders(Expression providerValues) {
|
||||
_checkMeta();
|
||||
|
||||
if (providerValues is ListLiteral) {
|
||||
final providers = providerValues.elements.map((el) {
|
||||
if (el is PrefixedIdentifier || el is SimpleIdentifier) {
|
||||
return new CompileProviderMetadata(token: _readIdentifier(el));
|
||||
|
||||
} else if (el is InstanceCreationExpression &&
|
||||
(el.constructorName.toString() == "Provider" ||
|
||||
el.constructorName.toString() == "Binding")
|
||||
|
||||
) {
|
||||
final token = el.argumentList.arguments.first;
|
||||
|
||||
var useClass;
|
||||
el.argumentList.arguments.skip(1).forEach((arg) {
|
||||
if (arg.name.toString() == "useClass:") {
|
||||
final id = _readIdentifier(arg.expression);
|
||||
useClass = new CompileTypeMetadata(prefix: id.prefix, name: id.name);
|
||||
}
|
||||
});
|
||||
return new CompileProviderMetadata(token: _readIdentifier(token), useClass: useClass);
|
||||
|
||||
} else {
|
||||
throw new ArgumentError(
|
||||
'Incorrect value. Expected a Provider or a String, but got "${el}".');
|
||||
}
|
||||
});
|
||||
_providers.addAll(providers);
|
||||
} else {
|
||||
_providers.add(new CompileProviderMetadata(token: _readIdentifier(providerValues)));
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Use AnnotationMatcher instead of string matching
|
||||
bool _isAnnotation(Annotation node, String annotationName) {
|
||||
var id = node.name;
|
||||
|
@ -356,12 +466,10 @@ class _DirectiveMetadataVisitor extends Object
|
|||
@override
|
||||
Object visitClassDeclaration(ClassDeclaration node) {
|
||||
node.metadata.accept(this);
|
||||
node.accept(_typeVisitor);
|
||||
_type = _typeVisitor.type;
|
||||
|
||||
if (this._hasMetadata) {
|
||||
_type = new CompileTypeMetadata(
|
||||
moduleUrl: toAssetUri(_assetId),
|
||||
name: node.name.toString(),
|
||||
runtime: null // Intentionally `null`, cannot be provided here.
|
||||
);
|
||||
_lifecycleHooks = node.implementsClause != null
|
||||
? node.implementsClause.accept(_lifecycleVisitor)
|
||||
: const [];
|
||||
|
@ -405,6 +513,9 @@ class _DirectiveMetadataVisitor extends Object
|
|||
case 'events':
|
||||
_populateEvents(node.expression);
|
||||
break;
|
||||
case 'providers':
|
||||
_populateProviders(node.expression);
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -687,3 +798,22 @@ class _PipeMetadataVisitor extends Object with RecursiveAstVisitor<Object> {
|
|||
_pure = _expressionToBool(pureValue, 'Pipe#pure');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dynamic _readIdentifier(dynamic el) {
|
||||
if (el is PrefixedIdentifier) {
|
||||
return new CompileIdentifierMetadata(name: '${el.identifier}', prefix: '${el.prefix}');
|
||||
|
||||
} else if (el is SimpleIdentifier) {
|
||||
return new CompileIdentifierMetadata(name: '$el');
|
||||
|
||||
} else if (el is SimpleStringLiteral){
|
||||
return el.value;
|
||||
|
||||
} else if (el is InstanceCreationExpression){
|
||||
return new CompileIdentifierMetadata(name: '${el.constructorName}', constConstructor: true);
|
||||
|
||||
} else {
|
||||
throw new ArgumentError('Incorrect identifier "${el}".');
|
||||
}
|
||||
}
|
|
@ -61,10 +61,10 @@ Future _linkRecursive(NgMeta ngMeta, AssetReader reader, AssetId assetId,
|
|||
}
|
||||
var assetUri = toAssetUri(assetId);
|
||||
|
||||
return Future.wait(ngMeta.ngDeps.exports
|
||||
.where((export) => !isDartCoreUri(export.uri))
|
||||
.map((export) =>
|
||||
_urlResolver.resolve(assetUri, toSummaryExtension(export.uri)))
|
||||
return Future.wait(ngMeta.linkingUris
|
||||
.where((uri) => !isDartCoreUri(uri))
|
||||
.map((uri) =>
|
||||
_urlResolver.resolve(assetUri, toSummaryExtension(uri)))
|
||||
.where((uri) => !seen.contains(uri))
|
||||
.map((uri) async {
|
||||
seen.add(uri);
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'dart:async';
|
|||
import 'package:analyzer/analyzer.dart';
|
||||
import 'package:barback/barback.dart' show AssetId;
|
||||
|
||||
import 'package:angular2/src/compiler/directive_metadata.dart' show CompileIdentifierMetadata;
|
||||
import 'package:angular2/src/compiler/template_compiler.dart';
|
||||
import 'package:angular2/src/transform/common/annotation_matcher.dart';
|
||||
import 'package:angular2/src/transform/common/asset_reader.dart';
|
||||
|
@ -14,6 +15,7 @@ import 'package:angular2/src/transform/common/interface_matcher.dart';
|
|||
import 'package:angular2/src/transform/common/logging.dart';
|
||||
import 'package:angular2/src/transform/common/ng_compiler.dart';
|
||||
import 'package:angular2/src/transform/common/ng_meta.dart';
|
||||
import 'package:angular2/src/transform/common/url_resolver.dart';
|
||||
import 'package:angular2/src/transform/common/zone.dart' as zone;
|
||||
|
||||
import 'inliner.dart';
|
||||
|
@ -89,14 +91,17 @@ class _NgMetaVisitor extends Object with SimpleAstVisitor<Object> {
|
|||
@override
|
||||
Object visitClassDeclaration(ClassDeclaration node) {
|
||||
_normalizations.add(
|
||||
_reader.readTypeMetadata(node, assetId).then((compileMetadataWithType) {
|
||||
if (compileMetadataWithType != null) {
|
||||
ngMeta.types[compileMetadataWithType.type.name] =
|
||||
compileMetadataWithType;
|
||||
_reader.readTypeMetadata(node, assetId).then((compileMetadataWithIdentifier) {
|
||||
if (compileMetadataWithIdentifier!= null) {
|
||||
ngMeta.identifiers[compileMetadataWithIdentifier.identifier.name] =
|
||||
compileMetadataWithIdentifier;
|
||||
} else {
|
||||
ngMeta.identifiers[node.name.name] = new CompileIdentifierMetadata(name: node.name.name, moduleUrl: toAssetUri(assetId));
|
||||
}
|
||||
}).catchError((err) {
|
||||
log.error('ERROR: $err', asset: assetId);
|
||||
}));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -108,6 +113,11 @@ class _NgMetaVisitor extends Object with SimpleAstVisitor<Object> {
|
|||
// doesn't support decorators on variable declarations (see
|
||||
// angular/angular#1747 and angular/ts2dart#249 for context).
|
||||
outer: for (var variable in node.variables.variables) {
|
||||
if (variable.isConst) {
|
||||
ngMeta.identifiers[variable.name.name] =
|
||||
new CompileIdentifierMetadata(name: variable.name.name, moduleUrl: toAssetUri(assetId));
|
||||
}
|
||||
|
||||
var initializer = variable.initializer;
|
||||
if (initializer != null && initializer is ListLiteral) {
|
||||
var otherNames = [];
|
||||
|
@ -117,9 +127,24 @@ class _NgMetaVisitor extends Object with SimpleAstVisitor<Object> {
|
|||
if (exp is! SimpleIdentifier) continue outer;
|
||||
otherNames.add(exp.name);
|
||||
}
|
||||
ngMeta.definesAlias = true;
|
||||
ngMeta.aliases[variable.name.name] = otherNames;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitFunctionTypeAlias(FunctionTypeAlias node) {
|
||||
ngMeta.identifiers[node.name.name] =
|
||||
new CompileIdentifierMetadata(name: node.name.name, moduleUrl: toAssetUri(assetId));
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitEnumDeclaration(EnumDeclaration node) {
|
||||
ngMeta.identifiers[node.name.name] =
|
||||
new CompileIdentifierMetadata(name: node.name.name, moduleUrl: toAssetUri(assetId));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,8 +74,8 @@ class _CompileDataCreator {
|
|||
var hasTemplate = ngDeps != null &&
|
||||
ngDeps.reflectables != null &&
|
||||
ngDeps.reflectables.any((reflectable) {
|
||||
if (ngMeta.types.containsKey(reflectable.name)) {
|
||||
final metadata = ngMeta.types[reflectable.name];
|
||||
if (ngMeta.identifiers.containsKey(reflectable.name)) {
|
||||
final metadata = ngMeta.identifiers[reflectable.name];
|
||||
return metadata is CompileDirectiveMetadata &&
|
||||
metadata.template != null;
|
||||
}
|
||||
|
@ -91,8 +91,8 @@ class _CompileDataCreator {
|
|||
final platformPipes = await _readPlatformTypes(this.platformPipes, 'pipes');
|
||||
|
||||
for (var reflectable in ngDeps.reflectables) {
|
||||
if (ngMeta.types.containsKey(reflectable.name)) {
|
||||
final compileDirectiveMetadata = ngMeta.types[reflectable.name];
|
||||
if (ngMeta.identifiers.containsKey(reflectable.name)) {
|
||||
final compileDirectiveMetadata = ngMeta.identifiers[reflectable.name];
|
||||
if (compileDirectiveMetadata is CompileDirectiveMetadata &&
|
||||
compileDirectiveMetadata.template != null) {
|
||||
final compileDatum = new NormalizedComponentWithViewDirectives(
|
||||
|
@ -106,6 +106,9 @@ class _CompileDataCreator {
|
|||
compileDatum.pipes
|
||||
.addAll(_resolveTypeMetadata(ngMetaMap, reflectable.pipes));
|
||||
compileData[reflectable] = compileDatum;
|
||||
|
||||
_resolveDiDependencyMetadata(ngMetaMap, compileDirectiveMetadata.type, compileDirectiveMetadata.type.diDeps);
|
||||
_resolveProviderMetadata(ngMetaMap, compileDirectiveMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -117,16 +120,16 @@ class _CompileDataCreator {
|
|||
var resolvedMetadata = [];
|
||||
for (var dep in prefixedTypes) {
|
||||
if (!ngMetaMap.containsKey(dep.prefix)) {
|
||||
log.warning(
|
||||
log.error(
|
||||
'Missing prefix "${dep.prefix}" '
|
||||
'needed by "${dep}" from metadata map',
|
||||
'needed by "${dep}" from metadata map,',
|
||||
asset: entryPoint);
|
||||
continue;
|
||||
return null;
|
||||
}
|
||||
final depNgMeta = ngMetaMap[dep.prefix];
|
||||
|
||||
if (depNgMeta.types.containsKey(dep.name)) {
|
||||
resolvedMetadata.add(depNgMeta.types[dep.name]);
|
||||
if (depNgMeta.identifiers.containsKey(dep.name)) {
|
||||
resolvedMetadata.add(depNgMeta.identifiers[dep.name]);
|
||||
} else if (depNgMeta.aliases.containsKey(dep.name)) {
|
||||
resolvedMetadata.addAll(depNgMeta.flatten(dep.name));
|
||||
} else {
|
||||
|
@ -141,6 +144,98 @@ class _CompileDataCreator {
|
|||
return resolvedMetadata;
|
||||
}
|
||||
|
||||
void _resolveProviderMetadata(Map<String, NgMeta> ngMetaMap, CompileDirectiveMetadata dirMeta) {
|
||||
final neededBy = dirMeta.type;
|
||||
|
||||
if (dirMeta.providers == null) return;
|
||||
|
||||
final resolvedProviders = [];
|
||||
for (var provider in dirMeta.providers) {
|
||||
final alias = _resolveAlias(ngMetaMap, neededBy, provider.token);
|
||||
if (alias != null) {
|
||||
resolvedProviders.addAll(alias.map((a) => new CompileProviderMetadata(token:a)));
|
||||
} else {
|
||||
provider.token = _resolveIdentifier(ngMetaMap, neededBy, provider.token);
|
||||
if (provider.useClass != null) {
|
||||
provider.useClass = _resolveIdentifier(ngMetaMap, neededBy, provider.useClass);
|
||||
}
|
||||
resolvedProviders.add(provider);
|
||||
}
|
||||
}
|
||||
|
||||
dirMeta.providers = resolvedProviders;
|
||||
}
|
||||
|
||||
void _resolveDiDependencyMetadata(
|
||||
Map<String, NgMeta> ngMetaMap,CompileTypeMetadata neededBy, List<CompileDiDependencyMetadata> deps) {
|
||||
if (deps == null) return;
|
||||
for (var dep in deps) {
|
||||
dep.token = _resolveIdentifier(ngMetaMap, neededBy, dep.token);
|
||||
}
|
||||
}
|
||||
|
||||
dynamic _resolveAlias(Map<String, NgMeta> ngMetaMap, CompileTypeMetadata neededBy, dynamic id) {
|
||||
if (id is String || id == null) return null;
|
||||
|
||||
final prefix = id.prefix == null ? "" : id.prefix;
|
||||
|
||||
if (!ngMetaMap.containsKey(prefix)) {
|
||||
log.error(
|
||||
'Missing prefix "${prefix}" '
|
||||
'needed by "${neededBy.name}" from metadata map',
|
||||
asset: entryPoint);
|
||||
return null;
|
||||
}
|
||||
|
||||
final depNgMeta = ngMetaMap[prefix];
|
||||
if (depNgMeta.aliases.containsKey(id.name)) {
|
||||
return depNgMeta.flatten(id.name);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
dynamic _resolveIdentifier(Map<String, NgMeta> ngMetaMap, CompileTypeMetadata neededBy, dynamic id) {
|
||||
if (id is String || id == null) return id;
|
||||
|
||||
final prefix = id.prefix == null ? "" : id.prefix;
|
||||
|
||||
if (!ngMetaMap.containsKey(prefix)) {
|
||||
log.error(
|
||||
'Missing prefix "${prefix}" '
|
||||
'needed by "${neededBy.name}" from metadata map',
|
||||
asset: entryPoint);
|
||||
return null;
|
||||
}
|
||||
|
||||
final depNgMeta = ngMetaMap[prefix];
|
||||
if (depNgMeta.identifiers.containsKey(id.name)) {
|
||||
return depNgMeta.identifiers[id.name];
|
||||
|
||||
} else if (_isPrimitive(id.name)) {
|
||||
return id;
|
||||
|
||||
} else if (id.name == "Window") {
|
||||
return new CompileIdentifierMetadata(name: "Window", moduleUrl: 'dart:html');
|
||||
|
||||
} else if (id.name == "Clock") {
|
||||
return new CompileIdentifierMetadata(name: "Clock", moduleUrl: 'dart:time');
|
||||
|
||||
} else if (id.name == "Profiler") {
|
||||
return new CompileIdentifierMetadata(name: "Clock", moduleUrl: 'profiler');
|
||||
|
||||
} else {
|
||||
log.error(
|
||||
'Missing identifier "${id.name}" '
|
||||
'needed by "${neededBy.name}" from metadata map',
|
||||
asset: entryPoint);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
bool _isPrimitive(String typeName) =>
|
||||
typeName == "String" || typeName == "Object" || typeName == "num" || typeName == "int" || typeName == "double" || typeName == "bool";
|
||||
|
||||
Future<List<dynamic>> _readPlatformTypes(
|
||||
List<String> inputPlatformTypes, String configOption) async {
|
||||
if (inputPlatformTypes == null) return const [];
|
||||
|
@ -168,8 +263,8 @@ class _CompileDataCreator {
|
|||
if (jsonString != null && jsonString.isNotEmpty) {
|
||||
var newMetadata = new NgMeta.fromJson(JSON.decode(jsonString));
|
||||
|
||||
if (newMetadata.types.containsKey(token)) {
|
||||
return [newMetadata.types[token]];
|
||||
if (newMetadata.identifiers.containsKey(token)) {
|
||||
return [newMetadata.identifiers[token]];
|
||||
} else if (newMetadata.aliases.containsKey(token)) {
|
||||
return newMetadata.flatten(token);
|
||||
} else {
|
||||
|
@ -194,7 +289,6 @@ class _CompileDataCreator {
|
|||
return map;
|
||||
}
|
||||
final resolver = const TransformerUrlResolver();
|
||||
|
||||
ngMeta.ngDeps.imports
|
||||
.where((model) => !isDartCoreUri(model.uri))
|
||||
.forEach((model) {
|
||||
|
@ -242,6 +336,7 @@ class _CompileDataCreator {
|
|||
var ngMeta = retVal[prefix] = new NgMeta.empty();
|
||||
for (var importAssetUri in prefixToImports[prefix]) {
|
||||
var metaAssetId = fromUri(toMetaExtension(importAssetUri));
|
||||
|
||||
if (await reader.hasInput(metaAssetId)) {
|
||||
try {
|
||||
var jsonString = await reader.readAsString(metaAssetId);
|
||||
|
|
|
@ -42,16 +42,18 @@ Future<Outputs> processTemplates(AssetReader reader, AssetId assetId,
|
|||
var viewDefResults = await createCompileData(
|
||||
reader, assetId, platformDirectives, platformPipes);
|
||||
if (viewDefResults == null) return null;
|
||||
final compileTypeMetadatas = viewDefResults.ngMeta.types.values;
|
||||
final compileTypeMetadatas = viewDefResults.ngMeta.identifiers.values;
|
||||
if (compileTypeMetadatas.isNotEmpty) {
|
||||
var processor = new reg.Processor();
|
||||
compileTypeMetadatas.forEach(processor.process);
|
||||
viewDefResults.ngMeta.ngDeps.getters
|
||||
.addAll(processor.getterNames.map((e) => e.sanitizedName));
|
||||
viewDefResults.ngMeta.ngDeps.setters
|
||||
.addAll(processor.setterNames.map((e) => e.sanitizedName));
|
||||
viewDefResults.ngMeta.ngDeps.methods
|
||||
.addAll(processor.methodNames.map((e) => e.sanitizedName));
|
||||
if (viewDefResults.ngMeta.ngDeps != null) {
|
||||
viewDefResults.ngMeta.ngDeps.getters
|
||||
.addAll(processor.getterNames.map((e) => e.sanitizedName));
|
||||
viewDefResults.ngMeta.ngDeps.setters
|
||||
.addAll(processor.setterNames.map((e) => e.sanitizedName));
|
||||
viewDefResults.ngMeta.ngDeps.methods
|
||||
.addAll(processor.methodNames.map((e) => e.sanitizedName));
|
||||
}
|
||||
}
|
||||
var templateCompiler = zone.templateCompiler;
|
||||
if (templateCompiler == null) {
|
||||
|
@ -98,4 +100,4 @@ class Outputs {
|
|||
final SourceModule templatesSource;
|
||||
|
||||
Outputs._(this.ngDeps, this.templatesSource);
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ class Processor implements CodegenModel {
|
|||
/// The names of all requested `method`s.
|
||||
final Set<ReflectiveAccessor> methodNames = new Set<ReflectiveAccessor>();
|
||||
|
||||
void process(CompileMetadataWithType meta) {
|
||||
void process(Object meta) {
|
||||
if (meta is CompileDirectiveMetadata) {
|
||||
if (meta.outputs != null) {
|
||||
meta.outputs.keys.forEach((eventName) {
|
||||
|
|
|
@ -82,4 +82,4 @@ CompileDirectiveMetadata createBaz([String moduleBase = 'asset:a']) =>
|
|||
name: 'BazComponent',
|
||||
moduleUrl: '$moduleBase/export_cycle_files/baz.dart',
|
||||
selector: 'baz',
|
||||
template: 'Baz');
|
||||
template: 'Baz');
|
|
@ -8,7 +8,7 @@ import 'package:guinness/guinness.dart';
|
|||
main() => allTests();
|
||||
|
||||
void allTests() {
|
||||
var mockData = [
|
||||
var mockDirMetadata = [
|
||||
CompileDirectiveMetadata.create(type: new CompileTypeMetadata(name: 'N1')),
|
||||
CompileDirectiveMetadata.create(type: new CompileTypeMetadata(name: 'N2')),
|
||||
CompileDirectiveMetadata.create(type: new CompileTypeMetadata(name: 'N3')),
|
||||
|
@ -28,14 +28,16 @@ void allTests() {
|
|||
|
||||
it('should be lossless', () {
|
||||
var a = new NgMeta.empty();
|
||||
a.types['T0'] = mockData[0];
|
||||
a.types['T1'] = mockData[1];
|
||||
a.types['T2'] = mockData[2];
|
||||
a.types['T3'] = mockData[3];
|
||||
a.identifiers['T0'] = mockDirMetadata[0];
|
||||
a.identifiers['T1'] = mockDirMetadata[1];
|
||||
a.identifiers['T2'] = mockDirMetadata[2];
|
||||
a.identifiers['T3'] = mockDirMetadata[3];
|
||||
|
||||
a.aliases['a1'] = ['T1'];
|
||||
a.aliases['a2'] = ['a1'];
|
||||
a.aliases['a3'] = ['T3', 'a2'];
|
||||
a.aliases['a4'] = ['a3', 'T3'];
|
||||
|
||||
_checkSimilar(a, new NgMeta.fromJson(a.toJson()));
|
||||
});
|
||||
});
|
||||
|
@ -43,35 +45,46 @@ void allTests() {
|
|||
describe('flatten', () {
|
||||
it('should include recursive aliases.', () {
|
||||
var a = new NgMeta.empty();
|
||||
a.types['T0'] = mockData[0];
|
||||
a.types['T1'] = mockData[1];
|
||||
a.types['T2'] = mockData[2];
|
||||
a.types['T3'] = mockData[3];
|
||||
a.identifiers['T0'] = mockDirMetadata[0];
|
||||
a.identifiers['T1'] = mockDirMetadata[1];
|
||||
a.identifiers['T2'] = mockDirMetadata[2];
|
||||
a.identifiers['T3'] = mockDirMetadata[3];
|
||||
a.aliases['a1'] = ['T1'];
|
||||
a.aliases['a2'] = ['a1'];
|
||||
a.aliases['a3'] = ['T3', 'a2'];
|
||||
a.aliases['a4'] = ['a3', 'T0'];
|
||||
expect(a.flatten('a4')).toEqual([mockData[3], mockData[1], mockData[0]]);
|
||||
|
||||
expect(a.flatten('a4')).toEqual([mockDirMetadata[3], mockDirMetadata[1], mockDirMetadata[0]]);
|
||||
});
|
||||
|
||||
it('should detect cycles.', () {
|
||||
var a = new NgMeta.empty();
|
||||
a.types['T0'] = mockData[0];
|
||||
a.aliases['a1'] = ['T0', 'a1'];
|
||||
a.identifiers['T0'] = mockDirMetadata[0];
|
||||
a.aliases['a1'] = ['T0', 'a2'];
|
||||
a.aliases['a2'] = ['a1'];
|
||||
expect(a.flatten('a1')).toEqual([mockData[0]]);
|
||||
|
||||
expect(() => a.flatten('a1')).toThrowWith(message: new RegExp('Cycle: a1 -> a2 -> a1.'));
|
||||
});
|
||||
|
||||
it('should allow duplicates.', () {
|
||||
var a = new NgMeta.empty();
|
||||
a.identifiers['T0'] = mockDirMetadata[0];
|
||||
a.aliases['a1'] = ['T0', 'a2'];
|
||||
a.aliases['a2'] = ['T0'];
|
||||
|
||||
expect(() => a.flatten('a1')).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('merge', () {
|
||||
it('should merge all types on addAll', () {
|
||||
it('should merge all identifiers on addAll', () {
|
||||
var a = new NgMeta.empty();
|
||||
var b = new NgMeta.empty();
|
||||
a.types['T0'] = mockData[0];
|
||||
b.types['T1'] = mockData[1];
|
||||
a.identifiers['T0'] = mockDirMetadata[0];
|
||||
b.identifiers['T1'] = mockDirMetadata[1];
|
||||
a.addAll(b);
|
||||
expect(a.types).toContain('T1');
|
||||
expect(a.types['T1']).toEqual(mockData[1]);
|
||||
expect(a.identifiers).toContain('T1');
|
||||
expect(a.identifiers['T1']).toEqual(mockDirMetadata[1]);
|
||||
});
|
||||
|
||||
it('should merge all aliases on addAll', () {
|
||||
|
@ -87,12 +100,12 @@ void allTests() {
|
|||
}
|
||||
|
||||
_checkSimilar(NgMeta a, NgMeta b) {
|
||||
expect(a.types.length).toEqual(b.types.length);
|
||||
expect(a.identifiers.length).toEqual(b.identifiers.length);
|
||||
expect(a.aliases.length).toEqual(b.aliases.length);
|
||||
for (var k in a.types.keys) {
|
||||
expect(b.types).toContain(k);
|
||||
var at = a.types[k];
|
||||
var bt = b.types[k];
|
||||
for (var k in a.identifiers.keys) {
|
||||
expect(b.identifiers).toContain(k);
|
||||
var at = a.identifiers[k];
|
||||
var bt = b.identifiers[k];
|
||||
expect(at.type.name).toEqual(bt.type.name);
|
||||
}
|
||||
for (var k in a.aliases.keys) {
|
||||
|
|
|
@ -27,13 +27,15 @@ void allTests() {
|
|||
var fooNgMeta, fooAssetId;
|
||||
var barNgMeta, barAssetId;
|
||||
var bazNgMeta, bazAssetId;
|
||||
var aliasNgMeta, aliasAssetId;
|
||||
|
||||
/// Call after making changes to `fooNgMeta`, `barNgMeta`, or `bazNgMeta` and
|
||||
/// before trying to read them from `reader`.
|
||||
final updateReader = () => reader
|
||||
..addAsset(fooAssetId, JSON.encode(fooNgMeta.toJson()))
|
||||
..addAsset(barAssetId, JSON.encode(barNgMeta.toJson()))
|
||||
..addAsset(bazAssetId, JSON.encode(bazNgMeta.toJson()));
|
||||
..addAsset(bazAssetId, JSON.encode(bazNgMeta.toJson()))
|
||||
..addAsset(aliasAssetId, JSON.encode(aliasNgMeta.toJson()));
|
||||
|
||||
beforeEach(() {
|
||||
reader = new TestAssetReader();
|
||||
|
@ -41,19 +43,24 @@ void allTests() {
|
|||
// Establish some test NgMeta objects with one Component each.
|
||||
var fooComponentMeta = createFoo(moduleBase);
|
||||
fooNgMeta = new NgMeta(ngDeps: new NgDepsModel());
|
||||
fooNgMeta.types[fooComponentMeta.type.name] = fooComponentMeta;
|
||||
fooNgMeta.identifiers[fooComponentMeta.type.name] = fooComponentMeta;
|
||||
|
||||
var barComponentMeta = createBar(moduleBase);
|
||||
barNgMeta = new NgMeta(ngDeps: new NgDepsModel());
|
||||
barNgMeta.types[barComponentMeta.type.name] = barComponentMeta;
|
||||
barNgMeta.identifiers[barComponentMeta.type.name] = barComponentMeta;
|
||||
|
||||
var bazComponentMeta = createBaz(moduleBase);
|
||||
bazNgMeta = new NgMeta(ngDeps: new NgDepsModel());
|
||||
barNgMeta.types[bazComponentMeta.type.name] = bazComponentMeta;
|
||||
barNgMeta.identifiers[bazComponentMeta.type.name] = bazComponentMeta;
|
||||
|
||||
aliasNgMeta = new NgMeta(ngDeps: new NgDepsModel());
|
||||
aliasNgMeta.aliases["Providers"] = ["someAlias"];
|
||||
aliasNgMeta.definesAlias = true;
|
||||
|
||||
fooAssetId = new AssetId('a', toSummaryExtension('lib/foo.dart'));
|
||||
barAssetId = new AssetId('a', toSummaryExtension('lib/bar.dart'));
|
||||
bazAssetId = new AssetId('a', toSummaryExtension('lib/baz.dart'));
|
||||
aliasAssetId = new AssetId('a', toSummaryExtension('lib/alais.dart'));
|
||||
updateReader();
|
||||
});
|
||||
|
||||
|
@ -63,11 +70,11 @@ void allTests() {
|
|||
updateReader();
|
||||
|
||||
var extracted = await _testLink(reader, fooAssetId);
|
||||
expect(extracted.types).toContain('FooComponent');
|
||||
expect(extracted.types).toContain('BarComponent');
|
||||
expect(extracted.identifiers).toContain('FooComponent');
|
||||
expect(extracted.identifiers).toContain('BarComponent');
|
||||
|
||||
expect(extracted.types['FooComponent'].selector).toEqual('foo');
|
||||
expect(extracted.types['BarComponent'].selector).toEqual('bar');
|
||||
expect(extracted.identifiers['FooComponent'].selector).toEqual('foo');
|
||||
expect(extracted.identifiers['BarComponent'].selector).toEqual('bar');
|
||||
});
|
||||
|
||||
it('should include `DirectiveMetadata` recursively from exported files.',
|
||||
|
@ -77,13 +84,33 @@ void allTests() {
|
|||
updateReader();
|
||||
|
||||
var extracted = await _testLink(reader, fooAssetId);
|
||||
expect(extracted.types).toContain('FooComponent');
|
||||
expect(extracted.types).toContain('BarComponent');
|
||||
expect(extracted.types).toContain('BazComponent');
|
||||
expect(extracted.identifiers).toContain('FooComponent');
|
||||
expect(extracted.identifiers).toContain('BarComponent');
|
||||
expect(extracted.identifiers).toContain('BazComponent');
|
||||
|
||||
expect(extracted.types['FooComponent'].selector).toEqual('foo');
|
||||
expect(extracted.types['BarComponent'].selector).toEqual('bar');
|
||||
expect(extracted.types['BazComponent'].selector).toEqual('baz');
|
||||
expect(extracted.identifiers['FooComponent'].selector).toEqual('foo');
|
||||
expect(extracted.identifiers['BarComponent'].selector).toEqual('bar');
|
||||
expect(extracted.identifiers['BazComponent'].selector).toEqual('baz');
|
||||
});
|
||||
|
||||
it('should include metadata recursively from imported files when they are aliases.',
|
||||
() async {
|
||||
aliasNgMeta.ngDeps.imports.add(new ImportModel()..uri = 'bar.dart');
|
||||
updateReader();
|
||||
|
||||
var extracted = await _testLink(reader, aliasAssetId);
|
||||
expect(extracted.identifiers).toContain('BarComponent');
|
||||
});
|
||||
|
||||
it('should NOT include metadata recursively from imported files when no aliases defined.',
|
||||
() async {
|
||||
fooNgMeta.ngDeps.imports.add(new ImportModel()..uri = 'bar.dart');
|
||||
barNgMeta.ngDeps.imports.add(new ImportModel()..uri = 'baz.dart');
|
||||
updateReader();
|
||||
|
||||
var extracted = await _testLink(reader, fooAssetId);
|
||||
expect(extracted.identifiers).not.toContain('BarComponent');
|
||||
expect(extracted.identifiers).not.toContain('BazComponent');
|
||||
});
|
||||
|
||||
it('should handle `DirectiveMetadata` export cycles gracefully.', () async {
|
||||
|
@ -93,9 +120,9 @@ void allTests() {
|
|||
updateReader();
|
||||
|
||||
var extracted = await _testLink(reader, bazAssetId);
|
||||
expect(extracted.types).toContain('FooComponent');
|
||||
expect(extracted.types).toContain('BarComponent');
|
||||
expect(extracted.types).toContain('BazComponent');
|
||||
expect(extracted.identifiers).toContain('FooComponent');
|
||||
expect(extracted.identifiers).toContain('BarComponent');
|
||||
expect(extracted.identifiers).toContain('BazComponent');
|
||||
});
|
||||
|
||||
it(
|
||||
|
@ -109,11 +136,11 @@ void allTests() {
|
|||
|
||||
var extracted = await _testLink(reader, fooAssetId);
|
||||
|
||||
expect(extracted.types).toContain('FooComponent');
|
||||
expect(extracted.types).toContain('BarComponent');
|
||||
expect(extracted.identifiers).toContain('FooComponent');
|
||||
expect(extracted.identifiers).toContain('BarComponent');
|
||||
|
||||
expect(extracted.types['FooComponent'].selector).toEqual('foo');
|
||||
expect(extracted.types['BarComponent'].selector).toEqual('bar');
|
||||
expect(extracted.identifiers['FooComponent'].selector).toEqual('foo');
|
||||
expect(extracted.identifiers['BarComponent'].selector).toEqual('bar');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:barback/barback.dart';
|
|||
import 'package:dart_style/dart_style.dart';
|
||||
import 'package:guinness/guinness.dart';
|
||||
|
||||
import 'package:angular2/src/compiler/directive_metadata.dart' show CompileIdentifierMetadata;
|
||||
import 'package:angular2/src/core/change_detection/change_detection.dart';
|
||||
import 'package:angular2/src/platform/server/html_adapter.dart';
|
||||
import 'package:angular2/src/core/linker/interfaces.dart' show LifecycleHooks;
|
||||
|
@ -317,10 +318,10 @@ void allTests() {
|
|||
it('should include hooks for implemented types (single)', () async {
|
||||
var ngMeta = await _testCreateModel('interfaces_files/soup.dart');
|
||||
|
||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||
expect(ngMeta.types['ChangingSoupComponent']).toBeNotNull();
|
||||
expect(ngMeta.types['ChangingSoupComponent'].selector).toEqual('[soup]');
|
||||
expect(ngMeta.types['ChangingSoupComponent'].lifecycleHooks)
|
||||
expect(ngMeta.identifiers.isNotEmpty).toBeTrue();
|
||||
expect(ngMeta.identifiers['ChangingSoupComponent']).toBeNotNull();
|
||||
expect(ngMeta.identifiers['ChangingSoupComponent'].selector).toEqual('[soup]');
|
||||
expect(ngMeta.identifiers['ChangingSoupComponent'].lifecycleHooks)
|
||||
.toContain(LifecycleHooks.OnChanges);
|
||||
});
|
||||
|
||||
|
@ -328,10 +329,10 @@ void allTests() {
|
|||
var ngMeta = await _testCreateModel(
|
||||
'multiple_interface_lifecycle_files/soup.dart');
|
||||
|
||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||
expect(ngMeta.types['MultiSoupComponent']).toBeNotNull();
|
||||
expect(ngMeta.types['MultiSoupComponent'].selector).toEqual('[soup]');
|
||||
expect(ngMeta.types['MultiSoupComponent'].lifecycleHooks)
|
||||
expect(ngMeta.identifiers.isNotEmpty).toBeTrue();
|
||||
expect(ngMeta.identifiers['MultiSoupComponent']).toBeNotNull();
|
||||
expect(ngMeta.identifiers['MultiSoupComponent'].selector).toEqual('[soup]');
|
||||
expect(ngMeta.identifiers['MultiSoupComponent'].lifecycleHooks)
|
||||
..toContain(LifecycleHooks.OnChanges)
|
||||
..toContain(LifecycleHooks.OnDestroy)
|
||||
..toContain(LifecycleHooks.OnInit);
|
||||
|
@ -345,18 +346,18 @@ void allTests() {
|
|||
'absolute_url_expression_files/hello.dart',
|
||||
reader: fakeReader);
|
||||
|
||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||
expect(ngMeta.types['HelloCmp']).toBeNotNull();
|
||||
expect(ngMeta.types['HelloCmp'].selector).toEqual('hello-app');
|
||||
expect(ngMeta.identifiers.isNotEmpty).toBeTrue();
|
||||
expect(ngMeta.identifiers['HelloCmp']).toBeNotNull();
|
||||
expect(ngMeta.identifiers['HelloCmp'].selector).toEqual('hello-app');
|
||||
});
|
||||
|
||||
it('should populate all provided values for Components & Directives',
|
||||
() async {
|
||||
var ngMeta = await _testCreateModel('unusual_component_files/hello.dart');
|
||||
|
||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||
expect(ngMeta.identifiers.isNotEmpty).toBeTrue();
|
||||
|
||||
var component = ngMeta.types['UnusualComp'];
|
||||
var component = ngMeta.identifiers['UnusualComp'];
|
||||
expect(component).toBeNotNull();
|
||||
expect(component.selector).toEqual('unusual-comp');
|
||||
expect(component.isComponent).toBeTrue();
|
||||
|
@ -370,7 +371,7 @@ void allTests() {
|
|||
expect(component.hostAttributes).toContain('hostKey');
|
||||
expect(component.hostAttributes['hostKey']).toEqual('hostValue');
|
||||
|
||||
var directive = ngMeta.types['UnusualDirective'];
|
||||
var directive = ngMeta.identifiers['UnusualDirective'];
|
||||
expect(directive).toBeNotNull();
|
||||
expect(directive.selector).toEqual('unusual-directive');
|
||||
expect(directive.isComponent).toBeFalse();
|
||||
|
@ -388,10 +389,10 @@ void allTests() {
|
|||
it('should include hooks for implemented types (single)', () async {
|
||||
var ngMeta = await _testCreateModel('interfaces_files/soup.dart');
|
||||
|
||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||
expect(ngMeta.types['ChangingSoupComponent']).toBeNotNull();
|
||||
expect(ngMeta.types['ChangingSoupComponent'].selector).toEqual('[soup]');
|
||||
expect(ngMeta.types['ChangingSoupComponent'].lifecycleHooks)
|
||||
expect(ngMeta.identifiers.isNotEmpty).toBeTrue();
|
||||
expect(ngMeta.identifiers['ChangingSoupComponent']).toBeNotNull();
|
||||
expect(ngMeta.identifiers['ChangingSoupComponent'].selector).toEqual('[soup]');
|
||||
expect(ngMeta.identifiers['ChangingSoupComponent'].lifecycleHooks)
|
||||
.toContain(LifecycleHooks.OnChanges);
|
||||
});
|
||||
|
||||
|
@ -399,10 +400,10 @@ void allTests() {
|
|||
var ngMeta = await _testCreateModel(
|
||||
'multiple_interface_lifecycle_files/soup.dart');
|
||||
|
||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||
expect(ngMeta.types['MultiSoupComponent']).toBeNotNull();
|
||||
expect(ngMeta.types['MultiSoupComponent'].selector).toEqual('[soup]');
|
||||
expect(ngMeta.types['MultiSoupComponent'].lifecycleHooks)
|
||||
expect(ngMeta.identifiers.isNotEmpty).toBeTrue();
|
||||
expect(ngMeta.identifiers['MultiSoupComponent']).toBeNotNull();
|
||||
expect(ngMeta.identifiers['MultiSoupComponent'].selector).toEqual('[soup]');
|
||||
expect(ngMeta.identifiers['MultiSoupComponent'].lifecycleHooks)
|
||||
..toContain(LifecycleHooks.OnChanges)
|
||||
..toContain(LifecycleHooks.OnDestroy)
|
||||
..toContain(LifecycleHooks.OnInit);
|
||||
|
@ -416,10 +417,10 @@ void allTests() {
|
|||
'absolute_url_expression_files/hello.dart',
|
||||
reader: fakeReader);
|
||||
|
||||
expect(ngMeta.types.isNotEmpty).toBeTrue();
|
||||
expect(ngMeta.types['HelloCmp']).toBeNotNull();
|
||||
expect(ngMeta.types['HelloCmp'].template).toBeNotNull();
|
||||
expect(ngMeta.types['HelloCmp'].template.templateUrl)
|
||||
expect(ngMeta.identifiers.isNotEmpty).toBeTrue();
|
||||
expect(ngMeta.identifiers['HelloCmp']).toBeNotNull();
|
||||
expect(ngMeta.identifiers['HelloCmp'].template).toBeNotNull();
|
||||
expect(ngMeta.identifiers['HelloCmp'].template.templateUrl)
|
||||
.toEqual('asset:other_package/lib/template.html');
|
||||
});
|
||||
|
||||
|
@ -445,6 +446,49 @@ void allTests() {
|
|||
});
|
||||
});
|
||||
|
||||
describe("identifiers", () {
|
||||
it("should populate `identifier` with class types.", () async {
|
||||
var model = (await _testCreateModel('identifiers/classes.dart'));
|
||||
final moduleUrl = "asset:angular2/test/transform/directive_processor/identifiers/classes.dart";
|
||||
expect(model.identifiers['Service1'].name).toEqual('Service1');
|
||||
expect(model.identifiers['Service1'].moduleUrl).toEqual(moduleUrl);
|
||||
expect(model.identifiers['Service2'].name).toEqual('Service2');
|
||||
expect(model.identifiers['Service2'].moduleUrl).toEqual(moduleUrl);
|
||||
});
|
||||
|
||||
it("should populate `identifier` with constants.", () async {
|
||||
var model = (await _testCreateModel('identifiers/constants.dart'));
|
||||
final moduleUrl = "asset:angular2/test/transform/directive_processor/identifiers/constants.dart";
|
||||
expect(model.identifiers['a']).
|
||||
toHaveSameProps(new CompileIdentifierMetadata(name: 'a', moduleUrl: moduleUrl));
|
||||
expect(model.identifiers['b']).
|
||||
toHaveSameProps(new CompileIdentifierMetadata(name: 'b', moduleUrl: moduleUrl));
|
||||
expect(model.identifiers['c']).toBeNull();
|
||||
});
|
||||
|
||||
it("should populate `identifier` with class names that do not have @Injectable;'.", () async {
|
||||
var model = (await _testCreateModel('identifiers/classes_no_injectable.dart'));
|
||||
final moduleUrl = "asset:angular2/test/transform/directive_processor/identifiers/classes_no_injectable.dart";
|
||||
expect(model.identifiers['ClassA']).
|
||||
toHaveSameProps(new CompileIdentifierMetadata(name: 'ClassA', moduleUrl: moduleUrl));
|
||||
});
|
||||
|
||||
it("should populate `identifier` with typedefs.", () async {
|
||||
var model = (await _testCreateModel('identifiers/typedefs.dart'));
|
||||
final moduleUrl = "asset:angular2/test/transform/directive_processor/identifiers/typedefs.dart";
|
||||
expect(model.identifiers['TypeDef']).
|
||||
toHaveSameProps(new CompileIdentifierMetadata(name: 'TypeDef', moduleUrl: moduleUrl));
|
||||
});
|
||||
|
||||
it("should populate `identifier` with enums.", () async {
|
||||
var model = (await _testCreateModel('identifiers/enums.dart'));
|
||||
final moduleUrl = "asset:angular2/test/transform/directive_processor/identifiers/enums.dart";
|
||||
|
||||
expect(model.identifiers['Enum']).
|
||||
toHaveSameProps(new CompileIdentifierMetadata(name: 'Enum', moduleUrl: moduleUrl));
|
||||
});
|
||||
});
|
||||
|
||||
describe('directives', () {
|
||||
final reflectableNamed = (NgDepsModel model, String name) {
|
||||
return model.reflectables
|
||||
|
@ -537,27 +581,128 @@ void allTests() {
|
|||
..prefix = 'dep2');
|
||||
});
|
||||
|
||||
it('should populate `diDependency`.',
|
||||
() async {
|
||||
var cmp =
|
||||
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithDiDeps'];
|
||||
|
||||
expect(cmp).toBeNotNull();
|
||||
var deps = cmp.type.diDeps;
|
||||
expect(deps).toBeNotNull();
|
||||
expect(deps.length).toEqual(2);
|
||||
expect(deps[0].token.name).toEqual("ServiceDep");
|
||||
expect(deps[1].token.name).toEqual("ServiceDep");
|
||||
});
|
||||
|
||||
it('should populate `diDependency` using a string token.',
|
||||
() async {
|
||||
var cmp =
|
||||
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithDiDepsStrToken'];
|
||||
|
||||
var deps = cmp.type.diDeps;
|
||||
expect(deps).toBeNotNull();
|
||||
expect(deps.length).toEqual(1);
|
||||
expect(deps[0].token).toEqual("StringDep");
|
||||
});
|
||||
|
||||
it('should populate `services`.',
|
||||
() async {
|
||||
var service =
|
||||
(await _testCreateModel('directives_files/services.dart')).identifiers['Service'];
|
||||
|
||||
expect(service).toBeNotNull();
|
||||
|
||||
var deps = service.diDeps;
|
||||
expect(deps).toBeNotNull();
|
||||
expect(deps.length).toEqual(2);
|
||||
expect(deps[0].token.name).toEqual("ServiceDep");
|
||||
expect(deps[1].token.name).toEqual("ServiceDep");
|
||||
});
|
||||
|
||||
it('should populate `providers` using types.',
|
||||
() async {
|
||||
var cmp =
|
||||
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithProvidersTypes'];
|
||||
|
||||
expect(cmp).toBeNotNull();
|
||||
expect(cmp.providers).toBeNotNull();
|
||||
expect(cmp.providers.length).toEqual(2);
|
||||
|
||||
var firstToken = cmp.providers.first.token;
|
||||
expect(firstToken.prefix).toEqual(null);
|
||||
expect(firstToken.name).toEqual("ServiceDep");
|
||||
|
||||
var secondToken = cmp.providers[1].token;
|
||||
expect(secondToken.prefix).toEqual("dep2");
|
||||
expect(secondToken.name).toEqual("ServiceDep");
|
||||
});
|
||||
|
||||
it('should populate `providers` using useClass.',
|
||||
() async {
|
||||
var cmp =
|
||||
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithProvidersUseClass'];
|
||||
|
||||
expect(cmp).toBeNotNull();
|
||||
expect(cmp.providers).toBeNotNull();
|
||||
expect(cmp.providers.length).toEqual(1);
|
||||
|
||||
var token = cmp.providers.first.token;
|
||||
var useClass = cmp.providers.first.useClass;
|
||||
expect(token.prefix).toEqual(null);
|
||||
expect(token.name).toEqual("ServiceDep");
|
||||
|
||||
expect(useClass.prefix).toEqual(null);
|
||||
expect(useClass.name).toEqual("ServiceDep");
|
||||
});
|
||||
|
||||
it('should populate `providers` using a string token.',
|
||||
() async {
|
||||
var cmp =
|
||||
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithProvidersStringToken'];
|
||||
|
||||
expect(cmp).toBeNotNull();
|
||||
expect(cmp.providers).toBeNotNull();
|
||||
expect(cmp.providers.length).toEqual(1);
|
||||
|
||||
var token = cmp.providers.first.token;
|
||||
expect(token).toEqual("StringDep");
|
||||
});
|
||||
|
||||
it('should populate `providers` using a const token.',
|
||||
() async {
|
||||
var cmp =
|
||||
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithProvidersConstToken'];
|
||||
|
||||
expect(cmp).toBeNotNull();
|
||||
expect(cmp.providers).toBeNotNull();
|
||||
expect(cmp.providers.length).toEqual(1);
|
||||
|
||||
var token = cmp.providers.first.token;
|
||||
expect(token.name).toEqual("ServiceDep");
|
||||
expect(token.constConstructor).toEqual(true);
|
||||
});
|
||||
|
||||
it('should merge `outputs` from the annotation and fields.', () async {
|
||||
var model = await _testCreateModel('directives_files/components.dart');
|
||||
expect(model.types['ComponentWithOutputs'].outputs).toEqual(
|
||||
expect(model.identifiers['ComponentWithOutputs'].outputs).toEqual(
|
||||
{'a': 'a', 'b': 'b', 'c': 'renamed', 'd': 'd', 'e': 'get-renamed'});
|
||||
});
|
||||
|
||||
it('should merge `inputs` from the annotation and fields.', () async {
|
||||
var model = await _testCreateModel('directives_files/components.dart');
|
||||
expect(model.types['ComponentWithInputs'].inputs).toEqual(
|
||||
expect(model.identifiers['ComponentWithInputs'].inputs).toEqual(
|
||||
{'a': 'a', 'b': 'b', 'c': 'renamed', 'd': 'd', 'e': 'set-renamed'});
|
||||
});
|
||||
|
||||
it('should merge host bindings from the annotation and fields.', () async {
|
||||
var model = await _testCreateModel('directives_files/components.dart');
|
||||
expect(model.types['ComponentWithHostBindings'].hostProperties)
|
||||
expect(model.identifiers['ComponentWithHostBindings'].hostProperties)
|
||||
.toEqual({'a': 'a', 'b': 'b', 'renamed': 'c', 'd': 'd', 'get-renamed': 'e'});
|
||||
});
|
||||
|
||||
it('should merge host listeners from the annotation and fields.', () async {
|
||||
var model = await _testCreateModel('directives_files/components.dart');
|
||||
expect(model.types['ComponentWithHostListeners'].hostListeners).toEqual({
|
||||
expect(model.identifiers['ComponentWithHostListeners'].hostListeners).toEqual({
|
||||
'a': 'onA()',
|
||||
'b': 'onB()',
|
||||
'c': 'onC(\$event.target,\$event.target.value)'
|
||||
|
@ -617,13 +762,13 @@ void allTests() {
|
|||
describe('pipes', () {
|
||||
it('should read the pipe name', () async {
|
||||
var model = await _testCreateModel('pipe_files/pipes.dart');
|
||||
expect(model.types['NameOnlyPipe'].name).toEqual('nameOnly');
|
||||
expect(model.types['NameOnlyPipe'].pure).toBe(false);
|
||||
expect(model.identifiers['NameOnlyPipe'].name).toEqual('nameOnly');
|
||||
expect(model.identifiers['NameOnlyPipe'].pure).toBe(false);
|
||||
});
|
||||
|
||||
it('should read the pure flag', () async {
|
||||
var model = await _testCreateModel('pipe_files/pipes.dart');
|
||||
expect(model.types['NameAndPurePipe'].pure).toBe(true);
|
||||
expect(model.identifiers['NameAndPurePipe'].pure).toBe(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
library angular2.test.transform.directive_processor.directive_files.components;
|
||||
|
||||
import 'package:angular2/angular2.dart'
|
||||
show Component, Directive, View, NgElement, Output, Input;
|
||||
show Component, Directive, View, NgElement, Output, Input, Provider;
|
||||
import 'dep1.dart';
|
||||
import 'dep2.dart' as dep2;
|
||||
|
||||
|
@ -84,3 +84,43 @@ class ComponentWithHostListeners {
|
|||
@HostListener('c', ['\$event.target', '\$event.target.value']) void onC(
|
||||
t, v) {}
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'component-with-providers-types',
|
||||
template: '',
|
||||
providers: [ServiceDep, dep2.ServiceDep])
|
||||
class ComponentWithProvidersTypes {}
|
||||
|
||||
@Component(
|
||||
selector: 'component-with-providers-string-token',
|
||||
template: '',
|
||||
providers: [const Provider("StringDep", useClass: ServiceDep)])
|
||||
class ComponentWithProvidersStringToken {}
|
||||
|
||||
@Component(
|
||||
selector: 'ComponentWithProvidersConstToken',
|
||||
template: '',
|
||||
providers: [const Provider(const ServiceDep(), useClass: ServiceDep)])
|
||||
class ComponentWithProvidersConstToken {
|
||||
ComponentWithProvidersConstToken();
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'component-with-providers-use-class',
|
||||
template: '',
|
||||
providers: [const Provider(ServiceDep, useClass: ServiceDep)])
|
||||
class ComponentWithProvidersUseClass {}
|
||||
|
||||
@Component(
|
||||
selector: 'component-with-di-deps',
|
||||
template: '')
|
||||
class ComponentWithDiDeps {
|
||||
ComponentWithDiDeps(ServiceDep arg1, @Inject(ServiceDep) arg2);
|
||||
}
|
||||
|
||||
@Component(
|
||||
selector: 'component-with-di-deps-string-token',
|
||||
template: '')
|
||||
class ComponentWithDiDepsStrToken {
|
||||
ComponentWithDiDepsStrToken(@Inject("StringDep") arg1);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
library angular2.test.transform.directive_processor.directive_files.dep1;
|
||||
|
||||
import 'package:angular2/angular2.dart' show Component, Directive, View, Pipe;
|
||||
import 'package:angular2/angular2.dart' show Component, Directive, View, Pipe, Injectable;
|
||||
|
||||
@Component(selector: 'dep1')
|
||||
@View(template: 'Dep1')
|
||||
|
@ -8,3 +8,8 @@ class Dep {}
|
|||
|
||||
@Pipe(name: 'dep1')
|
||||
class PipeDep {}
|
||||
|
||||
@Injectable()
|
||||
class ServiceDep {
|
||||
const ServiceDep();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
library angular2.test.transform.directive_processor.directive_files.dep2;
|
||||
|
||||
import 'package:angular2/angular2.dart' show Component, Directive, View, Pipe;
|
||||
import 'package:angular2/angular2.dart' show Component, Directive, View, Pipe, Injectable;
|
||||
|
||||
@Component(selector: 'dep2')
|
||||
@View(template: 'Dep2')
|
||||
|
@ -8,3 +8,6 @@ class Dep {}
|
|||
|
||||
@Pipe(name: 'dep2')
|
||||
class PipeDep {}
|
||||
|
||||
@Injectable()
|
||||
class ServiceDep {}
|
|
@ -0,0 +1,10 @@
|
|||
library angular2.test.transform.directive_processor.directive_files.components;
|
||||
|
||||
import 'package:angular2/angular2.dart'
|
||||
show Injectable, Inject;
|
||||
import 'dep1.dart';
|
||||
|
||||
@Injectable()
|
||||
class Service {
|
||||
Service(ServiceDep arg1, @Inject(ServiceDep) arg2);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
library angular2.test.transform.directive_processor.identifiers.classes;
|
||||
|
||||
import 'package:angular2/angular2.dart' show Injectable;
|
||||
|
||||
@Injectable()
|
||||
class Service1 {}
|
||||
|
||||
@Injectable()
|
||||
class Service2 {}
|
||||
|
||||
class Service3 {}
|
|
@ -0,0 +1,3 @@
|
|||
library angular2.test.transform.directive_processor.identifiers.classes_no_injectable;
|
||||
|
||||
abstract class ClassA {}
|
|
@ -0,0 +1,5 @@
|
|||
library angular2.test.transform.directive_processor.identifiers.constants;
|
||||
|
||||
const a = "a";
|
||||
const b = "b";
|
||||
var c = "c";
|
|
@ -0,0 +1,5 @@
|
|||
library angular2.test.transform.directive_processor.identifiers.enums;
|
||||
|
||||
enum Enum {
|
||||
one
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
library angular2.test.transform.directive_processor.identifiers.typedefs;
|
||||
|
||||
typedef String TypeDef(String);
|
|
@ -5,6 +5,7 @@ import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
|||
import 'package:angular2/src/core/metadata.dart';
|
||||
import 'foo.dart';
|
||||
import 'package:angular2/src/core/metadata.template.dart' as i0;
|
||||
import 'foo.template.dart' as i1;
|
||||
export 'bar.dart';
|
||||
|
||||
var _visited = false;
|
||||
|
@ -22,4 +23,5 @@ void initReflector() {
|
|||
const [MyContext]
|
||||
], (MyContext c) => new MyComponent(c)));
|
||||
i0.initReflector();
|
||||
i1.initReflector();
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ import 'foo.dart' as prefix;
|
|||
@View(template: '')
|
||||
class MyComponent {
|
||||
final prefix.MyContext c;
|
||||
final String generatedValue;
|
||||
MyComponent(this.c, String inValue) {
|
||||
generatedValue = 'generated ' + inValue;
|
||||
final prefix.MyDep generatedValue;
|
||||
MyComponent(this.c, prefix.MyDep inValue) {
|
||||
generatedValue = inValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:angular2/src/core/reflection/reflection.dart' as _ngRef;
|
|||
import 'package:angular2/src/core/metadata.dart';
|
||||
import 'foo.dart' as prefix;
|
||||
import 'package:angular2/src/core/metadata.template.dart' as i0;
|
||||
import 'foo.template.dart' as i1;
|
||||
export 'bar.dart';
|
||||
|
||||
var _visited = false;
|
||||
|
@ -16,15 +17,16 @@ void initReflector() {
|
|||
MyComponent,
|
||||
new _ngRef.ReflectionInfo(
|
||||
const [
|
||||
const Component(selector: 'soup'),
|
||||
const View(template: ''),
|
||||
hostViewFactory_MyComponent
|
||||
],
|
||||
const Component(selector: 'soup'),
|
||||
const View(template: ''),
|
||||
hostViewFactory_MyComponent
|
||||
],
|
||||
const [
|
||||
const [prefix.MyContext],
|
||||
const [String]
|
||||
],
|
||||
(prefix.MyContext c, String inValue) =>
|
||||
new MyComponent(c, inValue)));
|
||||
const [prefix.MyContext],
|
||||
const [prefix.MyDep]
|
||||
],
|
||||
(prefix.MyContext c, prefix.MyDep inValue) =>
|
||||
new MyComponent(c, inValue)));
|
||||
i0.initReflector();
|
||||
}
|
||||
i1.initReflector();
|
||||
}
|
|
@ -1,6 +1,11 @@
|
|||
library foo;
|
||||
|
||||
import 'package:angular2/angular2.dart';
|
||||
|
||||
@Injectable()
|
||||
class MyDep {}
|
||||
|
||||
class MyContext {
|
||||
final String selector;
|
||||
final MyDep selector;
|
||||
const MyContext(this.selector);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,9 @@ import 'package:angular2/src/transform/common/code/ng_deps_code.dart';
|
|||
import 'package:angular2/src/transform/common/code/source_module.dart';
|
||||
import 'package:angular2/src/transform/common/zone.dart' as zone;
|
||||
import 'package:angular2/src/transform/template_compiler/generator.dart';
|
||||
import 'package:angular2/src/transform/template_compiler/compile_data_creator.dart';
|
||||
|
||||
import 'package:angular2/src/transform/common/model/parameter_model.pb.dart';
|
||||
import '../common/compile_directive_metadata/ng_for.ng_meta.dart' as ngMeta;
|
||||
import '../common/ng_meta_helper.dart';
|
||||
import '../common/read_file.dart';
|
||||
|
@ -57,7 +59,7 @@ void allTests() {
|
|||
fooNgMeta = new NgMeta(ngDeps: new NgDepsModel()
|
||||
..libraryUri = 'test.foo'
|
||||
..reflectables.add(new ReflectionInfoModel()..name = fooComponentMeta.type.name));
|
||||
fooNgMeta.types[fooComponentMeta.type.name] = fooComponentMeta;
|
||||
fooNgMeta.identifiers[fooComponentMeta.type.name] = fooComponentMeta;
|
||||
|
||||
barComponentMeta = createBar(moduleBase);
|
||||
barPipeMeta = createBarPipe(moduleBase);
|
||||
|
@ -65,14 +67,14 @@ void allTests() {
|
|||
..libraryUri = 'test.bar'
|
||||
..reflectables.add(new ReflectionInfoModel()..name = barPipeMeta.type.name)
|
||||
..reflectables.add(new ReflectionInfoModel()..name = barComponentMeta.type.name));
|
||||
barNgMeta.types[barComponentMeta.type.name] = barComponentMeta;
|
||||
barNgMeta.types[barPipeMeta.type.name] = barPipeMeta;
|
||||
barNgMeta.identifiers[barComponentMeta.type.name] = barComponentMeta;
|
||||
barNgMeta.identifiers[barPipeMeta.type.name] = barPipeMeta;
|
||||
|
||||
bazComponentMeta = createBaz(moduleBase);
|
||||
bazNgMeta = new NgMeta(ngDeps: new NgDepsModel()
|
||||
..libraryUri = 'test.baz'
|
||||
..reflectables.add(new ReflectionInfoModel()..name = bazComponentMeta.type.name));
|
||||
barNgMeta.types[bazComponentMeta.type.name] = bazComponentMeta;
|
||||
barNgMeta.identifiers[bazComponentMeta.type.name] = bazComponentMeta;
|
||||
|
||||
fooAssetId = new AssetId('a', 'lib/foo.ng_meta.json');
|
||||
barAssetId = new AssetId('a', 'lib/bar.ng_meta.json');
|
||||
|
@ -114,6 +116,145 @@ void allTests() {
|
|||
expect(_generatedCode(outputs)).not.toContain('notifyDispatcher');
|
||||
});
|
||||
|
||||
it('should generate generate diDeps of injectable services.', () async {
|
||||
bazNgMeta.identifiers['Service2'] = new CompileTypeMetadata(
|
||||
name: 'Service2',
|
||||
moduleUrl: 'moduleUrl');
|
||||
|
||||
barNgMeta.identifiers['Service'] = new CompileTypeMetadata(
|
||||
name: 'Service',
|
||||
moduleUrl: 'moduleUrl',
|
||||
diDeps: [new CompileDiDependencyMetadata(token: new CompileIdentifierMetadata(name: 'Service2'))]);
|
||||
barNgMeta.ngDeps.imports.add(new ImportModel()..uri = 'package:a/baz.dart');
|
||||
|
||||
fooComponentMeta.template = new CompileTemplateMetadata(template: "import 'bar.dart';");
|
||||
fooComponentMeta.providers = [
|
||||
new CompileProviderMetadata(
|
||||
token: new CompileIdentifierMetadata(name: 'Service'),
|
||||
useClass: new CompileTypeMetadata(name: 'Service')
|
||||
)
|
||||
];
|
||||
|
||||
final viewAnnotation = new AnnotationModel()..name = 'View'..isView = true;
|
||||
final reflectable = fooNgMeta.ngDeps.reflectables.first;
|
||||
reflectable.annotations.add(viewAnnotation);
|
||||
fooNgMeta.ngDeps.imports.add(new ImportModel()..uri = 'package:a/bar.dart');
|
||||
|
||||
updateReader();
|
||||
|
||||
final viewDefResults = await createCompileData(reader, fooAssetId, [], []);
|
||||
final cmp = viewDefResults.viewDefinitions.values.first.component;
|
||||
|
||||
expect(cmp.providers.length).toEqual(1);
|
||||
|
||||
expect(cmp.providers[0].useClass.name).toEqual("Service");
|
||||
expect(cmp.providers[0].useClass.diDeps.first.token.name).toEqual("Service2");
|
||||
});
|
||||
|
||||
it('should generate providers from types.', () async {
|
||||
barNgMeta.identifiers['Service'] = new CompileTypeMetadata(name: 'Service', moduleUrl: 'moduleUrl');
|
||||
|
||||
fooComponentMeta.template = new CompileTemplateMetadata(template: "import 'bar.dart';");
|
||||
fooComponentMeta.providers = [new CompileProviderMetadata(token: new CompileIdentifierMetadata(name: 'Service'))];
|
||||
fooComponentMeta.type.diDeps = [new CompileDiDependencyMetadata(token: new CompileIdentifierMetadata(name: 'Service'))];
|
||||
|
||||
final viewAnnotation = new AnnotationModel()..name = 'View'..isView = true;
|
||||
final reflectable = fooNgMeta.ngDeps.reflectables.first;
|
||||
reflectable.annotations.add(viewAnnotation);
|
||||
fooNgMeta.ngDeps.imports.add(new ImportModel()..uri = 'package:a/bar.dart');
|
||||
|
||||
updateReader();
|
||||
|
||||
final viewDefResults = await createCompileData(reader, fooAssetId, [], []);
|
||||
final cmp = viewDefResults.viewDefinitions.values.first.component;
|
||||
|
||||
expect(cmp.providers.length).toEqual(1);
|
||||
|
||||
expect(cmp.providers[0].token.name).toEqual("Service");
|
||||
expect(cmp.providers[0].token.moduleUrl).toEqual("moduleUrl");
|
||||
|
||||
expect(cmp.type.diDeps.length).toEqual(1);
|
||||
expect(cmp.type.diDeps[0].token.name).toEqual("Service");
|
||||
expect(cmp.type.diDeps[0].token.moduleUrl).toEqual("moduleUrl");
|
||||
});
|
||||
|
||||
it('should generate providers from Provider objects (references).', () async {
|
||||
barNgMeta.identifiers['Service1'] = new CompileTypeMetadata(name: 'Service1', moduleUrl: 'moduleUrl');
|
||||
barNgMeta.identifiers['Service2'] = new CompileTypeMetadata(name: 'Service2', moduleUrl: 'moduleUrl');
|
||||
|
||||
fooComponentMeta.template = new CompileTemplateMetadata(template: "import 'bar.dart';");
|
||||
fooComponentMeta.providers = [new CompileProviderMetadata(token: new CompileIdentifierMetadata(name: 'Service1'), useClass:
|
||||
new CompileTypeMetadata(name: 'Service2'))];
|
||||
|
||||
final viewAnnotation = new AnnotationModel()..name = 'View'..isView = true;
|
||||
final reflectable = fooNgMeta.ngDeps.reflectables.first;
|
||||
reflectable.annotations.add(viewAnnotation);
|
||||
fooNgMeta.ngDeps.imports.add(new ImportModel()..uri = 'package:a/bar.dart');
|
||||
|
||||
updateReader();
|
||||
|
||||
final viewDefResults = await createCompileData(reader, fooAssetId, [], []);
|
||||
final cmp = viewDefResults.viewDefinitions.values.first.component;
|
||||
|
||||
expect(cmp.providers.length).toEqual(1);
|
||||
|
||||
expect(cmp.providers[0].token.name).toEqual("Service1");
|
||||
expect(cmp.providers[0].token.moduleUrl).toEqual("moduleUrl");
|
||||
expect(cmp.providers[0].useClass.name).toEqual("Service2");
|
||||
expect(cmp.providers[0].useClass.moduleUrl).toEqual("moduleUrl");
|
||||
});
|
||||
|
||||
it('should generate providers from Provider objects (literals).', () async {
|
||||
barNgMeta.identifiers['Service'] = new CompileTypeMetadata(name: 'Service', moduleUrl: 'moduleUrl');
|
||||
|
||||
fooComponentMeta.template = new CompileTemplateMetadata(template: "import 'bar.dart';");
|
||||
fooComponentMeta.providers = [new CompileProviderMetadata(token: "StrService", useClass:
|
||||
new CompileTypeMetadata(name: 'Service'))];
|
||||
fooComponentMeta.type.diDeps = [new CompileDiDependencyMetadata(token: "StrService")];
|
||||
|
||||
final viewAnnotation = new AnnotationModel()..name = 'View'..isView = true;
|
||||
final reflectable = fooNgMeta.ngDeps.reflectables.first;
|
||||
reflectable.annotations.add(viewAnnotation);
|
||||
fooNgMeta.ngDeps.imports.add(new ImportModel()..uri = 'package:a/bar.dart');
|
||||
|
||||
updateReader();
|
||||
|
||||
final viewDefResults = await createCompileData(reader, fooAssetId, [], []);
|
||||
final cmp = viewDefResults.viewDefinitions.values.first.component;
|
||||
|
||||
expect(cmp.providers.length).toEqual(1);
|
||||
|
||||
expect(cmp.providers[0].token).toEqual("StrService");
|
||||
expect(cmp.providers[0].useClass.name).toEqual("Service");
|
||||
expect(cmp.providers[0].useClass.moduleUrl).toEqual("moduleUrl");
|
||||
|
||||
expect(cmp.type.diDeps.length).toEqual(1);
|
||||
expect(cmp.type.diDeps[0].token).toEqual("StrService");
|
||||
});
|
||||
|
||||
it('should include providers mentioned in aliases.', () async {
|
||||
barNgMeta.identifiers['Service'] = new CompileTypeMetadata(name: 'Service', moduleUrl: 'moduleUrl');
|
||||
|
||||
fooComponentMeta.template = new CompileTemplateMetadata(template: "import 'bar.dart';");
|
||||
|
||||
fooNgMeta.aliases['providerAlias'] = ['Service'];
|
||||
|
||||
fooComponentMeta.providers = [new CompileProviderMetadata(token: new CompileIdentifierMetadata(name: 'providerAlias'))];
|
||||
|
||||
final viewAnnotation = new AnnotationModel()..name = 'View'..isView = true;
|
||||
final reflectable = fooNgMeta.ngDeps.reflectables.first;
|
||||
reflectable.annotations.add(viewAnnotation);
|
||||
fooNgMeta.ngDeps.imports.add(new ImportModel()..uri = 'package:a/bar.dart');
|
||||
|
||||
updateReader();
|
||||
|
||||
final viewDefResults = await createCompileData(reader, fooAssetId, [], []);
|
||||
final cmp = viewDefResults.viewDefinitions.values.first.component;
|
||||
|
||||
expect(cmp.providers.length).toEqual(1);
|
||||
expect(cmp.providers[0].token.name).toEqual("Service");
|
||||
});
|
||||
|
||||
it('should parse simple expressions in inline templates.', () async {
|
||||
fooComponentMeta.template = new CompileTemplateMetadata(
|
||||
template: '<div [a]="b">{{greeting}}</div>',
|
||||
|
@ -369,7 +510,7 @@ void allTests() {
|
|||
..name = 'View'
|
||||
..isView = true;
|
||||
|
||||
barNgMeta.types['PLATFORM'] = barComponentMeta;
|
||||
barNgMeta.identifiers['PLATFORM'] = barComponentMeta;
|
||||
updateReader();
|
||||
|
||||
final outputs = await process(fooAssetId,
|
||||
|
|
|
@ -835,8 +835,12 @@ const COMPILER = [
|
|||
'BoundTextAst.visit(visitor:TemplateAstVisitor, context:any):any',
|
||||
'CompileDirectiveMetadata',
|
||||
'CompileDirectiveMetadata.changeDetection:ChangeDetectionStrategy',
|
||||
'CompileDirectiveMetadata.constructor({type,isComponent,dynamicLoadable,selector,exportAs,changeDetection,inputs,outputs,hostListeners,hostProperties,hostAttributes,lifecycleHooks,template}:{type?:CompileTypeMetadata, isComponent?:boolean, dynamicLoadable?:boolean, selector?:string, exportAs?:string, changeDetection?:ChangeDetectionStrategy, inputs?:{[key:string]:string}, outputs?:{[key:string]:string}, hostListeners?:{[key:string]:string}, hostProperties?:{[key:string]:string}, hostAttributes?:{[key:string]:string}, lifecycleHooks?:LifecycleHooks[], template?:CompileTemplateMetadata})',
|
||||
'CompileDirectiveMetadata.create({type,isComponent,dynamicLoadable,selector,exportAs,changeDetection,inputs,outputs,host,lifecycleHooks,template}:{type?:CompileTypeMetadata, isComponent?:boolean, dynamicLoadable?:boolean, selector?:string, exportAs?:string, changeDetection?:ChangeDetectionStrategy, inputs?:string[], outputs?:string[], host?:{[key:string]:string}, lifecycleHooks?:LifecycleHooks[], template?:CompileTemplateMetadata}):CompileDirectiveMetadata',
|
||||
'CompileDirectiveMetadata.constructor({type,isComponent,dynamicLoadable,selector,exportAs,changeDetection,inputs,outputs,hostListeners,hostProperties,hostAttributes,lifecycleHooks,providers,viewProviders,queries,viewQueries,template}:{type?:CompileTypeMetadata, isComponent?:boolean, dynamicLoadable?:boolean, selector?:string, exportAs?:string, changeDetection?:ChangeDetectionStrategy, inputs?:{[key:string]:string}, outputs?:{[key:string]:string}, hostListeners?:{[key:string]:string}, hostProperties?:{[key:string]:string}, hostAttributes?:{[key:string]:string}, lifecycleHooks?:LifecycleHooks[], providers?:Array<CompileProviderMetadata|CompileTypeMetadata|any[]>, viewProviders?:Array<CompileProviderMetadata|CompileTypeMetadata|any[]>, queries?:CompileQueryMetadata[], viewQueries?:CompileQueryMetadata[], template?:CompileTemplateMetadata})',
|
||||
'CompileDirectiveMetadata.create({type,isComponent,dynamicLoadable,selector,exportAs,changeDetection,inputs,outputs,host,lifecycleHooks,providers,viewProviders,queries,viewQueries,template}:{type?:CompileTypeMetadata, isComponent?:boolean, dynamicLoadable?:boolean, selector?:string, exportAs?:string, changeDetection?:ChangeDetectionStrategy, inputs?:string[], outputs?:string[], host?:{[key:string]:string}, lifecycleHooks?:LifecycleHooks[], providers?:Array<CompileProviderMetadata|CompileTypeMetadata|any[]>, viewProviders?:Array<CompileProviderMetadata|CompileTypeMetadata|any[]>, queries?:CompileQueryMetadata[], viewQueries?:CompileQueryMetadata[], template?:CompileTemplateMetadata}):CompileDirectiveMetadata',
|
||||
'CompileDirectiveMetadata.providers:Array<CompileProviderMetadata|CompileTypeMetadata|any[]>',
|
||||
'CompileDirectiveMetadata.queries:CompileQueryMetadata[]',
|
||||
'CompileDirectiveMetadata.viewProviders:Array<CompileProviderMetadata|CompileTypeMetadata|any[]>',
|
||||
'CompileDirectiveMetadata.viewQueries:CompileQueryMetadata[]',
|
||||
'CompileDirectiveMetadata.dynamicLoadable:boolean',
|
||||
'CompileDirectiveMetadata.exportAs:string',
|
||||
'CompileDirectiveMetadata.fromJson(data:{[key:string]:any}):CompileDirectiveMetadata',
|
||||
|
@ -851,6 +855,7 @@ const COMPILER = [
|
|||
'CompileDirectiveMetadata.template:CompileTemplateMetadata',
|
||||
'CompileDirectiveMetadata.toJson():{[key:string]:any}',
|
||||
'CompileDirectiveMetadata.type:CompileTypeMetadata',
|
||||
'CompileDirectiveMetadata.identifier:CompileIdentifierMetadata',
|
||||
'CompileTemplateMetadata',
|
||||
'CompileTemplateMetadata.constructor({encapsulation,template,templateUrl,styles,styleUrls,ngContentSelectors}:{encapsulation?:ViewEncapsulation, template?:string, templateUrl?:string, styles?:string[], styleUrls?:string[], ngContentSelectors?:string[]})',
|
||||
'CompileTemplateMetadata.encapsulation:ViewEncapsulation',
|
||||
|
@ -862,13 +867,18 @@ const COMPILER = [
|
|||
'CompileTemplateMetadata.templateUrl:string',
|
||||
'CompileTemplateMetadata.toJson():{[key:string]:any}',
|
||||
'CompileTypeMetadata',
|
||||
'CompileTypeMetadata.constructor({runtime,name,moduleUrl,isHost}:{runtime?:Type, name?:string, moduleUrl?:string, isHost?:boolean})',
|
||||
'CompileTypeMetadata.constructor({runtime,name,moduleUrl,prefix,isHost,constConstructor,diDeps}:{runtime?:Type, name?:string, moduleUrl?:string, prefix?:string, isHost?:boolean, constConstructor?:boolean, diDeps?:CompileDiDependencyMetadata[]})',
|
||||
'CompileTypeMetadata.fromJson(data:{[key:string]:any}):CompileTypeMetadata',
|
||||
'CompileTypeMetadata.isHost:boolean',
|
||||
'CompileTypeMetadata.moduleUrl:string',
|
||||
'CompileTypeMetadata.name:string',
|
||||
'CompileTypeMetadata.runtime:Type',
|
||||
'CompileTypeMetadata.toJson():{[key:string]:any}',
|
||||
'CompileTypeMetadata.diDeps:CompileDiDependencyMetadata[]',
|
||||
'CompileTypeMetadata.prefix:string',
|
||||
'CompileTypeMetadata.constConstructor:boolean',
|
||||
'CompileTypeMetadata.identifier:CompileIdentifierMetadata',
|
||||
'CompileTypeMetadata.type:CompileTypeMetadata',
|
||||
'DirectiveAst',
|
||||
'DirectiveAst.constructor(directive:CompileDirectiveMetadata, inputs:BoundDirectivePropertyAst[], hostProperties:BoundElementPropertyAst[], hostEvents:BoundEventAst[], exportAsVars:VariableAst[], sourceSpan:ParseSourceSpan)',
|
||||
'DirectiveAst.visit(visitor:TemplateAstVisitor, context:any):any',
|
||||
|
|
Loading…
Reference in New Issue