diff --git a/modules/@angular/compiler-cli/integrationtest/src/features.ts b/modules/@angular/compiler-cli/integrationtest/src/features.ts
index a9ef563254..62eec6107c 100644
--- a/modules/@angular/compiler-cli/integrationtest/src/features.ts
+++ b/modules/@angular/compiler-cli/integrationtest/src/features.ts
@@ -1,5 +1,5 @@
import {Component, Inject, OpaqueToken} from '@angular/core';
-import {NgIf} from '@angular/common';
+import * as common from '@angular/common';
export const SOME_OPAQUE_TOKEN = new OpaqueToken('opaqueToken');
@@ -9,7 +9,7 @@ export const SOME_OPAQUE_TOKEN = new OpaqueToken('opaqueToken');
providers: [
{provide: 'strToken', useValue: 'strValue'},
{provide: SOME_OPAQUE_TOKEN, useValue: 10},
- {provide: 'reference', useValue: NgIf},
+ {provide: 'reference', useValue: common.NgIf},
{provide: 'complexToken', useValue: {a: 1, b: ['test', SOME_OPAQUE_TOKEN]}},
]
})
@@ -23,7 +23,7 @@ export class CompWithProviders {
{{a.value}}
{{a.value}}
`,
- directives: [NgIf]
+ directives: [common.NgIf]
})
export class CompWithReferences {
}
diff --git a/tools/@angular/tsc-wrapped/src/evaluator.ts b/tools/@angular/tsc-wrapped/src/evaluator.ts
index 3c9a6b5039..e6cdf29276 100644
--- a/tools/@angular/tsc-wrapped/src/evaluator.ts
+++ b/tools/@angular/tsc-wrapped/src/evaluator.ts
@@ -1,6 +1,6 @@
import * as ts from 'typescript';
-import {MetadataValue, MetadataSymbolicCallExpression, MetadataSymbolicReferenceExpression, MetadataError, isMetadataError, isMetadataModuleReferenceExpression, isMetadataImportedSymbolReferenceExpression, isMetadataGlobalReferenceExpression,} from './schema';
+import {MetadataError, MetadataGlobalReferenceExpression, MetadataImportedSymbolReferenceExpression, MetadataSymbolicCallExpression, MetadataSymbolicReferenceExpression, MetadataValue, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataImportedSymbolReferenceExpression, isMetadataModuleReferenceExpression, isMetadataSymbolicReferenceExpression} from './schema';
import {Symbols} from './symbols';
function isMethodCallOf(callExpression: ts.CallExpression, memberName: string): boolean {
@@ -66,14 +66,21 @@ function getSourceFileOfNode(node: ts.Node): ts.SourceFile {
export function errorSymbol(
message: string, node?: ts.Node, context?: {[name: string]: string},
sourceFile?: ts.SourceFile): MetadataError {
+ let result: MetadataError;
if (node) {
sourceFile = sourceFile || getSourceFileOfNode(node);
if (sourceFile) {
let {line, character} = ts.getLineAndCharacterOfPosition(sourceFile, node.pos);
- return {__symbolic: 'error', message, line, character, context};
+ result = {__symbolic: 'error', message, line, character};
};
}
- return {__symbolic: 'error', message, context};
+ if (!result) {
+ result = {__symbolic: 'error', message};
+ }
+ if (context) {
+ result.context = context;
+ }
+ return result;
}
/**
@@ -325,27 +332,36 @@ export class Evaluator {
case ts.SyntaxKind.TypeReference:
const typeReferenceNode = node;
const typeNameNode = typeReferenceNode.typeName;
- if (typeNameNode.kind != ts.SyntaxKind.Identifier) {
- return errorSymbol('Qualified type names not supported', node);
- }
- const typeNameIdentifier = typeReferenceNode.typeName;
- const typeName = typeNameIdentifier.text;
- const typeReference = this.symbols.resolve(typeName);
- if (!typeReference) {
- return errorSymbol('Could not resolve type', node, {typeName});
- }
- if (typeReferenceNode.typeArguments && typeReferenceNode.typeArguments.length) {
- const args = typeReferenceNode.typeArguments.map(element => this.evaluateNode(element));
- if (isMetadataImportedSymbolReferenceExpression(typeReference)) {
- return {
- __symbolic: 'reference',
- module: typeReference.module,
- name: typeReference.name,
- arguments: args
+ const getReference: (typeNameNode: ts.Identifier | ts.QualifiedName) =>
+ MetadataSymbolicReferenceExpression | MetadataError = node => {
+ if (typeNameNode.kind === ts.SyntaxKind.QualifiedName) {
+ const qualifiedName = node;
+ const left = this.evaluateNode(qualifiedName.left);
+ if (isMetadataModuleReferenceExpression(left)) {
+ return {
+ __symbolic: 'reference', module: left.module, name: qualifiedName.right.text
+ }
+ }
+ return errorSymbol('Qualified type names not supported', node);
+ } else {
+ const identifier = typeNameNode;
+ let symbol = this.symbols.resolve(identifier.text);
+ if (isMetadataError(symbol) || isMetadataSymbolicReferenceExpression(symbol)) {
+ return symbol;
+ }
+ return errorSymbol('Could not resolve type', node, {typeName: identifier.text});
+ }
};
- } else if (isMetadataGlobalReferenceExpression(typeReference)) {
- return {__symbolic: 'reference', name: typeReference.name, arguments: args};
- }
+ const typeReference = getReference(typeNameNode);
+ if (isMetadataError(typeReference)) {
+ return typeReference;
+ }
+ if (!isMetadataModuleReferenceExpression(typeReference) &&
+ typeReferenceNode.typeArguments && typeReferenceNode.typeArguments.length) {
+ const args = typeReferenceNode.typeArguments.map(element => this.evaluateNode(element));
+ // TODO: Remove typecast when upgraded to 2.0 as it will be corretly inferred.
+ // Some versions of 1.9 do not infer this correctly.
+ (typeReference).arguments = args;
}
return typeReference;
case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
diff --git a/tools/@angular/tsc-wrapped/src/schema.ts b/tools/@angular/tsc-wrapped/src/schema.ts
index e6a1fdcd8d..4bb94790e8 100644
--- a/tools/@angular/tsc-wrapped/src/schema.ts
+++ b/tools/@angular/tsc-wrapped/src/schema.ts
@@ -165,6 +165,7 @@ export interface MetadataImportedDefaultReferenceExpression extends MetadataSymb
module: string;
default:
boolean;
+ arguments?: MetadataValue[];
}
export function isMetadataImportDefaultReference(value: any):
value is MetadataImportedDefaultReferenceExpression {
diff --git a/tools/@angular/tsc-wrapped/test/collector.spec.ts b/tools/@angular/tsc-wrapped/test/collector.spec.ts
index ec27d3225a..5a32785922 100644
--- a/tools/@angular/tsc-wrapped/test/collector.spec.ts
+++ b/tools/@angular/tsc-wrapped/test/collector.spec.ts
@@ -14,7 +14,7 @@ describe('Collector', () => {
beforeEach(() => {
host = new Host(FILES, [
'/app/app.component.ts', '/app/cases-data.ts', '/app/error-cases.ts', '/promise.ts',
- '/unsupported-1.ts', '/unsupported-2.ts'
+ '/unsupported-1.ts', '/unsupported-2.ts', 'import-star.ts'
]);
service = ts.createLanguageService(host);
program = service.getProgram();
@@ -212,41 +212,16 @@ describe('Collector', () => {
__symbolic: 'module',
version: 1,
metadata: {
- a: {
- __symbolic: 'error',
- message: 'Destructuring declarations cannot be referenced statically',
- line: 1,
- character: 16
- },
- b: {
- __symbolic: 'error',
- message: 'Destructuring declarations cannot be referenced statically',
- line: 1,
- character: 18
- },
- c: {
- __symbolic: 'error',
- message: 'Destructuring declarations cannot be referenced statically',
- line: 2,
- character: 16
- },
- d: {
- __symbolic: 'error',
- message: 'Destructuring declarations cannot be referenced statically',
- line: 2,
- character: 18
- },
- e: {
- __symbolic: 'error',
- message: 'Only intialized variables and constants can be referenced statically',
- line: 3,
- character: 14
- }
+ a: {__symbolic: 'error', message: 'Destructuring not supported', line: 1, character: 16},
+ b: {__symbolic: 'error', message: 'Destructuring not supported', line: 1, character: 18},
+ c: {__symbolic: 'error', message: 'Destructuring not supported', line: 2, character: 16},
+ d: {__symbolic: 'error', message: 'Destructuring not supported', line: 2, character: 18},
+ e: {__symbolic: 'error', message: 'Variable not initialized', line: 3, character: 14}
}
});
});
- it('should report an error for refrences to unexpected types', () => {
+ it('should report an error for references to unexpected types', () => {
let unsupported1 = program.getSourceFile('/unsupported-2.ts');
let metadata = collector.getMetadata(unsupported1);
let barClass = metadata.metadata['Bar'];
@@ -254,11 +229,23 @@ describe('Collector', () => {
let parameter = ctor.parameters[0];
expect(parameter).toEqual({
__symbolic: 'error',
- message: 'Reference to non-exported class Foo',
+ message: 'Reference to non-exported class',
line: 1,
- character: 45
+ character: 45,
+ context: {className: 'Foo'}
});
});
+
+ it('should be able to handle import star type references', () => {
+ let importStar = program.getSourceFile('/import-star.ts');
+ let metadata = collector.getMetadata(importStar);
+ let someClass = metadata.metadata['SomeClass'];
+ let ctor = someClass.members['__ctor__'][0];
+ let parameters = ctor.parameters;
+ expect(parameters).toEqual([
+ {__symbolic: 'reference', module: 'angular2/common', name: 'NgFor'}
+ ]);
+ });
});
// TODO: Do not use \` in a template literal as it confuses clang-format
@@ -468,6 +455,15 @@ const FILES: Directory = {
constructor(private f: Foo) {}
}
`,
+ 'import-star.ts': `
+ import {Injectable} from 'angular2/core';
+ import * as common from 'angular2/common';
+
+ @Injectable()
+ export class SomeClass {
+ constructor(private f: common.NgFor) {}
+ }
+ `,
'node_modules': {
'angular2': {
'core.d.ts': `
diff --git a/tools/@angular/tsc-wrapped/test/evaluator.spec.ts b/tools/@angular/tsc-wrapped/test/evaluator.spec.ts
index dd509f4b7c..f47841bf1f 100644
--- a/tools/@angular/tsc-wrapped/test/evaluator.spec.ts
+++ b/tools/@angular/tsc-wrapped/test/evaluator.spec.ts
@@ -156,31 +156,29 @@ describe('Evaluator', () => {
character: 10
});
let fDecl = findVar(errors, 'f');
- expect(evaluator.evaluateNode(fDecl.initializer)).toEqual({
- __symbolic: 'error',
- message:
- 'Functions cannot be evaluated statically; consider replacing with a reference to an exported function',
- line: 6,
- character: 11
- });
+ expect(evaluator.evaluateNode(fDecl.initializer))
+ .toEqual(
+ {__symbolic: 'error', message: 'Function call not supported', line: 6, character: 11});
let eDecl = findVar(errors, 'e');
expect(evaluator.evaluateNode(eDecl.type)).toEqual({
__symbolic: 'error',
- message: 'Could not resolve type NotFound',
+ message: 'Could not resolve type',
line: 7,
- character: 10
+ character: 10,
+ context: {typeName: 'NotFound'}
});
let sDecl = findVar(errors, 's');
expect(evaluator.evaluateNode(sDecl.initializer)).toEqual({
__symbolic: 'error',
- message: 'Name expected a string or an identifier but received "1"',
+ message: 'Name expected',
line: 8,
- character: 13
+ character: 13,
+ context: {received: '1'}
});
let tDecl = findVar(errors, 't');
expect(evaluator.evaluateNode(tDecl.initializer)).toEqual({
__symbolic: 'error',
- message: 'Expression form not supported statically',
+ message: 'Expression form not supported',
line: 9,
character: 11
});