feat: add TypeScript 3 support (#25275)

PR Close #25275
This commit is contained in:
Alan Agius 2018-08-05 17:31:27 +02:00 committed by Matias Niemelä
parent c230173716
commit 5653fada32
30 changed files with 219 additions and 86 deletions

View File

@ -0,0 +1,49 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import * as compiler from '@angular/compiler';
import * as compilerTesting from '@angular/compiler/testing';
import * as core from '@angular/core';
import * as coreTesting from '@angular/core/testing';
import * as elements from '@angular/elements';
import * as forms from '@angular/forms';
import * as http from '@angular/http';
import * as httpTesting from '@angular/http/testing';
import * as platformBrowser from '@angular/platform-browser';
import * as platformBrowserTesting from '@angular/platform-browser/testing';
import * as platformBrowserDynamic from '@angular/platform-browser-dynamic';
import * as platformServer from '@angular/platform-server';
import * as platformServerTesting from '@angular/platform-server/testing';
import * as platformWebworker from '@angular/platform-webworker';
import * as platformWebworkerDynamic from '@angular/platform-webworker-dynamic';
import * as router from '@angular/router';
import * as routerTesting from '@angular/router/testing';
import * as serviceWorker from '@angular/service-worker';
import * as upgrade from '@angular/upgrade';
export default {
compiler,
compilerTesting,
core,
coreTesting,
elements,
forms,
http,
httpTesting,
platformBrowser,
platformBrowserTesting,
platformBrowserDynamic,
platformServer,
platformServerTesting,
platformWebworker,
platformWebworkerDynamic,
router,
routerTesting,
serviceWorker,
upgrade,
};

View File

@ -0,0 +1,31 @@
{
"name": "angular-integration",
"description": "Assert that users with TypeScript 3.0 can type-check an Angular application",
"version": "0.0.0",
"license": "MIT",
"dependencies": {
"@angular/animations": "file:../../dist/packages-dist/animations",
"@angular/common": "file:../../dist/packages-dist/common",
"@angular/compiler": "file:../../dist/packages-dist/compiler",
"@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli",
"@angular/core": "file:../../dist/packages-dist/core",
"@angular/elements": "file:../../dist/packages-dist/elements",
"@angular/forms": "file:../../dist/packages-dist/forms",
"@angular/http": "file:../../dist/packages-dist/http",
"@angular/platform-browser": "file:../../dist/packages-dist/platform-browser",
"@angular/platform-browser-dynamic": "file:../../dist/packages-dist/platform-browser-dynamic",
"@angular/platform-server": "file:../../dist/packages-dist/platform-server",
"@angular/platform-webworker": "file:../../dist/packages-dist/platform-webworker",
"@angular/platform-webworker-dynamic": "file:../../dist/packages-dist/platform-webworker-dynamic",
"@angular/router": "file:../../dist/packages-dist/router",
"@angular/service-worker": "file:../../dist/packages-dist/service-worker",
"@angular/upgrade": "file:../../dist/packages-dist/upgrade",
"@types/jasmine": "2.5.41",
"rxjs": "file:../../node_modules/rxjs",
"typescript": "3.0.x",
"zone.js": "file:../../node_modules/zone.js"
},
"scripts": {
"test": "tsc"
}
}

View File

@ -0,0 +1,24 @@
{
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"module": "commonjs",
"moduleResolution": "node",
"outDir": "../../dist/typings_test_ts30/",
"rootDir": ".",
"target": "es5",
"lib": [
"es5",
"dom",
"es2015.collection",
"es2015.iterable",
"es2015.promise"
],
"types": [],
"strictNullChecks": true
},
"files": [
"include-all.ts",
"node_modules/@types/jasmine/index.d.ts"
]
}

View File

@ -124,7 +124,7 @@
"tslint": "5.7.0", "tslint": "5.7.0",
"tslint-eslint-rules": "4.1.1", "tslint-eslint-rules": "4.1.1",
"tsutils": "2.20.0", "tsutils": "2.20.0",
"typescript": "2.9.x", "typescript": "~3.0.1",
"uglify-es": "^3.3.9", "uglify-es": "^3.3.9",
"universal-analytics": "0.4.15", "universal-analytics": "0.4.15",
"vlq": "0.2.2", "vlq": "0.2.2",

View File

@ -11,7 +11,7 @@
}, },
"peerDependencies": { "peerDependencies": {
"@angular/compiler-cli": "0.0.0-PLACEHOLDER", "@angular/compiler-cli": "0.0.0-PLACEHOLDER",
"typescript": ">=2.7.2 <2.10" "typescript": ">=3.0.1 <3.1"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -18,10 +18,10 @@ import {ConsoleReporter, Injector, MeasureValues, SampleDescription} from '../..
function createReporter( function createReporter(
{columnWidth = null, sampleId = null, descriptions = null, metrics = null}: { {columnWidth = null, sampleId = null, descriptions = null, metrics = null}: {
columnWidth?: number, columnWidth?: number | null,
sampleId?: string, sampleId?: string | null,
descriptions?: {[key: string]: any}[], descriptions?: {[key: string]: any}[] | null,
metrics?: {[key: string]: any} metrics?: {[key: string]: any} | null
}) { }) {
log = []; log = [];
if (!descriptions) { if (!descriptions) {

View File

@ -314,7 +314,7 @@ export class HttpXhrBackend implements HttpBackend {
} }
// Fire the request, and notify the event stream that it was fired. // Fire the request, and notify the event stream that it was fired.
xhr.send(reqBody); xhr.send(reqBody !);
observer.next({type: HttpEventType.Sent}); observer.next({type: HttpEventType.Sent});
// This is the return from the Observable function, which is the // This is the return from the Observable function, which is the

View File

@ -19,8 +19,8 @@
"source-map": "^0.6.1" "source-map": "^0.6.1"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": ">=2.7.2 <2.10", "@angular/compiler": "0.0.0-PLACEHOLDER",
"@angular/compiler": "0.0.0-PLACEHOLDER" "typescript": ">=3.0.1 <3.1"
}, },
"engines" : { "engines" : {
"node" : ">=8.0" "node" : ">=8.0"

View File

@ -12,7 +12,8 @@ import {Evaluator, errorSymbol, recordMapEntry} from './evaluator';
import {ClassMetadata, ConstructorMetadata, FunctionMetadata, InterfaceMetadata, METADATA_VERSION, MemberMetadata, MetadataEntry, MetadataError, MetadataMap, MetadataSymbolicBinaryExpression, MetadataSymbolicCallExpression, MetadataSymbolicExpression, MetadataSymbolicIfExpression, MetadataSymbolicIndexExpression, MetadataSymbolicPrefixExpression, MetadataSymbolicReferenceExpression, MetadataSymbolicSelectExpression, MetadataSymbolicSpreadExpression, MetadataValue, MethodMetadata, ModuleExportMetadata, ModuleMetadata, isClassMetadata, isConstructorMetadata, isFunctionMetadata, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataImportDefaultReference, isMetadataImportedSymbolReferenceExpression, isMetadataSymbolicExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSelectExpression, isMethodMetadata} from './schema'; import {ClassMetadata, ConstructorMetadata, FunctionMetadata, InterfaceMetadata, METADATA_VERSION, MemberMetadata, MetadataEntry, MetadataError, MetadataMap, MetadataSymbolicBinaryExpression, MetadataSymbolicCallExpression, MetadataSymbolicExpression, MetadataSymbolicIfExpression, MetadataSymbolicIndexExpression, MetadataSymbolicPrefixExpression, MetadataSymbolicReferenceExpression, MetadataSymbolicSelectExpression, MetadataSymbolicSpreadExpression, MetadataValue, MethodMetadata, ModuleExportMetadata, ModuleMetadata, isClassMetadata, isConstructorMetadata, isFunctionMetadata, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataImportDefaultReference, isMetadataImportedSymbolReferenceExpression, isMetadataSymbolicExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSelectExpression, isMethodMetadata} from './schema';
import {Symbols} from './symbols'; import {Symbols} from './symbols';
const isStatic = (node: ts.Node) => ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Static; const isStatic = (node: ts.Declaration) =>
ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Static;
/** /**
* A set of collector options to use when collecting metadata. * A set of collector options to use when collecting metadata.
@ -277,8 +278,8 @@ export class MetadataCollector {
} }
}); });
const isExport = (node: ts.Node) => const isExport = (node: ts.Node) => sourceFile.isDeclarationFile ||
sourceFile.isDeclarationFile || ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export; ts.getCombinedModifierFlags(node as ts.Declaration) & ts.ModifierFlags.Export;
const isExportedIdentifier = (identifier?: ts.Identifier) => const isExportedIdentifier = (identifier?: ts.Identifier) =>
identifier && exportMap.has(identifier.text); identifier && exportMap.has(identifier.text);
const isExported = const isExported =

View File

@ -224,7 +224,8 @@ function isEligibleForLowering(node: ts.Node | undefined): boolean {
return false; return false;
case ts.SyntaxKind.VariableDeclaration: case ts.SyntaxKind.VariableDeclaration:
// Avoid lowering expressions already in an exported variable declaration // Avoid lowering expressions already in an exported variable declaration
return (ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) == 0; return (ts.getCombinedModifierFlags(node as ts.VariableDeclaration) &
ts.ModifierFlags.Export) == 0;
} }
return isEligibleForLowering(node.parent); return isEligibleForLowering(node.parent);
} }
@ -370,7 +371,7 @@ function createExportTableFor(sourceFile: ts.SourceFile): Set<string> {
case ts.SyntaxKind.ClassDeclaration: case ts.SyntaxKind.ClassDeclaration:
case ts.SyntaxKind.FunctionDeclaration: case ts.SyntaxKind.FunctionDeclaration:
case ts.SyntaxKind.InterfaceDeclaration: case ts.SyntaxKind.InterfaceDeclaration:
if ((ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) != 0) { if ((ts.getCombinedModifierFlags(node as ts.Declaration) & ts.ModifierFlags.Export) != 0) {
const classDeclaration = const classDeclaration =
node as(ts.ClassDeclaration | ts.FunctionDeclaration | ts.InterfaceDeclaration); node as(ts.ClassDeclaration | ts.FunctionDeclaration | ts.InterfaceDeclaration);
const name = classDeclaration.name; const name = classDeclaration.name;
@ -385,7 +386,7 @@ function createExportTableFor(sourceFile: ts.SourceFile): Set<string> {
break; break;
case ts.SyntaxKind.VariableDeclaration: case ts.SyntaxKind.VariableDeclaration:
const variableDeclaration = node as ts.VariableDeclaration; const variableDeclaration = node as ts.VariableDeclaration;
if ((ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) != 0 && if ((ts.getCombinedModifierFlags(variableDeclaration) & ts.ModifierFlags.Export) != 0 &&
variableDeclaration.name.kind == ts.SyntaxKind.Identifier) { variableDeclaration.name.kind == ts.SyntaxKind.Identifier) {
const name = variableDeclaration.name as ts.Identifier; const name = variableDeclaration.name as ts.Identifier;
exportTable.add(name.text); exportTable.add(name.text);

View File

@ -102,14 +102,14 @@ const defaultEmitCallback: TsEmitCallback =
* Minimum supported TypeScript version * Minimum supported TypeScript version
* supported typescript version v, v >= MIN_TS_VERSION * supported typescript version v, v >= MIN_TS_VERSION
*/ */
const MIN_TS_VERSION = '2.7.2'; const MIN_TS_VERSION = '3.0.1';
/** /**
* Supremum of supported TypeScript versions * Supremum of supported TypeScript versions
* supported typescript version v, v < MAX_TS_VERSION * supported typescript version v, v < MAX_TS_VERSION
* MAX_TS_VERSION is not considered as a supported TypeScript version * MAX_TS_VERSION is not considered as a supported TypeScript version
*/ */
const MAX_TS_VERSION = '2.10.0'; const MAX_TS_VERSION = '3.1.0';
class AngularCompilerProgram implements Program { class AngularCompilerProgram implements Program {
private rootNames: string[]; private rootNames: string[];

View File

@ -29,13 +29,13 @@ describe('expression diagnostics', () => {
registry = ts.createDocumentRegistry(false, '/src'); registry = ts.createDocumentRegistry(false, '/src');
host = new MockLanguageServiceHost(['app/app.component.ts'], FILES, '/src'); host = new MockLanguageServiceHost(['app/app.component.ts'], FILES, '/src');
service = ts.createLanguageService(host, registry); service = ts.createLanguageService(host, registry);
const program = service.getProgram(); const program = service.getProgram() !;
const checker = program.getTypeChecker(); const checker = program.getTypeChecker();
const options: CompilerOptions = Object.create(host.getCompilationSettings()); const options: CompilerOptions = Object.create(host.getCompilationSettings());
options.genDir = '/dist'; options.genDir = '/dist';
options.basePath = '/src'; options.basePath = '/src';
const symbolResolverHost = new ReflectorHost(() => program, host, options); const symbolResolverHost = new ReflectorHost(() => program !, host, options);
context = new DiagnosticContext(service, program, checker, symbolResolverHost); context = new DiagnosticContext(service, program !, checker, symbolResolverHost);
type = context.getStaticSymbol('app/app.component.ts', 'AppComponent'); type = context.getStaticSymbol('app/app.component.ts', 'AppComponent');
}); });

View File

@ -39,7 +39,7 @@ describe('symbol query', () => {
const host = new MockLanguageServiceHost( const host = new MockLanguageServiceHost(
['/quickstart/app/app.component.ts'], QUICKSTART, '/quickstart'); ['/quickstart/app/app.component.ts'], QUICKSTART, '/quickstart');
const service = ts.createLanguageService(host, registry); const service = ts.createLanguageService(host, registry);
program = service.getProgram(); program = service.getProgram() !;
checker = program.getTypeChecker(); checker = program.getTypeChecker();
sourceFile = program.getSourceFile('/quickstart/app/app.component.ts') !; sourceFile = program.getSourceFile('/quickstart/app/app.component.ts') !;
const options: CompilerOptions = Object.create(host.getCompilationSettings()); const options: CompilerOptions = Object.create(host.getCompilationSettings());

View File

@ -40,7 +40,7 @@ describe('Collector', () => {
'interface-reference.ts' 'interface-reference.ts'
]); ]);
service = ts.createLanguageService(host, documentRegistry); service = ts.createLanguageService(host, documentRegistry);
program = service.getProgram(); program = service.getProgram() !;
collector = new MetadataCollector({quotedNames: true}); collector = new MetadataCollector({quotedNames: true});
}); });
@ -1128,7 +1128,7 @@ describe('Collector', () => {
function override(fileName: string, content: string) { function override(fileName: string, content: string) {
host.overrideFile(fileName, content); host.overrideFile(fileName, content);
host.addFile(fileName); host.addFile(fileName);
program = service.getProgram(); program = service.getProgram() !;
} }
function collectSource(content: string): ModuleMetadata { function collectSource(content: string): ModuleMetadata {

View File

@ -29,7 +29,7 @@ describe('Evaluator', () => {
'newExpression.ts', 'errors.ts', 'declared.ts' 'newExpression.ts', 'errors.ts', 'declared.ts'
]); ]);
service = ts.createLanguageService(host, documentRegistry); service = ts.createLanguageService(host, documentRegistry);
program = service.getProgram(); program = service.getProgram() !;
typeChecker = program.getTypeChecker(); typeChecker = program.getTypeChecker();
symbols = new Symbols(null as any as ts.SourceFile); symbols = new Symbols(null as any as ts.SourceFile);
evaluator = new Evaluator(symbols, new Map()); evaluator = new Evaluator(symbols, new Map());

View File

@ -42,7 +42,7 @@ describe('Symbols', () => {
beforeEach(() => { beforeEach(() => {
host = new Host(FILES, ['consts.ts', 'expressions.ts', 'imports.ts']); host = new Host(FILES, ['consts.ts', 'expressions.ts', 'imports.ts']);
service = ts.createLanguageService(host); service = ts.createLanguageService(host);
program = service.getProgram(); program = service.getProgram() !;
expressions = program.getSourceFile('expressions.ts') !; expressions = program.getSourceFile('expressions.ts') !;
imports = program.getSourceFile('imports.ts') !; imports = program.getSourceFile('imports.ts') !;
}); });

View File

@ -7,6 +7,7 @@
*/ */
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
export interface Directory { [name: string]: (Directory|string); } export interface Directory { [name: string]: (Directory|string); }
@ -54,8 +55,10 @@ export class Host implements ts.LanguageServiceHost {
if (this.overrides.has(fileName)) { if (this.overrides.has(fileName)) {
return this.overrides.get(fileName); return this.overrides.get(fileName);
} }
if (fileName.endsWith('lib.d.ts')) { if (/lib(.*)\.d\.ts/.test(fileName)) {
return fs.readFileSync(ts.getDefaultLibFilePath(this.getCompilationSettings()), 'utf8'); const libDirPath = path.dirname(ts.getDefaultLibFilePath(this.getCompilationSettings()));
const libPath = path.join(libDirPath, fileName);
return fs.readFileSync(libPath, 'utf8');
} }
const current = open(this.directory, fileName); const current = open(this.directory, fileName);
if (typeof current === 'string') return current; if (typeof current === 'string') return current;
@ -76,6 +79,9 @@ export function open(directory: Directory, fileName: string): Directory|string|u
} }
export class MockNode implements ts.Node { export class MockNode implements ts.Node {
decorators?: ts.NodeArray<ts.Decorator>;
modifiers?: ts.NodeArray<ts.Modifier>;
parent !: ts.Node;
constructor( constructor(
public kind: ts.SyntaxKind = ts.SyntaxKind.Identifier, public flags: ts.NodeFlags = 0, public kind: ts.SyntaxKind = ts.SyntaxKind.Identifier, public flags: ts.NodeFlags = 0,
public pos: number = 0, public end: number = 0) {} public pos: number = 0, public end: number = 0) {}
@ -101,6 +107,11 @@ export class MockNode implements ts.Node {
} }
export class MockIdentifier extends MockNode implements ts.Identifier { export class MockIdentifier extends MockNode implements ts.Identifier {
originalKeywordKind?: ts.SyntaxKind;
isInJSDocNamespace?: boolean;
decorators?: ts.NodeArray<ts.Decorator>;
modifiers?: ts.NodeArray<ts.Modifier>;
parent !: ts.Node;
public text: string; public text: string;
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
public escapedText !: ts.__String; public escapedText !: ts.__String;
@ -124,6 +135,12 @@ export class MockIdentifier extends MockNode implements ts.Identifier {
} }
export class MockVariableDeclaration extends MockNode implements ts.VariableDeclaration { export class MockVariableDeclaration extends MockNode implements ts.VariableDeclaration {
parent !: ts.VariableDeclarationList | ts.CatchClause;
exclamationToken?: ts.Token<ts.SyntaxKind.ExclamationToken>;
type?: ts.TypeNode;
initializer?: ts.Expression;
decorators?: ts.NodeArray<ts.Decorator>;
modifiers?: ts.NodeArray<ts.Modifier>;
// tslint:disable-next-line // tslint:disable-next-line
public _declarationBrand: any; public _declarationBrand: any;
@ -140,6 +157,11 @@ export class MockVariableDeclaration extends MockNode implements ts.VariableDecl
} }
export class MockSymbol implements ts.Symbol { export class MockSymbol implements ts.Symbol {
declarations !: ts.Declaration[];
valueDeclaration !: ts.Declaration;
members?: ts.UnderscoreEscapedMap<ts.Symbol>;
exports?: ts.UnderscoreEscapedMap<ts.Symbol>;
globalExports?: ts.UnderscoreEscapedMap<ts.Symbol>;
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
public escapedName !: ts.__String; public escapedName !: ts.__String;
constructor( constructor(

View File

@ -83,7 +83,7 @@ function createTestSupportFor(basePath: string) {
'lib': [ 'lib': [
path.resolve(basePath, 'node_modules/typescript/lib/lib.es6.d.ts'), path.resolve(basePath, 'node_modules/typescript/lib/lib.es6.d.ts'),
], ],
...overrideOptions, 'paths': {'@angular/*': ['./node_modules/@angular/*']}, ...overrideOptions,
}; };
} }

View File

@ -26,7 +26,7 @@ export class CompilerConfig {
defaultEncapsulation?: ViewEncapsulation, defaultEncapsulation?: ViewEncapsulation,
useJit?: boolean, useJit?: boolean,
jitDevMode?: boolean, jitDevMode?: boolean,
missingTranslation?: MissingTranslationStrategy, missingTranslation?: MissingTranslationStrategy|null,
preserveWhitespaces?: boolean, preserveWhitespaces?: boolean,
strictInjectionParameters?: boolean, strictInjectionParameters?: boolean,
} = {}) { } = {}) {

View File

@ -1137,8 +1137,8 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
function createDir( function createDir(
selector: string, {providers = null, viewProviders = null, deps = [], queries = []}: { selector: string, {providers = null, viewProviders = null, deps = [], queries = []}: {
providers?: CompileProviderMetadata[], providers?: CompileProviderMetadata[] | null,
viewProviders?: CompileProviderMetadata[], viewProviders?: CompileProviderMetadata[] | null,
deps?: string[], deps?: string[],
queries?: string[] queries?: string[]
} = {}): CompileDirectiveSummary { } = {}): CompileDirectiveSummary {

View File

@ -80,7 +80,7 @@ export class InertBodyHelper {
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
xhr.responseType = 'document'; xhr.responseType = 'document';
xhr.open('GET', 'data:text/html;charset=utf-8,' + html, false); xhr.open('GET', 'data:text/html;charset=utf-8,' + html, false);
xhr.send(null); xhr.send(undefined);
const body: HTMLBodyElement = xhr.response.body; const body: HTMLBodyElement = xhr.response.body;
body.removeChild(body.firstChild !); body.removeChild(body.firstChild !);
return body; return body;

View File

@ -27,7 +27,7 @@ export function create(info: any /* ts.server.PluginCreateInfo */): ts.LanguageS
let oldLS: ts.LanguageService = info.languageService; let oldLS: ts.LanguageService = info.languageService;
function tryCall<T>(fileName: string | undefined, callback: () => T): T { function tryCall<T>(fileName: string | undefined, callback: () => T): T {
if (fileName && !oldLS.getProgram().getSourceFile(fileName)) { if (fileName && !oldLS.getProgram() !.getSourceFile(fileName)) {
return undefined as any as T; return undefined as any as T;
} }
try { try {
@ -84,10 +84,11 @@ export function create(info: any /* ts.server.PluginCreateInfo */): ts.LanguageS
getCompletionsAtPosition: tryFilenameTwoCall(ls.getCompletionsAtPosition), getCompletionsAtPosition: tryFilenameTwoCall(ls.getCompletionsAtPosition),
getCompletionEntryDetails: tryFilenameFiveCall(ls.getCompletionEntryDetails), getCompletionEntryDetails: tryFilenameFiveCall(ls.getCompletionEntryDetails),
getCompletionEntrySymbol: tryFilenameThreeCall(ls.getCompletionEntrySymbol), getCompletionEntrySymbol: tryFilenameThreeCall(ls.getCompletionEntrySymbol),
getJsxClosingTagAtPosition: tryFilenameOneCall(ls.getJsxClosingTagAtPosition),
getQuickInfoAtPosition: tryFilenameOneCall(ls.getQuickInfoAtPosition), getQuickInfoAtPosition: tryFilenameOneCall(ls.getQuickInfoAtPosition),
getNameOrDottedNameSpan: tryFilenameTwoCall(ls.getNameOrDottedNameSpan), getNameOrDottedNameSpan: tryFilenameTwoCall(ls.getNameOrDottedNameSpan),
getBreakpointStatementAtPosition: tryFilenameOneCall(ls.getBreakpointStatementAtPosition), getBreakpointStatementAtPosition: tryFilenameOneCall(ls.getBreakpointStatementAtPosition),
getSignatureHelpItems: tryFilenameOneCall(ls.getSignatureHelpItems), getSignatureHelpItems: tryFilenameTwoCall(ls.getSignatureHelpItems),
getRenameInfo: tryFilenameOneCall(ls.getRenameInfo), getRenameInfo: tryFilenameOneCall(ls.getRenameInfo),
findRenameLocations: tryFilenameThreeCall(ls.findRenameLocations), findRenameLocations: tryFilenameThreeCall(ls.findRenameLocations),
getDefinitionAtPosition: tryFilenameOneCall(ls.getDefinitionAtPosition), getDefinitionAtPosition: tryFilenameOneCall(ls.getDefinitionAtPosition),
@ -229,32 +230,33 @@ export function create(info: any /* ts.server.PluginCreateInfo */): ts.LanguageS
return base; return base;
}; };
proxy.getQuickInfoAtPosition = function(fileName: string, position: number): ts.QuickInfo { proxy.getQuickInfoAtPosition = function(fileName: string, position: number): ts.QuickInfo |
let base = oldLS.getQuickInfoAtPosition(fileName, position); undefined {
// TODO(vicb): the tags property has been removed in TS 2.2 let base = oldLS.getQuickInfoAtPosition(fileName, position);
tryOperation('get quick info', () => { // TODO(vicb): the tags property has been removed in TS 2.2
const ours = ls.getHoverAt(fileName, position); tryOperation('get quick info', () => {
if (ours) { const ours = ls.getHoverAt(fileName, position);
const displayParts: ts.SymbolDisplayPart[] = []; if (ours) {
for (const part of ours.text) { const displayParts: ts.SymbolDisplayPart[] = [];
displayParts.push({kind: part.language || 'angular', text: part.text}); for (const part of ours.text) {
} displayParts.push({kind: part.language || 'angular', text: part.text});
const tags = base && (<any>base).tags; }
base = <any>{ const tags = base && (<any>base).tags;
displayParts, base = <any>{
documentation: [], displayParts,
kind: 'angular', documentation: [],
kindModifiers: 'what does this do?', kind: 'angular',
textSpan: {start: ours.span.start, length: ours.span.end - ours.span.start}, kindModifiers: 'what does this do?',
}; textSpan: {start: ours.span.start, length: ours.span.end - ours.span.start},
if (tags) { };
(<any>base).tags = tags; if (tags) {
} (<any>base).tags = tags;
} }
}); }
});
return base; return base;
}; };
proxy.getSemanticDiagnostics = function(fileName: string) { proxy.getSemanticDiagnostics = function(fileName: string) {
let result = oldLS.getSemanticDiagnostics(fileName); let result = oldLS.getSemanticDiagnostics(fileName);
@ -263,7 +265,7 @@ export function create(info: any /* ts.server.PluginCreateInfo */): ts.LanguageS
info.project.projectService.logger.info(`Computing Angular semantic diagnostics...`); info.project.projectService.logger.info(`Computing Angular semantic diagnostics...`);
const ours = ls.getDiagnostics(fileName); const ours = ls.getDiagnostics(fileName);
if (ours && ours.length) { if (ours && ours.length) {
const file = oldLS.getProgram().getSourceFile(fileName); const file = oldLS.getProgram() !.getSourceFile(fileName);
if (file) { if (file) {
base.push.apply(base, ours.map(d => diagnosticToDiagnostic(d, file))); base.push.apply(base, ours.map(d => diagnosticToDiagnostic(d, file)));
} }

View File

@ -166,7 +166,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
}; };
} else { } else {
const analyzeHost = {isSourceFile(filePath: string) { return true; }}; const analyzeHost = {isSourceFile(filePath: string) { return true; }};
const programFiles = this.program.getSourceFiles().map(sf => sf.fileName); const programFiles = this.program !.getSourceFiles().map(sf => sf.fileName);
analyzedModules = analyzedModules =
analyzeNgModules(programFiles, analyzeHost, this.staticSymbolResolver, this.resolver); analyzeNgModules(programFiles, analyzeHost, this.staticSymbolResolver, this.resolver);
} }
@ -224,7 +224,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
} }
getSourceFile(fileName: string): ts.SourceFile|undefined { getSourceFile(fileName: string): ts.SourceFile|undefined {
return this.tsService.getProgram().getSourceFile(fileName); return this.tsService.getProgram() !.getSourceFile(fileName);
} }
updateAnalyzedModules() { updateAnalyzedModules() {
@ -244,7 +244,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
private get checker() { private get checker() {
let checker = this._checker; let checker = this._checker;
if (!checker) { if (!checker) {
checker = this._checker = this.program.getTypeChecker(); checker = this._checker = this.program !.getTypeChecker();
} }
return checker; return checker;
} }
@ -257,7 +257,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
this._staticSymbolResolver.invalidateFile(fileName); this._staticSymbolResolver.invalidateFile(fileName);
this.clearCaches(); this.clearCaches();
const seen = new Set<string>(); const seen = new Set<string>();
for (let sourceFile of this.program.getSourceFiles()) { for (let sourceFile of this.program !.getSourceFiles()) {
const fileName = sourceFile.fileName; const fileName = sourceFile.fileName;
seen.add(fileName); seen.add(fileName);
const version = this.host.getScriptVersion(fileName); const version = this.host.getScriptVersion(fileName);
@ -325,14 +325,14 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
span, span,
type, type,
get members() { get members() {
return getClassMembersFromDeclaration(t.program, t.checker, sourceFile, declaration); return getClassMembersFromDeclaration(t.program !, t.checker, sourceFile, declaration);
}, },
get query() { get query() {
if (!queryCache) { if (!queryCache) {
const pipes = t.service.getPipesAt(fileName, node.getStart()); const pipes = t.service.getPipesAt(fileName, node.getStart());
queryCache = getSymbolQuery( queryCache = getSymbolQuery(
t.program, t.checker, sourceFile, t.program !, t.checker, sourceFile,
() => getPipesTable(sourceFile, t.program, t.checker, pipes)); () => getPipesTable(sourceFile, t.program !, t.checker, pipes));
} }
return queryCache; return queryCache;
} }
@ -394,7 +394,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
// The host's getCurrentDirectory() is not reliable as it is always "" in // The host's getCurrentDirectory() is not reliable as it is always "" in
// tsserver. We don't need the exact base directory, just one that contains // tsserver. We don't need the exact base directory, just one that contains
// a source file. // a source file.
const source = this.tsService.getProgram().getSourceFile(this.context); const source = this.tsService.getProgram() !.getSourceFile(this.context);
if (!source) { if (!source) {
throw new Error('Internal error: no context could be determined'); throw new Error('Internal error: no context could be determined');
} }
@ -410,7 +410,7 @@ export class TypeScriptServiceHost implements LanguageServiceHost {
options.paths = compilerOptions.paths; options.paths = compilerOptions.paths;
} }
result = this._reflectorHost = result = this._reflectorHost =
new ReflectorHost(() => this.tsService.getProgram(), this.host, options); new ReflectorHost(() => this.tsService.getProgram() !, this.host, options);
} }
return result; return result;
} }

View File

@ -26,7 +26,7 @@ describe('references', () => {
beforeEach(() => { beforeEach(() => {
mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts'], toh); mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts'], toh);
service = ts.createLanguageService(mockHost, documentRegistry); service = ts.createLanguageService(mockHost, documentRegistry);
program = service.getProgram(); program = service.getProgram() !;
ngHost = new TypeScriptServiceHost(mockHost, service); ngHost = new TypeScriptServiceHost(mockHost, service);
ngService = createLanguageService(ngHost); ngService = createLanguageService(ngHost);
ngHost.setSite(ngService); ngHost.setSite(ngService);

View File

@ -25,7 +25,7 @@ describe('plugin', () => {
it('should not report errors on tour of heroes', () => { it('should not report errors on tour of heroes', () => {
expectNoDiagnostics(service.getCompilerOptionsDiagnostics()); expectNoDiagnostics(service.getCompilerOptionsDiagnostics());
for (let source of program.getSourceFiles()) { for (let source of program !.getSourceFiles()) {
expectNoDiagnostics(service.getSyntacticDiagnostics(source.fileName)); expectNoDiagnostics(service.getSyntacticDiagnostics(source.fileName));
expectNoDiagnostics(service.getSemanticDiagnostics(source.fileName)); expectNoDiagnostics(service.getSemanticDiagnostics(source.fileName));
} }
@ -36,7 +36,7 @@ describe('plugin', () => {
{ts: ts, languageService: service, project: mockProject, languageServiceHost: mockHost}); {ts: ts, languageService: service, project: mockProject, languageServiceHost: mockHost});
it('should not report template errors on tour of heroes', () => { it('should not report template errors on tour of heroes', () => {
for (let source of program.getSourceFiles()) { for (let source of program !.getSourceFiles()) {
// Ignore all 'cases.ts' files as they intentionally contain errors. // Ignore all 'cases.ts' files as they intentionally contain errors.
if (!source.fileName.endsWith('cases.ts')) { if (!source.fileName.endsWith('cases.ts')) {
expectNoDiagnostics(plugin.getSemanticDiagnostics(source.fileName)); expectNoDiagnostics(plugin.getSemanticDiagnostics(source.fileName));
@ -204,12 +204,12 @@ describe('plugin', () => {
function contains(fileName: string, locationMarker: string, ...names: string[]) { function contains(fileName: string, locationMarker: string, ...names: string[]) {
const location = getMarkerLocation(fileName, locationMarker); const location = getMarkerLocation(fileName, locationMarker);
expectEntries( expectEntries(
locationMarker, plugin.getCompletionsAtPosition(fileName, location, undefined), ...names); locationMarker, plugin.getCompletionsAtPosition(fileName, location, undefined) !, ...names);
} }
function expectEmpty(fileName: string, locationMarker: string) { function expectEmpty(fileName: string, locationMarker: string) {
const location = getMarkerLocation(fileName, locationMarker); const location = getMarkerLocation(fileName, locationMarker);
expect(plugin.getCompletionsAtPosition(fileName, location, undefined).entries || []).toEqual([ expect(plugin.getCompletionsAtPosition(fileName, location, undefined) !.entries || []).toEqual([
]); ]);
} }

View File

@ -7,6 +7,7 @@
*/ */
export class MockBody implements Body { export class MockBody implements Body {
readonly body !: ReadableStream;
bodyUsed: boolean = false; bodyUsed: boolean = false;
constructor(public _body: string|null) {} constructor(public _body: string|null) {}
@ -80,6 +81,9 @@ export class MockHeaders implements Headers {
} }
export class MockRequest extends MockBody implements Request { export class MockRequest extends MockBody implements Request {
readonly isHistoryNavigation: boolean = false;
readonly isReloadNavigation: boolean = false;
readonly body !: ReadableStream;
readonly cache: RequestCache = 'default'; readonly cache: RequestCache = 'default';
readonly credentials: RequestCredentials = 'omit'; readonly credentials: RequestCredentials = 'omit';
readonly destination: RequestDestination = 'document'; readonly destination: RequestDestination = 'document';
@ -91,7 +95,6 @@ export class MockRequest extends MockBody implements Request {
readonly redirect: RequestRedirect = 'error'; readonly redirect: RequestRedirect = 'error';
readonly referrer: string = ''; readonly referrer: string = '';
readonly referrerPolicy: ReferrerPolicy = 'no-referrer'; readonly referrerPolicy: ReferrerPolicy = 'no-referrer';
readonly type: RequestType = '';
readonly signal: AbortSignal = null as any; readonly signal: AbortSignal = null as any;
url: string; url: string;
@ -132,13 +135,13 @@ export class MockRequest extends MockBody implements Request {
} }
export class MockResponse extends MockBody implements Response { export class MockResponse extends MockBody implements Response {
readonly trailer: Promise<Headers> = Promise.resolve(new MockHeaders());
readonly headers: Headers = new MockHeaders(); readonly headers: Headers = new MockHeaders();
get ok(): boolean { return this.status >= 200 && this.status < 300; } get ok(): boolean { return this.status >= 200 && this.status < 300; }
readonly status: number; readonly status: number;
readonly statusText: string; readonly statusText: string;
readonly type: ResponseType = 'basic'; readonly type: ResponseType = 'basic';
readonly url: string = ''; readonly url: string = '';
readonly body: ReadableStream|null = null;
readonly redirected: boolean = false; readonly redirected: boolean = false;
constructor( constructor(

View File

@ -550,7 +550,7 @@ export declare class NgZone {
readonly onStable: EventEmitter<any>; readonly onStable: EventEmitter<any>;
readonly onUnstable: EventEmitter<any>; readonly onUnstable: EventEmitter<any>;
constructor({ enableLongStackTrace }: { constructor({ enableLongStackTrace }: {
enableLongStackTrace?: boolean; enableLongStackTrace?: boolean | undefined;
}); });
run<T>(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any[]): T; run<T>(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any[]): T;
runGuarded<T>(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any[]): T; runGuarded<T>(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any[]): T;

View File

@ -11,7 +11,7 @@
"test": "test" "test": "test"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": "^2.6.1" "typescript": "^3.0.1"
}, },
"dependencies": { "dependencies": {
"chalk": "^2.3.1", "chalk": "^2.3.1",
@ -21,7 +21,7 @@
"devDependencies": { "devDependencies": {
"chai": "^4.1.2", "chai": "^4.1.2",
"jasmine": "^3.1.0", "jasmine": "^3.1.0",
"typescript": "~2.6.2" "typescript": "~3.0.1"
}, },
"repository": {}, "repository": {},
"keywords": [ "keywords": [

View File

@ -153,9 +153,9 @@ type-detect@^4.0.0:
version "4.0.8" version "4.0.8"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
typescript@~2.6.2: typescript@~3.0.1:
version "2.6.2" version "3.0.1"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.0.1.tgz#43738f29585d3a87575520a4b93ab6026ef11fdb"
wrappy@1: wrappy@1:
version "1.0.2" version "1.0.2"

View File

@ -7079,14 +7079,14 @@ typedarray@^0.0.6:
version "0.0.6" version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
typescript@2.9.x:
version "2.9.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c"
"typescript@>=2.6.2 <2.8": "typescript@>=2.6.2 <2.8":
version "2.7.2" version "2.7.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836"
typescript@~3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/npm/OBG-NPM/typescript/-/typescript-3.0.1.tgz#43738f29585d3a87575520a4b93ab6026ef11fdb"
uglify-es@^3.3.9: uglify-es@^3.3.9:
version "3.3.9" version "3.3.9"
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677"