fix(compiler): Correctly handles references to static methods (#11013)
Fixes: #10975
This commit is contained in:
parent
5ddecb18a7
commit
14a30f3ca0
|
@ -30,11 +30,12 @@ export class CompWithProviders {
|
|||
@Component({
|
||||
selector: 'cmp-reference',
|
||||
template: `
|
||||
<input #a>{{a.value}}
|
||||
<input #a [(ngModel)]="foo" required>{{a.value}}
|
||||
<div *ngIf="true">{{a.value}}</div>
|
||||
`
|
||||
})
|
||||
export class CompWithReferences {
|
||||
foo: string;
|
||||
}
|
||||
|
||||
@Component({selector: 'cmp-pipes', template: `<div *ngIf>{{test | somePipe}}</div>`})
|
||||
|
|
|
@ -35,7 +35,7 @@ import {CompForChildQuery, CompWithChildQuery, CompWithDirectiveChild, Directive
|
|||
providers: [SomeService],
|
||||
entryComponents: [
|
||||
AnimateCmp, BasicComp, CompWithEntryComponents, CompWithAnalyzeEntryComponentsProvider,
|
||||
ProjectingComp, CompWithChildQuery, CompUsingRootModuleDirectiveAndPipe
|
||||
ProjectingComp, CompWithChildQuery, CompUsingRootModuleDirectiveAndPipe, CompWithReferences
|
||||
]
|
||||
})
|
||||
export class MainModule {
|
||||
|
|
|
@ -221,11 +221,12 @@ export class ReflectorHost implements StaticReflectorHost, ImportGenerator {
|
|||
* @param declarationFile the absolute path of the file where the symbol is declared
|
||||
* @param name the name of the type.
|
||||
*/
|
||||
getStaticSymbol(declarationFile: string, name: string): StaticSymbol {
|
||||
let key = `"${declarationFile}".${name}`;
|
||||
getStaticSymbol(declarationFile: string, name: string, members?: string[]): StaticSymbol {
|
||||
const memberSuffix = members ? `.${ members.join('.')}` : '';
|
||||
const key = `"${declarationFile}".${name}${memberSuffix}`;
|
||||
let result = this.typeCache.get(key);
|
||||
if (!result) {
|
||||
result = new StaticSymbol(declarationFile, name);
|
||||
result = new StaticSymbol(declarationFile, name, members);
|
||||
this.typeCache.set(key, result);
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -34,7 +34,7 @@ export interface StaticReflectorHost {
|
|||
*/
|
||||
findDeclaration(modulePath: string, symbolName: string, containingFile?: string): StaticSymbol;
|
||||
|
||||
getStaticSymbol(declarationFile: string, name: string): StaticSymbol;
|
||||
getStaticSymbol(declarationFile: string, name: string, members?: string[]): StaticSymbol;
|
||||
|
||||
angularImportLocations(): {
|
||||
coreDecorators: string,
|
||||
|
@ -52,7 +52,7 @@ export interface StaticReflectorHost {
|
|||
* This token is unique for a filePath and name and can be used as a hash table key.
|
||||
*/
|
||||
export class StaticSymbol {
|
||||
constructor(public filePath: string, public name: string) {}
|
||||
constructor(public filePath: string, public name: string, public members?: string[]) {}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -451,7 +451,12 @@ export class StaticReflector implements ReflectorReader {
|
|||
if (declarationValue && declarationValue.statics) {
|
||||
selectTarget = declarationValue.statics;
|
||||
} else {
|
||||
return null;
|
||||
const member: string = expression['member'];
|
||||
const members = selectTarget.members ?
|
||||
(selectTarget.members as string[]).concat(member) :
|
||||
[member];
|
||||
return _this.host.getStaticSymbol(
|
||||
selectTarget.filePath, selectTarget.name, members);
|
||||
}
|
||||
}
|
||||
const member = simplify(expression['member']);
|
||||
|
|
|
@ -426,6 +426,13 @@ describe('StaticReflector', () => {
|
|||
expect(annotations.length).toBe(1);
|
||||
expect(annotations[0].providers).toEqual([['a', true, false]]);
|
||||
});
|
||||
|
||||
it('should be able to get metadata with a reference to a static method', () => {
|
||||
const annotations = reflector.annotations(
|
||||
host.getStaticSymbol('/tmp/src/static-method-ref.ts', 'MethodReference'));
|
||||
expect(annotations.length).toBe(1);
|
||||
expect(annotations[0]._providers[0].useValue.members[0]).toEqual('staticMethod');
|
||||
});
|
||||
});
|
||||
|
||||
class MockReflectorHost implements StaticReflectorHost {
|
||||
|
@ -444,11 +451,11 @@ class MockReflectorHost implements StaticReflectorHost {
|
|||
provider: 'angular2/src/core/di/provider'
|
||||
};
|
||||
}
|
||||
getStaticSymbol(declarationFile: string, name: string): StaticSymbol {
|
||||
var cacheKey = `${declarationFile}:${name}`;
|
||||
getStaticSymbol(declarationFile: string, name: string, members?: string[]): StaticSymbol {
|
||||
var cacheKey = `${declarationFile}:${name}${members?'.'+members.join('.'):''}`;
|
||||
var result = this.staticTypeCache.get(cacheKey);
|
||||
if (isBlank(result)) {
|
||||
result = new StaticSymbol(declarationFile, name);
|
||||
result = new StaticSymbol(declarationFile, name, members);
|
||||
this.staticTypeCache.set(cacheKey, result);
|
||||
}
|
||||
return result;
|
||||
|
@ -1011,6 +1018,22 @@ class MockReflectorHost implements StaticReflectorHost {
|
|||
providers: [ { provider: 'a', useValue: MyModule.VALUE } ]
|
||||
})
|
||||
export class Foo { }
|
||||
`,
|
||||
'/tmp/src/static-method-def.ts': `
|
||||
export class ClassWithStatics {
|
||||
static staticMethod() {}
|
||||
}
|
||||
`,
|
||||
'/tmp/src/static-method-ref.ts': `
|
||||
import {Component} from 'angular2/src/core/metadata';
|
||||
import {ClassWithStatics} from './static-method-def';
|
||||
|
||||
@Component({
|
||||
providers: [ { provider: 'a', useValue: ClassWithStatics.staticMethod}]
|
||||
})
|
||||
export class MethodReference {
|
||||
|
||||
}
|
||||
`
|
||||
};
|
||||
|
||||
|
|
|
@ -319,5 +319,9 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
|
|||
(type: any /** TODO #9100 */) => type.visitType(this, ctx), typeParams, ctx, ',');
|
||||
ctx.print(`>`);
|
||||
}
|
||||
if (value.runtime && value.runtime.members) {
|
||||
ctx.print('.');
|
||||
ctx.print(value.runtime.members.join('.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue