diff --git a/modules/@angular/compiler-cli/integrationtest/third_party_src/tsconfig-build.json b/modules/@angular/compiler-cli/integrationtest/third_party_src/tsconfig-build.json index fa3e79f5f6..3544d7c598 100644 --- a/modules/@angular/compiler-cli/integrationtest/third_party_src/tsconfig-build.json +++ b/modules/@angular/compiler-cli/integrationtest/third_party_src/tsconfig-build.json @@ -15,6 +15,8 @@ "declaration": true, "lib": ["es6", "dom"], "baseUrl": ".", - "outDir": "../node_modules/third_party" - } + "outDir": "../node_modules/third_party", + // Prevent scanning up the directory tree for types + "typeRoots": ["node_modules/@types"] + } } \ No newline at end of file diff --git a/modules/@angular/compiler-cli/integrationtest/tsconfig-build.json b/modules/@angular/compiler-cli/integrationtest/tsconfig-build.json index c1125b2044..492b26a341 100644 --- a/modules/@angular/compiler-cli/integrationtest/tsconfig-build.json +++ b/modules/@angular/compiler-cli/integrationtest/tsconfig-build.json @@ -14,7 +14,9 @@ "rootDir": "", "declaration": true, "lib": ["es6", "dom"], - "baseUrl": "." + "baseUrl": ".", + // Prevent scanning up the directory tree for types + "typeRoots": ["node_modules/@types"] }, "files": [ diff --git a/modules/@angular/language-service/src/typescript_host.ts b/modules/@angular/language-service/src/typescript_host.ts index 7bc7b72165..06462dbc9e 100644 --- a/modules/@angular/language-service/src/typescript_host.ts +++ b/modules/@angular/language-service/src/typescript_host.ts @@ -29,7 +29,17 @@ import {createLanguageService} from './language_service'; import {ReflectorHost} from './reflector_host'; import {BuiltinType, CompletionKind, Declaration, DeclarationError, Declarations, Definition, LanguageService, LanguageServiceHost, PipeInfo, Pipes, Signature, Span, Symbol, SymbolDeclaration, SymbolQuery, SymbolTable, TemplateSource, TemplateSources} from './types'; - +// In TypeScript 2.1 these flags moved +// These helpers work for both 2.0 and 2.1. +const isPrivate = (ts as any).ModifierFlags ? + ((node: ts.Node) => + !!((ts as any).getCombinedModifierFlags(node) & (ts as any).ModifierFlags.Private)) : + ((node: ts.Node) => !!(node.flags & (ts as any).NodeFlags.Private)); +const isReferenceType = (ts as any).ObjectFlags ? + ((type: ts.Type) => + !!(type.flags & (ts as any).TypeFlags.Object && + (type as any).objectFlags & (ts as any).ObjectFlags.Reference)) : + ((type: ts.Type) => !!(type.flags & (ts as any).TypeFlags.Reference)); /** * Create a `LanguageServiceHost` @@ -680,7 +690,7 @@ class TypeScriptSymbolQuery implements SymbolQuery { const constructorDeclaration = constructor.declarations[0] as ts.ConstructorTypeNode; for (const parameter of constructorDeclaration.parameters) { const type = this.checker.getTypeAtLocation(parameter.type); - if (type.symbol.name == 'TemplateRef' && type.flags & ts.TypeFlags.Reference) { + if (type.symbol.name == 'TemplateRef' && isReferenceType(type)) { const typeReference = type as ts.TypeReference; if (typeReference.typeArguments.length === 1) { return typeReference.typeArguments[0].symbol; @@ -805,7 +815,7 @@ class SymbolWrapper implements Symbol { get public(): boolean { // Symbols that are not explicitly made private are public. - return !(getDeclarationFlagsFromSymbol(this.symbol) & ts.NodeFlags.Private); + return !isSymbolPrivate(this.symbol); } get callable(): boolean { return typeCallable(this.tsType); } @@ -1097,10 +1107,8 @@ function getCombinedNodeFlags(node: ts.Node): ts.NodeFlags { return flags; } -function getDeclarationFlagsFromSymbol(s: ts.Symbol): ts.NodeFlags { - return s.valueDeclaration ? - getCombinedNodeFlags(s.valueDeclaration) : - s.flags & ts.SymbolFlags.Prototype ? ts.NodeFlags.Public | ts.NodeFlags.Static : 0; +function isSymbolPrivate(s: ts.Symbol): boolean { + return s.valueDeclaration && isPrivate(s.valueDeclaration); } function getBuiltinTypeFromTs(kind: BuiltinType, context: TypeContext): ts.Type { @@ -1258,4 +1266,4 @@ function typeKindOf(type: ts.Type): BuiltinType { } } return BuiltinType.Other; -} \ No newline at end of file +} diff --git a/scripts/ci-lite/offline_compiler_test.sh b/scripts/ci-lite/offline_compiler_test.sh index 555ebe50a5..907b07730f 100755 --- a/scripts/ci-lite/offline_compiler_test.sh +++ b/scripts/ci-lite/offline_compiler_test.sh @@ -6,9 +6,10 @@ LINKABLE_PKGS=( $(pwd)/dist/packages-dist/{common,forms,core,compiler,compiler-cli,platform-{browser,server},platform-browser-dynamic,router} $(pwd)/dist/tools/@angular/tsc-wrapped ) +TYPESCRIPT_2_0=typescript@2.0.2 +TYPESCRIPT_2_1=typescript@2.1.4 PKGS=( reflect-metadata@0.1.8 - typescript@2.0.2 zone.js@0.6.25 rxjs@5.0.1 @types/{node@6.0.38,jasmine@2.2.33} @@ -30,7 +31,7 @@ cp -v package.json $TMP ( cd $TMP set -ex -o pipefail - npm install ${PKGS[*]} + npm install ${PKGS[*]} $TYPESCRIPT_2_0 # TODO(alexeagle): allow this to be npm link instead npm install ${LINKABLE_PKGS[*]} @@ -62,3 +63,21 @@ cp -v package.json $TMP mv tsconfig-build.json othername.json ./node_modules/.bin/ngc -p othername.json ) + +# Repeat selected parts of the above with TypeScript 2.1 +readonly TMP_2_1=$TMPDIR/e2e_test.$(date +%s) +mkdir -p $TMP_2_1 +cp -R -v modules/@angular/compiler-cli/integrationtest/* $TMP_2_1 +cp -R -v modules/benchmarks $TMP_2_1 +cp -v package.json $TMP_2_1 +( + cd $TMP_2_1 + set -ex -o pipefail + + npm install ${PKGS[*]} $TYPESCRIPT_2_1 + npm install ${LINKABLE_PKGS[*]} + + ./node_modules/.bin/tsc --version + node ./node_modules/@angular/tsc-wrapped/src/main -p third_party_src/tsconfig-build.json + ./node_modules/.bin/ngc -p tsconfig-build.json --i18nFile=src/messages.fi.xlf --locale=fi --i18nFormat=xlf +) \ No newline at end of file diff --git a/tools/@angular/tsc-wrapped/src/collector.ts b/tools/@angular/tsc-wrapped/src/collector.ts index 31a268ea90..affe5eda8e 100644 --- a/tools/@angular/tsc-wrapped/src/collector.ts +++ b/tools/@angular/tsc-wrapped/src/collector.ts @@ -12,6 +12,16 @@ import {Evaluator, errorSymbol, isPrimitive} from './evaluator'; import {ClassMetadata, ConstructorMetadata, FunctionMetadata, MemberMetadata, MetadataEntry, MetadataError, MetadataMap, MetadataSymbolicBinaryExpression, MetadataSymbolicCallExpression, MetadataSymbolicExpression, MetadataSymbolicIfExpression, MetadataSymbolicIndexExpression, MetadataSymbolicPrefixExpression, MetadataSymbolicReferenceExpression, MetadataSymbolicSelectExpression, MetadataSymbolicSpreadExpression, MetadataValue, MethodMetadata, ModuleExportMetadata, ModuleMetadata, VERSION, isClassMetadata, isConstructorMetadata, isFunctionMetadata, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataSymbolicExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSelectExpression, isMethodMetadata} from './schema'; import {Symbols} from './symbols'; +// In TypeScript 2.1 these flags moved +// These helpers work for both 2.0 and 2.1. +const isExport = (ts as any).ModifierFlags ? + ((node: ts.Node) => + !!((ts as any).getCombinedModifierFlags(node) & (ts as any).ModifierFlags.Export)) : + ((node: ts.Node) => !!((node.flags & (ts as any).NodeFlags.Export))); +const isStatic = (ts as any).ModifierFlags ? + ((node: ts.Node) => + !!((ts as any).getCombinedModifierFlags(node) & (ts as any).ModifierFlags.Static)) : + ((node: ts.Node) => !!((node.flags & (ts as any).NodeFlags.Static))); /** * A set of collector options to use when collecting metadata. @@ -146,7 +156,7 @@ export class MetadataCollector { case ts.SyntaxKind.MethodDeclaration: isConstructor = member.kind === ts.SyntaxKind.Constructor; const method = member; - if (method.flags & ts.NodeFlags.Static) { + if (isStatic(method)) { const maybeFunc = maybeGetSimpleFunction(method); if (maybeFunc) { recordStaticMember(maybeFunc.name, maybeFunc.func); @@ -193,7 +203,7 @@ export class MetadataCollector { case ts.SyntaxKind.GetAccessor: case ts.SyntaxKind.SetAccessor: const property = member; - if (property.flags & ts.NodeFlags.Static) { + if (isStatic(property)) { const name = evaluator.nameOf(property.name); if (!isMetadataError(name)) { if (property.initializer) { @@ -244,7 +254,7 @@ export class MetadataCollector { const isExportedIdentifier = (identifier: ts.Identifier) => exportMap.has(identifier.text); const isExported = (node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.EnumDeclaration) => - (node.flags & ts.NodeFlags.Export) || isExportedIdentifier(node.name); + isExport(node) || isExportedIdentifier(node.name); const exportedIdentifierName = (identifier: ts.Identifier) => exportMap.get(identifier.text) || identifier.text; const exportedName = @@ -404,8 +414,7 @@ export class MetadataCollector { varValue = recordEntry(errorSym('Variable not initialized', nameNode), nameNode); } let exported = false; - if (variableStatement.flags & ts.NodeFlags.Export || - variableDeclaration.flags & ts.NodeFlags.Export || + if (isExport(variableStatement) || isExport(variableDeclaration) || isExportedIdentifier(nameNode)) { if (!metadata) metadata = {}; metadata[exportedIdentifierName(nameNode)] = recordEntry(varValue, node); @@ -430,13 +439,13 @@ export class MetadataCollector { // or // var [[, ; // are not supported. - const report = (nameNode: ts.Node) => { + const report: (nameNode: ts.Node) => void = (nameNode: ts.Node) => { switch (nameNode.kind) { case ts.SyntaxKind.Identifier: const name = nameNode; - const varValue = errorSym('Destructuring not supported', nameNode); + const varValue = errorSym('Destructuring not supported', name); locals.define(name.text, varValue); - if (node.flags & ts.NodeFlags.Export) { + if (isExport(node)) { if (!metadata) metadata = {}; metadata[name.text] = varValue; } @@ -448,7 +457,7 @@ export class MetadataCollector { case ts.SyntaxKind.ObjectBindingPattern: case ts.SyntaxKind.ArrayBindingPattern: const bindings = nameNode; - bindings.elements.forEach(report); + (bindings as any).elements.forEach(report); break; } }; @@ -630,7 +639,10 @@ function namesOf(parameters: ts.NodeArray): string[] { } else { const bindingPattern = name; for (const element of bindingPattern.elements) { - addNamesOf(element.name); + const name = (element as any).name; + if (name) { + addNamesOf(name); + } } } } diff --git a/tools/@angular/tsc-wrapped/src/compiler_host.ts b/tools/@angular/tsc-wrapped/src/compiler_host.ts index 773e99d619..6afcb127ee 100644 --- a/tools/@angular/tsc-wrapped/src/compiler_host.ts +++ b/tools/@angular/tsc-wrapped/src/compiler_host.ts @@ -119,9 +119,19 @@ export class MetadataWriterHost extends DelegatingHost { // released if (/*DTS*/ /\.js$/.test(emitFilePath)) { const path = emitFilePath.replace(/*DTS*/ /\.js$/, '.metadata.json'); + + // Beginning with 2.1, TypeScript transforms the source tree before emitting it. + // We need the original, unmodified, tree which might be several levels back + // depending on the number of transforms performed. All SourceFile's prior to 2.1 + // will appear to be the original source since they didn't include an original field. + let collectableFile = sourceFile; + while ((collectableFile as any).original) { + collectableFile = (collectableFile as any).original; + } + const metadata = - this.metadataCollector.getMetadata(sourceFile, !!this.ngOptions.strictMetadataEmit); - const metadata1 = this.metadataCollector1.getMetadata(sourceFile, false); + this.metadataCollector.getMetadata(collectableFile, !!this.ngOptions.strictMetadataEmit); + const metadata1 = this.metadataCollector1.getMetadata(collectableFile, false); const metadatas: ModuleMetadata[] = [metadata, metadata1].filter(e => !!e); if (metadatas.length) { const metadataText = JSON.stringify(metadatas); diff --git a/tools/@angular/tsc-wrapped/src/evaluator.ts b/tools/@angular/tsc-wrapped/src/evaluator.ts index b668da190f..3b471315c7 100644 --- a/tools/@angular/tsc-wrapped/src/evaluator.ts +++ b/tools/@angular/tsc-wrapped/src/evaluator.ts @@ -12,6 +12,10 @@ import {CollectorOptions} from './collector'; import {MetadataEntry, MetadataError, MetadataGlobalReferenceExpression, MetadataImportedSymbolReferenceExpression, MetadataSymbolicCallExpression, MetadataSymbolicReferenceExpression, MetadataValue, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataImportedSymbolReferenceExpression, isMetadataModuleReferenceExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSpreadExpression} from './schema'; import {Symbols} from './symbols'; +// In TypeScript 2.1 the spread element kind was renamed. +const spreadElementSyntaxKind: ts.SyntaxKind = + (ts.SyntaxKind as any).SpreadElement || (ts.SyntaxKind as any).SpreadElementExpression; + function isMethodCallOf(callExpression: ts.CallExpression, memberName: string): boolean { const expression = callExpression.expression; if (expression.kind === ts.SyntaxKind.PropertyAccessExpression) { @@ -282,9 +286,8 @@ export class Evaluator { }); if (error) return error; return arr; - case ts.SyntaxKind.SpreadElementExpression: - let spread = node; - let spreadExpression = this.evaluateNode(spread.expression); + case spreadElementSyntaxKind: + let spreadExpression = this.evaluateNode((node as any).expression); return recordEntry({__symbolic: 'spread', expression: spreadExpression}, node); case ts.SyntaxKind.CallExpression: const callExpression = node;