refactor(compiler): support referenced `OpaqueToken`s correctly in offline compiler.
This commit is contained in:
parent
176e55927c
commit
15f6b27ae0
|
@ -7,7 +7,6 @@ import {
|
||||||
isStringMap,
|
isStringMap,
|
||||||
FunctionWrapper
|
FunctionWrapper
|
||||||
} from 'angular2/src/facade/lang';
|
} from 'angular2/src/facade/lang';
|
||||||
import {BaseException} from 'angular2/src/facade/exceptions';
|
|
||||||
import {
|
import {
|
||||||
AttributeMetadata,
|
AttributeMetadata,
|
||||||
DirectiveMetadata,
|
DirectiveMetadata,
|
||||||
|
@ -35,11 +34,6 @@ import {
|
||||||
SkipSelfMetadata,
|
SkipSelfMetadata,
|
||||||
InjectMetadata,
|
InjectMetadata,
|
||||||
} from "angular2/src/core/di/metadata";
|
} from "angular2/src/core/di/metadata";
|
||||||
import {OpaqueToken} from 'angular2/src/core/di/opaque_token';
|
|
||||||
|
|
||||||
export class ModuleContext {
|
|
||||||
constructor(public moduleId: string, public filePath: string) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The host of the static resolver is expected to be able to provide module metadata in the form of
|
* The host of the static resolver is expected to be able to provide module metadata in the form of
|
||||||
|
@ -71,7 +65,7 @@ export interface StaticReflectorHost {
|
||||||
*
|
*
|
||||||
* This token is unique for a moduleId and name and can be used as a hash table key.
|
* This token is unique for a moduleId and name and can be used as a hash table key.
|
||||||
*/
|
*/
|
||||||
export class StaticSymbol implements ModuleContext {
|
export class StaticSymbol {
|
||||||
constructor(public moduleId: string, public filePath: string, public name: string) {}
|
constructor(public moduleId: string, public filePath: string, public name: string) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,8 +78,7 @@ export class StaticReflector implements ReflectorReader {
|
||||||
private propertyCache = new Map<StaticSymbol, {[key: string]: any}>();
|
private propertyCache = new Map<StaticSymbol, {[key: string]: any}>();
|
||||||
private parameterCache = new Map<StaticSymbol, any[]>();
|
private parameterCache = new Map<StaticSymbol, any[]>();
|
||||||
private metadataCache = new Map<string, {[key: string]: any}>();
|
private metadataCache = new Map<string, {[key: string]: any}>();
|
||||||
private conversionMap =
|
private conversionMap = new Map<StaticSymbol, (context: StaticSymbol, args: any[]) => any>();
|
||||||
new Map<StaticSymbol, (moduleContext: ModuleContext, args: any[]) => any>();
|
|
||||||
|
|
||||||
constructor(private host: StaticReflectorHost) { this.initializeConversionMap(); }
|
constructor(private host: StaticReflectorHost) { this.initializeConversionMap(); }
|
||||||
|
|
||||||
|
@ -155,22 +148,20 @@ export class StaticReflector implements ReflectorReader {
|
||||||
}
|
}
|
||||||
return parameters;
|
return parameters;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed on type', type, 'with error', e);
|
console.log(`Failed on type ${type} with error ${e}`);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerDecoratorOrConstructor(type: StaticSymbol, ctor: any): void {
|
private registerDecoratorOrConstructor(type: StaticSymbol, ctor: any): void {
|
||||||
this.conversionMap.set(type, (moduleContext: ModuleContext, args: any[]) => {
|
this.conversionMap.set(type, (context: StaticSymbol, args: any[]) => {
|
||||||
let argValues = [];
|
let argValues = [];
|
||||||
ListWrapper.forEachWithIndex(args, (arg, index) => {
|
ListWrapper.forEachWithIndex(args, (arg, index) => {
|
||||||
let argValue;
|
let argValue;
|
||||||
if (isStringMap(arg) && isBlank(arg['__symbolic'])) {
|
if (isStringMap(arg) && isBlank(arg['__symbolic'])) {
|
||||||
argValue =
|
argValue = mapStringMap(arg, (value, key) => this.simplify(context, value));
|
||||||
mapStringMap(arg, (value, key) => this.simplify(
|
|
||||||
moduleContext, value) );
|
|
||||||
} else {
|
} else {
|
||||||
argValue = this.simplify(moduleContext, arg);
|
argValue = this.simplify(context, arg);
|
||||||
}
|
}
|
||||||
argValues.push(argValue);
|
argValues.push(argValue);
|
||||||
});
|
});
|
||||||
|
@ -183,7 +174,6 @@ export class StaticReflector implements ReflectorReader {
|
||||||
let diDecorators = 'angular2/src/core/di/decorators';
|
let diDecorators = 'angular2/src/core/di/decorators';
|
||||||
let diMetadata = 'angular2/src/core/di/metadata';
|
let diMetadata = 'angular2/src/core/di/metadata';
|
||||||
let provider = 'angular2/src/core/di/provider';
|
let provider = 'angular2/src/core/di/provider';
|
||||||
let opaqueToken = 'angular2/src/core/di/opaque_token';
|
|
||||||
this.registerDecoratorOrConstructor(this.host.findDeclaration(provider, 'Provider'), Provider);
|
this.registerDecoratorOrConstructor(this.host.findDeclaration(provider, 'Provider'), Provider);
|
||||||
|
|
||||||
this.registerDecoratorOrConstructor(this.host.findDeclaration(diDecorators, 'Host'),
|
this.registerDecoratorOrConstructor(this.host.findDeclaration(diDecorators, 'Host'),
|
||||||
|
@ -236,12 +226,10 @@ export class StaticReflector implements ReflectorReader {
|
||||||
SkipSelfMetadata);
|
SkipSelfMetadata);
|
||||||
this.registerDecoratorOrConstructor(this.host.findDeclaration(diMetadata, 'OptionalMetadata'),
|
this.registerDecoratorOrConstructor(this.host.findDeclaration(diMetadata, 'OptionalMetadata'),
|
||||||
OptionalMetadata);
|
OptionalMetadata);
|
||||||
this.registerDecoratorOrConstructor(this.host.findDeclaration(opaqueToken, 'OpaqueToken'),
|
|
||||||
OpaqueToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
public simplify(moduleContext: ModuleContext, value: any): any {
|
public simplify(context: StaticSymbol, value: any): any {
|
||||||
let _this = this;
|
let _this = this;
|
||||||
|
|
||||||
function simplify(expression: any): any {
|
function simplify(expression: any): any {
|
||||||
|
@ -331,41 +319,39 @@ export class StaticReflector implements ReflectorReader {
|
||||||
case "reference":
|
case "reference":
|
||||||
if (isPresent(expression['module'])) {
|
if (isPresent(expression['module'])) {
|
||||||
staticSymbol = _this.host.findDeclaration(expression['module'], expression['name'],
|
staticSymbol = _this.host.findDeclaration(expression['module'], expression['name'],
|
||||||
moduleContext.filePath);
|
context.filePath);
|
||||||
} else {
|
} else {
|
||||||
staticSymbol = _this.host.getStaticSymbol(
|
staticSymbol = _this.host.getStaticSymbol(context.moduleId, context.filePath,
|
||||||
moduleContext.moduleId, moduleContext.filePath, expression['name']);
|
expression['name']);
|
||||||
}
|
}
|
||||||
let result = staticSymbol;
|
let result = staticSymbol;
|
||||||
let moduleMetadata = _this.getModuleMetadata(staticSymbol.filePath);
|
let moduleMetadata = _this.getModuleMetadata(staticSymbol.filePath);
|
||||||
let declarationValue = isPresent(moduleMetadata) ? moduleMetadata['metadata'][staticSymbol.name] : null;
|
let declarationValue =
|
||||||
|
isPresent(moduleMetadata) ? moduleMetadata['metadata'][staticSymbol.name] : null;
|
||||||
if (isPresent(declarationValue)) {
|
if (isPresent(declarationValue)) {
|
||||||
if (isClassMetadata(declarationValue)) {
|
if (isClassMetadata(declarationValue)) {
|
||||||
result = staticSymbol;
|
result = staticSymbol;
|
||||||
} else {
|
} else {
|
||||||
let newModuleContext =
|
result = _this.simplify(staticSymbol, declarationValue);
|
||||||
new ModuleContext(staticSymbol.moduleId, staticSymbol.filePath);
|
|
||||||
result = _this.simplify(newModuleContext, declarationValue);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
case "class":
|
||||||
|
return context;
|
||||||
case "new":
|
case "new":
|
||||||
case "call":
|
case "call":
|
||||||
let target = expression['expression'];
|
let target = expression['expression'];
|
||||||
staticSymbol = _this.host.findDeclaration(target['module'], target['name'],
|
staticSymbol =
|
||||||
moduleContext.filePath);
|
_this.host.findDeclaration(target['module'], target['name'], context.filePath);
|
||||||
let converter = _this.conversionMap.get(staticSymbol);
|
let converter = _this.conversionMap.get(staticSymbol);
|
||||||
if (isBlank(converter)) {
|
|
||||||
throw new BaseException(`Cannot convert call/new expression for ${target['name']} in ${moduleContext.filePath}`)
|
|
||||||
}
|
|
||||||
if (isPresent(converter)) {
|
if (isPresent(converter)) {
|
||||||
let args = expression['arguments'];
|
let args = expression['arguments'];
|
||||||
if (isBlank(args)) {
|
if (isBlank(args)) {
|
||||||
args = [];
|
args = [];
|
||||||
}
|
}
|
||||||
return converter(moduleContext, args);
|
return converter(context, args);
|
||||||
} else {
|
} else {
|
||||||
return staticSymbol;
|
return context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -5,15 +5,14 @@ import {ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {
|
import {
|
||||||
StaticReflector,
|
StaticReflector,
|
||||||
StaticReflectorHost,
|
StaticReflectorHost,
|
||||||
StaticSymbol,
|
StaticSymbol
|
||||||
ModuleContext
|
|
||||||
} from 'angular2/src/compiler/static_reflector';
|
} from 'angular2/src/compiler/static_reflector';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
// Static reflector is not supported in Dart
|
// Static reflector is not supported in Dart
|
||||||
// as we use reflection to create objects.
|
// as we use reflection to create objects.
|
||||||
if (IS_DART) return;
|
if (IS_DART) return;
|
||||||
let noContext = new ModuleContext('', '');
|
let noContext = new StaticSymbol('', '', '');
|
||||||
|
|
||||||
describe('StaticReflector', () => {
|
describe('StaticReflector', () => {
|
||||||
let host: StaticReflectorHost;
|
let host: StaticReflectorHost;
|
||||||
|
@ -24,8 +23,8 @@ export function main() {
|
||||||
reflector = new StaticReflector(host);
|
reflector = new StaticReflector(host);
|
||||||
});
|
});
|
||||||
|
|
||||||
function simplify(moduleContext: ModuleContext, value: any) {
|
function simplify(context: StaticSymbol, value: any) {
|
||||||
return reflector.simplify(moduleContext, value);
|
return reflector.simplify(context, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should get annotations for NgFor', () => {
|
it('should get annotations for NgFor', () => {
|
||||||
|
@ -219,9 +218,7 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should simplify an array index', () => {
|
it('should simplify an array index', () => {
|
||||||
expect(
|
expect(simplify(noContext, ({__symbolic: "index", expression: [1, 2, 3], index: 2}))).toBe(3);
|
||||||
simplify(noContext, ({__symbolic: "index", expression: [1, 2, 3], index: 2})))
|
|
||||||
.toBe(3);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should simplify an object index', () => {
|
it('should simplify an object index', () => {
|
||||||
|
@ -230,14 +227,14 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should simplify a module reference', () => {
|
it('should simplify a module reference', () => {
|
||||||
expect(simplify(new ModuleContext('', '/src/cases'),
|
expect(simplify(new StaticSymbol('', '/src/cases', ''),
|
||||||
({__symbolic: "reference", module: "./extern", name: "s"})))
|
({__symbolic: "reference", module: "./extern", name: "s"})))
|
||||||
.toEqual("s");
|
.toEqual("s");
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should simplify a non existing reference as a static symbol', () => {
|
it('should simplify a non existing reference as a static symbol', () => {
|
||||||
expect(simplify(new ModuleContext('', '/src/cases'),
|
expect(simplify(new StaticSymbol('', '/src/cases', ''),
|
||||||
({__symbolic: "reference", module: "./extern", name: "nonExisting"})))
|
({__symbolic: "reference", module: "./extern", name: "nonExisting"})))
|
||||||
.toEqual(host.getStaticSymbol('', '/src/extern.d.ts', 'nonExisting'));
|
.toEqual(host.getStaticSymbol('', '/src/extern.d.ts', 'nonExisting'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue