2016-04-25 21:29:06 -07:00
|
|
|
import {StringMapWrapper} from 'angular2/src/facade/collection';
|
2016-04-12 09:40:37 -07:00
|
|
|
import {
|
|
|
|
isArray,
|
|
|
|
isPresent,
|
|
|
|
isPrimitive,
|
|
|
|
} from 'angular2/src/facade/lang';
|
|
|
|
import {
|
|
|
|
AttributeMetadata,
|
|
|
|
DirectiveMetadata,
|
|
|
|
ComponentMetadata,
|
|
|
|
ContentChildrenMetadata,
|
|
|
|
ContentChildMetadata,
|
|
|
|
InputMetadata,
|
|
|
|
HostBindingMetadata,
|
|
|
|
HostListenerMetadata,
|
|
|
|
OutputMetadata,
|
|
|
|
PipeMetadata,
|
|
|
|
ViewMetadata,
|
|
|
|
ViewChildMetadata,
|
|
|
|
ViewChildrenMetadata,
|
|
|
|
ViewQueryMetadata,
|
|
|
|
QueryMetadata,
|
|
|
|
} from 'angular2/src/core/metadata';
|
2016-02-18 10:53:21 -08:00
|
|
|
import {ReflectorReader} from 'angular2/src/core/reflection/reflector_reader';
|
2016-03-24 10:03:10 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The host of the static resolver is expected to be able to provide module metadata in the form of
|
|
|
|
* ModuleMetadata. Angular 2 CLI will produce this metadata for a module whenever a .d.ts files is
|
|
|
|
* produced and the module has exported variables or classes with decorators. Module metadata can
|
|
|
|
* also be produced directly from TypeScript sources by using MetadataCollector in tools/metadata.
|
|
|
|
*/
|
|
|
|
export interface StaticReflectorHost {
|
|
|
|
/**
|
2016-04-25 21:29:06 -07:00
|
|
|
* Return a ModuleMetadata for the given module.
|
2016-03-24 10:03:10 -07:00
|
|
|
*
|
2016-04-25 21:29:06 -07:00
|
|
|
* @param moduleId is a string identifier for a module as an absolute path.
|
2016-03-24 10:03:10 -07:00
|
|
|
* @returns the metadata for the given module.
|
|
|
|
*/
|
|
|
|
getMetadataFor(moduleId: string): {[key: string]: any};
|
2016-04-25 21:29:06 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Resolve a module from an import statement form to an absolute path.
|
|
|
|
* @param moduleName the location imported from
|
|
|
|
* @param containingFile for relative imports, the path of the file containing the import
|
|
|
|
*/
|
|
|
|
resolveModule(moduleName: string, containingFile?: string): string;
|
2016-03-24 10:03:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A token representing the a reference to a static type.
|
|
|
|
*
|
|
|
|
* This token is unique for a moduleId and name and can be used as a hash table key.
|
|
|
|
*/
|
|
|
|
export class StaticType {
|
|
|
|
constructor(public moduleId: string, public name: string) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A static reflector implements enough of the Reflector API that is necessary to compile
|
|
|
|
* templates statically.
|
|
|
|
*/
|
2016-02-18 10:53:21 -08:00
|
|
|
export class StaticReflector implements ReflectorReader {
|
2016-03-24 10:03:10 -07:00
|
|
|
private typeCache = new Map<string, StaticType>();
|
|
|
|
private annotationCache = new Map<StaticType, any[]>();
|
|
|
|
private propertyCache = new Map<StaticType, {[key: string]: any}>();
|
|
|
|
private parameterCache = new Map<StaticType, any[]>();
|
|
|
|
private metadataCache = new Map<string, {[key: string]: any}>();
|
|
|
|
constructor(private host: StaticReflectorHost) { this.initializeConversionMap(); }
|
|
|
|
|
2016-02-18 10:53:21 -08:00
|
|
|
importUri(typeOrFunc: any): string { return (<StaticType>typeOrFunc).moduleId; }
|
|
|
|
|
2016-03-24 10:03:10 -07:00
|
|
|
/**
|
2016-04-25 21:29:06 -07:00
|
|
|
* getStaticType produces a Type whose metadata is known but whose implementation is not loaded.
|
2016-03-24 10:03:10 -07:00
|
|
|
* All types passed to the StaticResolver should be pseudo-types returned by this method.
|
|
|
|
*
|
2016-04-25 21:29:06 -07:00
|
|
|
* @param moduleId the module identifier as an absolute path.
|
2016-03-24 10:03:10 -07:00
|
|
|
* @param name the name of the type.
|
|
|
|
*/
|
|
|
|
public getStaticType(moduleId: string, name: string): StaticType {
|
|
|
|
let key = `"${moduleId}".${name}`;
|
|
|
|
let result = this.typeCache.get(key);
|
|
|
|
if (!isPresent(result)) {
|
|
|
|
result = new StaticType(moduleId, name);
|
|
|
|
this.typeCache.set(key, result);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public annotations(type: StaticType): any[] {
|
|
|
|
let annotations = this.annotationCache.get(type);
|
|
|
|
if (!isPresent(annotations)) {
|
|
|
|
let classMetadata = this.getTypeMetadata(type);
|
|
|
|
if (isPresent(classMetadata['decorators'])) {
|
|
|
|
annotations = (<any[]>classMetadata['decorators'])
|
|
|
|
.map(decorator => this.convertKnownDecorator(type.moduleId, decorator))
|
|
|
|
.filter(decorator => isPresent(decorator));
|
2016-04-08 15:39:21 -07:00
|
|
|
} else {
|
|
|
|
annotations = [];
|
2016-03-24 10:03:10 -07:00
|
|
|
}
|
|
|
|
this.annotationCache.set(type, annotations);
|
|
|
|
}
|
|
|
|
return annotations;
|
|
|
|
}
|
|
|
|
|
|
|
|
public propMetadata(type: StaticType): {[key: string]: any} {
|
|
|
|
let propMetadata = this.propertyCache.get(type);
|
|
|
|
if (!isPresent(propMetadata)) {
|
|
|
|
let classMetadata = this.getTypeMetadata(type);
|
|
|
|
propMetadata = this.getPropertyMetadata(type.moduleId, classMetadata['members']);
|
2016-04-08 15:39:21 -07:00
|
|
|
if (!isPresent(propMetadata)) {
|
|
|
|
propMetadata = {};
|
|
|
|
}
|
2016-03-24 10:03:10 -07:00
|
|
|
this.propertyCache.set(type, propMetadata);
|
|
|
|
}
|
|
|
|
return propMetadata;
|
|
|
|
}
|
|
|
|
|
|
|
|
public parameters(type: StaticType): any[] {
|
|
|
|
let parameters = this.parameterCache.get(type);
|
|
|
|
if (!isPresent(parameters)) {
|
|
|
|
let classMetadata = this.getTypeMetadata(type);
|
2016-04-08 15:39:21 -07:00
|
|
|
if (isPresent(classMetadata)) {
|
|
|
|
let members = classMetadata['members'];
|
|
|
|
if (isPresent(members)) {
|
|
|
|
let ctorData = members['__ctor__'];
|
|
|
|
if (isPresent(ctorData)) {
|
|
|
|
let ctor = (<any[]>ctorData).find(a => a['__symbolic'] === 'constructor');
|
|
|
|
parameters = this.simplify(type.moduleId, ctor['parameters']);
|
|
|
|
}
|
|
|
|
}
|
2016-03-24 10:03:10 -07:00
|
|
|
}
|
2016-04-08 15:39:21 -07:00
|
|
|
if (!isPresent(parameters)) {
|
|
|
|
parameters = [];
|
|
|
|
}
|
|
|
|
this.parameterCache.set(type, parameters);
|
2016-03-24 10:03:10 -07:00
|
|
|
}
|
|
|
|
return parameters;
|
|
|
|
}
|
|
|
|
|
|
|
|
private conversionMap = new Map<StaticType, (moduleContext: string, expression: any) => any>();
|
2016-03-28 14:25:22 -07:00
|
|
|
private initializeConversionMap(): any {
|
2016-04-25 21:29:06 -07:00
|
|
|
let core_metadata = this.host.resolveModule('angular2/src/core/metadata');
|
2016-03-24 10:03:10 -07:00
|
|
|
let conversionMap = this.conversionMap;
|
2016-04-12 09:40:37 -07:00
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'Directive'),
|
|
|
|
(moduleContext, expression) => {
|
|
|
|
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
|
|
|
|
if (!isPresent(p0)) {
|
|
|
|
p0 = {};
|
|
|
|
}
|
|
|
|
return new DirectiveMetadata({
|
|
|
|
selector: p0['selector'],
|
|
|
|
inputs: p0['inputs'],
|
|
|
|
outputs: p0['outputs'],
|
|
|
|
events: p0['events'],
|
|
|
|
host: p0['host'],
|
|
|
|
bindings: p0['bindings'],
|
|
|
|
providers: p0['providers'],
|
|
|
|
exportAs: p0['exportAs'],
|
|
|
|
queries: p0['queries'],
|
|
|
|
});
|
|
|
|
});
|
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'Component'),
|
|
|
|
(moduleContext, expression) => {
|
|
|
|
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
|
|
|
|
if (!isPresent(p0)) {
|
|
|
|
p0 = {};
|
|
|
|
}
|
|
|
|
return new ComponentMetadata({
|
|
|
|
selector: p0['selector'],
|
|
|
|
inputs: p0['inputs'],
|
|
|
|
outputs: p0['outputs'],
|
|
|
|
properties: p0['properties'],
|
|
|
|
events: p0['events'],
|
|
|
|
host: p0['host'],
|
|
|
|
exportAs: p0['exportAs'],
|
|
|
|
moduleId: p0['moduleId'],
|
|
|
|
bindings: p0['bindings'],
|
|
|
|
providers: p0['providers'],
|
|
|
|
viewBindings: p0['viewBindings'],
|
|
|
|
viewProviders: p0['viewProviders'],
|
|
|
|
changeDetection: p0['changeDetection'],
|
|
|
|
queries: p0['queries'],
|
|
|
|
templateUrl: p0['templateUrl'],
|
|
|
|
template: p0['template'],
|
|
|
|
styleUrls: p0['styleUrls'],
|
|
|
|
styles: p0['styles'],
|
|
|
|
directives: p0['directives'],
|
|
|
|
pipes: p0['pipes'],
|
|
|
|
encapsulation: p0['encapsulation']
|
|
|
|
});
|
|
|
|
});
|
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'Input'),
|
|
|
|
(moduleContext, expression) => new InputMetadata(
|
|
|
|
this.getDecoratorParameter(moduleContext, expression, 0)));
|
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'Output'),
|
|
|
|
(moduleContext, expression) => new OutputMetadata(
|
|
|
|
this.getDecoratorParameter(moduleContext, expression, 0)));
|
2016-03-24 10:03:10 -07:00
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'View'), (moduleContext, expression) => {
|
|
|
|
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
|
|
|
|
if (!isPresent(p0)) {
|
|
|
|
p0 = {};
|
|
|
|
}
|
|
|
|
return new ViewMetadata({
|
|
|
|
templateUrl: p0['templateUrl'],
|
|
|
|
template: p0['template'],
|
|
|
|
directives: p0['directives'],
|
|
|
|
pipes: p0['pipes'],
|
|
|
|
encapsulation: p0['encapsulation'],
|
|
|
|
styles: p0['styles'],
|
|
|
|
});
|
|
|
|
});
|
2016-04-12 09:40:37 -07:00
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'Attribute'),
|
|
|
|
(moduleContext, expression) => new AttributeMetadata(
|
|
|
|
this.getDecoratorParameter(moduleContext, expression, 0)));
|
2016-03-24 10:03:10 -07:00
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'Query'), (moduleContext, expression) => {
|
|
|
|
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
|
|
|
|
let p1 = this.getDecoratorParameter(moduleContext, expression, 1);
|
|
|
|
if (!isPresent(p1)) {
|
|
|
|
p1 = {};
|
|
|
|
}
|
|
|
|
return new QueryMetadata(p0, {descendants: p1.descendants, first: p1.first});
|
|
|
|
});
|
2016-04-12 09:40:37 -07:00
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'ContentChildren'),
|
|
|
|
(moduleContext, expression) => new ContentChildrenMetadata(
|
|
|
|
this.getDecoratorParameter(moduleContext, expression, 0)));
|
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'ContentChild'),
|
|
|
|
(moduleContext, expression) => new ContentChildMetadata(
|
|
|
|
this.getDecoratorParameter(moduleContext, expression, 0)));
|
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'ViewChildren'),
|
|
|
|
(moduleContext, expression) => new ViewChildrenMetadata(
|
|
|
|
this.getDecoratorParameter(moduleContext, expression, 0)));
|
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'ViewChild'),
|
|
|
|
(moduleContext, expression) => new ViewChildMetadata(
|
|
|
|
this.getDecoratorParameter(moduleContext, expression, 0)));
|
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'ViewQuery'),
|
|
|
|
(moduleContext, expression) => {
|
|
|
|
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
|
|
|
|
let p1 = this.getDecoratorParameter(moduleContext, expression, 1);
|
|
|
|
if (!isPresent(p1)) {
|
|
|
|
p1 = {};
|
|
|
|
}
|
|
|
|
return new ViewQueryMetadata(p0, {
|
|
|
|
descendants: p1['descendants'],
|
|
|
|
first: p1['first'],
|
|
|
|
});
|
|
|
|
});
|
2016-03-24 10:03:10 -07:00
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'Pipe'), (moduleContext, expression) => {
|
|
|
|
let p0 = this.getDecoratorParameter(moduleContext, expression, 0);
|
|
|
|
if (!isPresent(p0)) {
|
|
|
|
p0 = {};
|
|
|
|
}
|
|
|
|
return new PipeMetadata({
|
|
|
|
name: p0['name'],
|
|
|
|
pure: p0['pure'],
|
|
|
|
});
|
|
|
|
});
|
2016-04-12 09:40:37 -07:00
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'HostBinding'),
|
|
|
|
(moduleContext, expression) => new HostBindingMetadata(
|
|
|
|
this.getDecoratorParameter(moduleContext, expression, 0)));
|
|
|
|
conversionMap.set(this.getStaticType(core_metadata, 'HostListener'),
|
|
|
|
(moduleContext, expression) => new HostListenerMetadata(
|
|
|
|
this.getDecoratorParameter(moduleContext, expression, 0),
|
|
|
|
this.getDecoratorParameter(moduleContext, expression, 1)));
|
2016-03-28 14:25:22 -07:00
|
|
|
return null;
|
2016-03-24 10:03:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
private convertKnownDecorator(moduleContext: string, expression: {[key: string]: any}): any {
|
|
|
|
let converter = this.conversionMap.get(this.getDecoratorType(moduleContext, expression));
|
|
|
|
if (isPresent(converter)) return converter(moduleContext, expression);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private getDecoratorType(moduleContext: string, expression: {[key: string]: any}): StaticType {
|
|
|
|
if (isMetadataSymbolicCallExpression(expression)) {
|
|
|
|
let target = expression['expression'];
|
|
|
|
if (isMetadataSymbolicReferenceExpression(target)) {
|
2016-04-25 21:29:06 -07:00
|
|
|
let moduleId = this.host.resolveModule(target['module'], moduleContext);
|
2016-03-24 10:03:10 -07:00
|
|
|
return this.getStaticType(moduleId, target['name']);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2016-04-12 09:40:37 -07:00
|
|
|
private getDecoratorParameter(moduleContext: string, expression: {[key: string]: any},
|
|
|
|
index: number): any {
|
2016-03-24 10:03:10 -07:00
|
|
|
if (isMetadataSymbolicCallExpression(expression) && isPresent(expression['arguments']) &&
|
|
|
|
(<any[]>expression['arguments']).length <= index + 1) {
|
|
|
|
return this.simplify(moduleContext, (<any[]>expression['arguments'])[index]);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2016-04-12 09:40:37 -07:00
|
|
|
private getPropertyMetadata(moduleContext: string,
|
|
|
|
value: {[key: string]: any}): {[key: string]: any} {
|
2016-03-24 10:03:10 -07:00
|
|
|
if (isPresent(value)) {
|
|
|
|
let result = {};
|
|
|
|
StringMapWrapper.forEach(value, (value, name) => {
|
|
|
|
let data = this.getMemberData(moduleContext, value);
|
|
|
|
if (isPresent(data)) {
|
2016-04-12 09:40:37 -07:00
|
|
|
let propertyData = data.filter(d => d['kind'] == "property")
|
2016-03-24 10:03:10 -07:00
|
|
|
.map(d => d['directives'])
|
|
|
|
.reduce((p, c) => (<any[]>p).concat(<any[]>c), []);
|
|
|
|
if (propertyData.length != 0) {
|
|
|
|
StringMapWrapper.set(result, name, propertyData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
}
|
2016-04-08 15:39:21 -07:00
|
|
|
return {};
|
2016-03-24 10:03:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
private getMemberData(moduleContext: string, member: { [key: string]: any }[]): { [key: string]: any }[] {
|
|
|
|
// clang-format on
|
|
|
|
let result = [];
|
|
|
|
if (isPresent(member)) {
|
|
|
|
for (let item of member) {
|
|
|
|
result.push({
|
|
|
|
kind: item['__symbolic'],
|
2016-04-12 09:40:37 -07:00
|
|
|
directives:
|
|
|
|
isPresent(item['decorators']) ?
|
|
|
|
(<any[]>item['decorators'])
|
|
|
|
.map(decorator => this.convertKnownDecorator(moduleContext, decorator))
|
|
|
|
.filter(d => isPresent(d)) :
|
|
|
|
null
|
2016-03-24 10:03:10 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @internal */
|
|
|
|
public simplify(moduleContext: string, value: any): any {
|
|
|
|
let _this = this;
|
|
|
|
|
|
|
|
function simplify(expression: any): any {
|
|
|
|
if (isPrimitive(expression)) {
|
|
|
|
return expression;
|
|
|
|
}
|
|
|
|
if (isArray(expression)) {
|
|
|
|
let result = [];
|
2016-04-12 09:40:37 -07:00
|
|
|
for (let item of(<any>expression)) {
|
2016-03-24 10:03:10 -07:00
|
|
|
result.push(simplify(item));
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
if (isPresent(expression)) {
|
|
|
|
if (isPresent(expression['__symbolic'])) {
|
|
|
|
switch (expression['__symbolic']) {
|
2016-04-12 09:40:37 -07:00
|
|
|
case "binop":
|
2016-03-24 10:03:10 -07:00
|
|
|
let left = simplify(expression['left']);
|
|
|
|
let right = simplify(expression['right']);
|
|
|
|
switch (expression['operator']) {
|
|
|
|
case '&&':
|
|
|
|
return left && right;
|
|
|
|
case '||':
|
|
|
|
return left || right;
|
|
|
|
case '|':
|
|
|
|
return left | right;
|
|
|
|
case '^':
|
|
|
|
return left ^ right;
|
|
|
|
case '&':
|
|
|
|
return left & right;
|
|
|
|
case '==':
|
|
|
|
return left == right;
|
|
|
|
case '!=':
|
|
|
|
return left != right;
|
|
|
|
case '===':
|
|
|
|
return left === right;
|
|
|
|
case '!==':
|
|
|
|
return left !== right;
|
|
|
|
case '<':
|
|
|
|
return left < right;
|
|
|
|
case '>':
|
|
|
|
return left > right;
|
|
|
|
case '<=':
|
|
|
|
return left <= right;
|
|
|
|
case '>=':
|
|
|
|
return left >= right;
|
|
|
|
case '<<':
|
|
|
|
return left << right;
|
|
|
|
case '>>':
|
|
|
|
return left >> right;
|
|
|
|
case '+':
|
|
|
|
return left + right;
|
|
|
|
case '-':
|
|
|
|
return left - right;
|
|
|
|
case '*':
|
|
|
|
return left * right;
|
|
|
|
case '/':
|
|
|
|
return left / right;
|
|
|
|
case '%':
|
|
|
|
return left % right;
|
|
|
|
}
|
|
|
|
return null;
|
2016-04-12 09:40:37 -07:00
|
|
|
case "pre":
|
2016-03-24 10:03:10 -07:00
|
|
|
let operand = simplify(expression['operand']);
|
|
|
|
switch (expression['operator']) {
|
|
|
|
case '+':
|
|
|
|
return operand;
|
|
|
|
case '-':
|
|
|
|
return -operand;
|
|
|
|
case '!':
|
|
|
|
return !operand;
|
|
|
|
case '~':
|
|
|
|
return ~operand;
|
|
|
|
}
|
|
|
|
return null;
|
2016-04-12 09:40:37 -07:00
|
|
|
case "index":
|
2016-03-24 10:03:10 -07:00
|
|
|
let indexTarget = simplify(expression['expression']);
|
|
|
|
let index = simplify(expression['index']);
|
|
|
|
if (isPresent(indexTarget) && isPrimitive(index)) return indexTarget[index];
|
|
|
|
return null;
|
2016-04-12 09:40:37 -07:00
|
|
|
case "select":
|
2016-03-24 10:03:10 -07:00
|
|
|
let selectTarget = simplify(expression['expression']);
|
|
|
|
let member = simplify(expression['member']);
|
|
|
|
if (isPresent(selectTarget) && isPrimitive(member)) return selectTarget[member];
|
|
|
|
return null;
|
2016-04-12 09:40:37 -07:00
|
|
|
case "reference":
|
2016-03-24 10:03:10 -07:00
|
|
|
let referenceModuleName =
|
2016-04-25 21:29:06 -07:00
|
|
|
_this.host.resolveModule(expression['module'], moduleContext);
|
2016-03-24 10:03:10 -07:00
|
|
|
let referenceModule = _this.getModuleMetadata(referenceModuleName);
|
|
|
|
let referenceValue = referenceModule['metadata'][expression['name']];
|
|
|
|
if (isClassMetadata(referenceValue)) {
|
|
|
|
// Convert to a pseudo type
|
|
|
|
return _this.getStaticType(referenceModuleName, expression['name']);
|
|
|
|
}
|
|
|
|
return _this.simplify(referenceModuleName, referenceValue);
|
2016-04-12 09:40:37 -07:00
|
|
|
case "call":
|
2016-03-24 10:03:10 -07:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
let result = {};
|
|
|
|
StringMapWrapper.forEach(expression, (value, name) => { result[name] = simplify(value); });
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return simplify(value);
|
|
|
|
}
|
|
|
|
|
2016-04-25 21:29:06 -07:00
|
|
|
/**
|
|
|
|
* @param module an absolute path to a module file.
|
|
|
|
*/
|
2016-02-18 10:53:21 -08:00
|
|
|
public getModuleMetadata(module: string): {[key: string]: any} {
|
2016-03-24 10:03:10 -07:00
|
|
|
let moduleMetadata = this.metadataCache.get(module);
|
|
|
|
if (!isPresent(moduleMetadata)) {
|
|
|
|
moduleMetadata = this.host.getMetadataFor(module);
|
|
|
|
if (!isPresent(moduleMetadata)) {
|
2016-04-12 09:40:37 -07:00
|
|
|
moduleMetadata = {__symbolic: "module", module: module, metadata: {}};
|
2016-03-24 10:03:10 -07:00
|
|
|
}
|
|
|
|
this.metadataCache.set(module, moduleMetadata);
|
|
|
|
}
|
|
|
|
return moduleMetadata;
|
|
|
|
}
|
|
|
|
|
|
|
|
private getTypeMetadata(type: StaticType): {[key: string]: any} {
|
|
|
|
let moduleMetadata = this.getModuleMetadata(type.moduleId);
|
|
|
|
let result = moduleMetadata['metadata'][type.name];
|
|
|
|
if (!isPresent(result)) {
|
2016-04-12 09:40:37 -07:00
|
|
|
result = {__symbolic: "class"};
|
2016-03-24 10:03:10 -07:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function isMetadataSymbolicCallExpression(expression: any): boolean {
|
|
|
|
return !isPrimitive(expression) && !isArray(expression) && expression['__symbolic'] == 'call';
|
|
|
|
}
|
|
|
|
|
|
|
|
function isMetadataSymbolicReferenceExpression(expression: any): boolean {
|
|
|
|
return !isPrimitive(expression) && !isArray(expression) &&
|
2016-04-12 09:40:37 -07:00
|
|
|
expression['__symbolic'] == 'reference';
|
2016-03-24 10:03:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
function isClassMetadata(expression: any): boolean {
|
|
|
|
return !isPrimitive(expression) && !isArray(expression) && expression['__symbolic'] == 'class';
|
|
|
|
}
|