From e48bf6bf05ef7a15abdad6691d11ec6e454c69a3 Mon Sep 17 00:00:00 2001 From: Tom van Ommeren Date: Thu, 21 Sep 2017 08:21:05 +0200 Subject: [PATCH 01/13] fix: bump package version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c77757592..2ff39be4e 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "opentracing": "^0.14.0", "semaphore-async-await": "^1.5.1", "string-similarity": "^1.1.0", - "typescript": "2.3.4", + "typescript": "2.4.2", "vscode-jsonrpc": "^3.3.1", "vscode-languageserver": "^3.1.0", "vscode-languageserver-types": "^3.0.3" From 78db06af97d4f0e3d27c71a431182ffa7163b318 Mon Sep 17 00:00:00 2001 From: Tom van Ommeren Date: Thu, 21 Sep 2017 08:23:36 +0200 Subject: [PATCH 02/13] fix: TS diagnostics fields are now optional --- src/diagnostics.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/diagnostics.ts b/src/diagnostics.ts index ed33f54fc..ca239d370 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -1,17 +1,20 @@ - import * as ts from 'typescript'; -import { Diagnostic, DiagnosticSeverity } from 'vscode-languageserver'; +import { Diagnostic, DiagnosticSeverity, Range } from 'vscode-languageserver'; /** * Converts a TypeScript Diagnostic to an LSP Diagnostic */ export function convertTsDiagnostic(diagnostic: ts.Diagnostic): Diagnostic { const text = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); - return { - range: { + let range: Range = { start: {character: 0, line: 0}, end: {character: 0, line: 0} }; + if (diagnostic.file && diagnostic.start && diagnostic.length) { + range = { start: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start), end: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start + diagnostic.length) - }, + }; + } + return { + range, message: text, severity: convertDiagnosticCategory(diagnostic.category), code: diagnostic.code, From fbc46712b365a5e1acc45b50c148693792a95edf Mon Sep 17 00:00:00 2001 From: Tom van Ommeren Date: Thu, 21 Sep 2017 08:26:16 +0200 Subject: [PATCH 03/13] fix: pass more restrictive type to url.format --- src/packages.ts | 2 +- src/typescript-service.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages.ts b/src/packages.ts index 2f1631a26..6ac5a8a22 100644 --- a/src/packages.ts +++ b/src/packages.ts @@ -193,7 +193,7 @@ export class PackageManager extends EventEmitter implements Disposable { * @return The found package.json or undefined if none found */ getClosestPackageJsonUri(uri: string): string | undefined { - const parts = url.parse(uri); + const parts: url.UrlObject = url.parse(uri); while (true) { if (!parts.pathname) { return undefined; diff --git a/src/typescript-service.ts b/src/typescript-service.ts index a889a5198..fb1030452 100644 --- a/src/typescript-service.ts +++ b/src/typescript-service.ts @@ -453,7 +453,7 @@ export class TypeScriptService { // The symbol is part of a dependency in node_modules // Build URI to package.json of the Dependency const encodedPackageName = packageName.split('/').map(encodeURIComponent).join('/'); - const parts = url.parse(uri); + const parts: url.UrlObject = url.parse(uri); const packageJsonUri = url.format({ ...parts, pathname: parts.pathname!.slice(0, parts.pathname!.lastIndexOf('/node_modules/' + encodedPackageName)) + `/node_modules/${encodedPackageName}/package.json` }); // Fetch the package.json of the dependency return this.updater.ensure(packageJsonUri, span) From af7ac3d527ac991131bd838137027ca3c783acef Mon Sep 17 00:00:00 2001 From: Tom van Ommeren Date: Thu, 21 Sep 2017 08:29:22 +0200 Subject: [PATCH 04/13] fix: TS2394 overload signature not compatible issues --- src/connection.ts | 4 ++-- src/packages.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/connection.ts b/src/connection.ts index 5218cfacb..dcfd67cba 100644 --- a/src/connection.ts +++ b/src/connection.ts @@ -82,7 +82,7 @@ export class MessageEmitter extends EventEmitter { /** Emitted when the underlying input stream was closed */ on(event: 'close', listener: () => void): this; /* istanbul ignore next */ - on(event: string, listener: () => void): this { + on(event: string, listener: (arg?: any) => void): this { return super.on(event, listener); } @@ -93,7 +93,7 @@ export class MessageEmitter extends EventEmitter { /** Emitted when the underlying input stream was closed */ once(event: 'close', listener: () => void): this; /* istanbul ignore next */ - once(event: string, listener: () => void): this { + once(event: string, listener: (arg?: any) => void): this { return super.on(event, listener); } } diff --git a/src/packages.ts b/src/packages.ts index 6ac5a8a22..ac11bc812 100644 --- a/src/packages.ts +++ b/src/packages.ts @@ -132,7 +132,7 @@ export class PackageManager extends EventEmitter implements Disposable { /** Emitted when a new package.json was found and parsed */ on(event: 'parsed', listener: (uri: string, packageJson: PackageJson) => void): this; - on(event: string, listener: () => void): this { + on(event: string, listener: (...args: any[]) => void): this { return super.on(event, listener); } From 776be8551f58158f2671e827192cb3da2e15d6ec Mon Sep 17 00:00:00 2001 From: Tom van Ommeren Date: Thu, 21 Sep 2017 08:35:15 +0200 Subject: [PATCH 05/13] fix: locations used in definitions to github test --- src/test/typescript-service-helpers.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/typescript-service-helpers.ts b/src/test/typescript-service-helpers.ts index d4da745a5..1c293b19d 100644 --- a/src/test/typescript-service-helpers.ts +++ b/src/test/typescript-service-helpers.ts @@ -1829,11 +1829,11 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor uri: 'git://github.com/Microsoft/TypeScript?v' + ts.version + '#lib/lib.dom.d.ts', range: { start: { - line: 8258, + line: 8259, character: 10 }, end: { - line: 8258, + line: 8259, character: 14 } } @@ -1841,11 +1841,11 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor uri: 'git://github.com/Microsoft/TypeScript?v' + ts.version + '#lib/lib.dom.d.ts', range: { start: { - line: 8310, + line: 8311, character: 12 }, end: { - line: 8310, + line: 8311, character: 16 } } From e4d6c35793362fcde829e390a2a1c9fa22cddbd5 Mon Sep 17 00:00:00 2001 From: Tom van Ommeren Date: Thu, 21 Sep 2017 22:29:29 +0200 Subject: [PATCH 06/13] fix: add resolved references to TS for imports This fixes imports (tests and at runtime) --- src/project-manager.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/project-manager.ts b/src/project-manager.ts index a5ef62198..973729f4f 100644 --- a/src/project-manager.ts +++ b/src/project-manager.ts @@ -368,6 +368,7 @@ export class ProjectManager implements Disposable { const config = this.getConfiguration(referencingFilePath); config.ensureBasicFiles(span); const contents = this.inMemoryFs.getContent(uri); + config.ensureSourceFile(referencingFilePath, span); const info = ts.preProcessFile(contents, true, true); const compilerOpt = config.getHost().getCompilationSettings(); const pathResolver = referencingFilePath.includes('\\') ? path.win32 : path.posix; From 761d9f4c3ad9c5cd13d6a092dbb24f2d7df0118a Mon Sep 17 00:00:00 2001 From: Tom van Ommeren Date: Thu, 21 Sep 2017 22:31:08 +0200 Subject: [PATCH 07/13] fix: Switch to getChildren() in ast --- src/ast.ts | 806 +---------------------------------------------------- 1 file changed, 1 insertion(+), 805 deletions(-) diff --git a/src/ast.ts b/src/ast.ts index ae70f8b55..f17555e84 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -8,814 +8,10 @@ import * as ts from 'typescript'; */ export function *walkMostAST(node: ts.Node): IterableIterator { yield node; - // TODO don't maintain an array - const children: ts.Node[] = []; - switch (node.kind) { - case ts.SyntaxKind.QualifiedName: { - const n = node as ts.QualifiedName; - children.push(n.left, n.right); - break; - } - case ts.SyntaxKind.ComputedPropertyName: { - const n = node as ts.ComputedPropertyName; - children.push(n.expression); - break; - } - case ts.SyntaxKind.TypeParameter: { - const n = node as ts.TypeParameterDeclaration; - pushall(children, n.name, n.constraint, n.expression); - break; - } - case ts.SyntaxKind.Parameter: { - const n = node as ts.ParameterDeclaration; - pushall(children, n.name, n.type, n.initializer); - break; - } - case ts.SyntaxKind.Decorator: { - const n = node as ts.Decorator; - children.push(n.expression); - break; - } - case ts.SyntaxKind.PropertySignature: { - const n = node as ts.PropertySignature; - pushall(children, n.name, n.type, n.initializer); - break; - } - case ts.SyntaxKind.PropertyDeclaration: { - const n = node as ts.PropertyDeclaration; - pushall(children, n.name, n.type, n.initializer); - break; - } - case ts.SyntaxKind.MethodSignature: { - const n = node as ts.MethodSignature; - pushall(children, n.name, n.type); - if (n.typeParameters) { - children.push(...n.typeParameters); - } - if (n.parameters) { - children.push(...n.parameters); - } - break; - } - case ts.SyntaxKind.MethodDeclaration: { - const n = node as ts.MethodDeclaration; - pushall(children, n.name, n.body); - break; - } - case ts.SyntaxKind.Constructor: { - const n = node as ts.ConstructorDeclaration; - pushall(children, n.name, n.body); - break; - } - case ts.SyntaxKind.GetAccessor: { - const n = node as ts.GetAccessorDeclaration; - children.push(n.name, n.body); - break; - } - case ts.SyntaxKind.SetAccessor: { - const n = node as ts.SetAccessorDeclaration; - children.push(n.name, n.body); - break; - } - case ts.SyntaxKind.CallSignature: { - const n = node as ts.CallSignatureDeclaration; - pushall(children, n.name, n.type); - if (n.typeParameters) { - children.push(...n.typeParameters); - } - if (n.parameters) { - children.push(...n.parameters); - } - break; - } - case ts.SyntaxKind.ConstructSignature: { - const n = node as ts.ConstructSignatureDeclaration; - pushall(children, n.name, n.type); - if (n.typeParameters) { - children.push(...n.typeParameters); - } - if (n.parameters) { - children.push(...n.parameters); - } - break; - } - case ts.SyntaxKind.IndexSignature: { - const n = node as ts.IndexSignatureDeclaration; - pushall(children, n.name, n.type); - if (n.typeParameters) { - children.push(...n.typeParameters); - } - if (n.parameters) { - children.push(...n.parameters); - } - break; - } - case ts.SyntaxKind.TypePredicate: { - const n = node as ts.TypePredicateNode; - children.push(n.parameterName, n.type); - break; - } - case ts.SyntaxKind.TypeReference: { - const n = node as ts.TypeReferenceNode; - children.push(n.typeName); - if (n.typeArguments) { - children.push(...n.typeArguments); - } - break; - } - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.FunctionType: { - const n = node as ts.FunctionOrConstructorTypeNode; - pushall(children, n.name, n.type); - pushall(children, n.name, n.type); - if (n.typeParameters) { - children.push(...n.typeParameters); - } - if (n.parameters) { - children.push(...n.parameters); - } - break; - } - case ts.SyntaxKind.TypeQuery: { - const n = node as ts.TypeQueryNode; - children.push(n.exprName); - break; - } - case ts.SyntaxKind.TypeLiteral: { - const n = node as ts.TypeLiteralNode; - pushall(children, n.name); - children.push(...n.members); - break; - } - case ts.SyntaxKind.ArrayType: { - const n = node as ts.ArrayTypeNode; - children.push(n.elementType); - break; - } - case ts.SyntaxKind.TupleType: { - const n = node as ts.TupleTypeNode; - children.push(...n.elementTypes); - break; - } - case ts.SyntaxKind.IntersectionType: - case ts.SyntaxKind.UnionType: { - const n = node as ts.UnionTypeNode; - children.push(...n.types); - break; - } - case ts.SyntaxKind.ParenthesizedType: { - const n = node as ts.ParenthesizedTypeNode; - children.push(n.type); - break; - } - case ts.SyntaxKind.LiteralType: { - const n = node as ts.LiteralTypeNode; - children.push(n.literal); - break; - } - case ts.SyntaxKind.ObjectBindingPattern: - case ts.SyntaxKind.ArrayBindingPattern: { - const n = node as ts.ObjectBindingPattern; - children.push(...n.elements); - break; - } - case ts.SyntaxKind.BindingElement: { - const n = node as ts.BindingElement; - pushall(children, n.propertyName, n.name, n.initializer); - break; - } - case ts.SyntaxKind.ArrayLiteralExpression: { - const n = node as ts.ArrayLiteralExpression; - children.push(...n.elements); - break; - } - case ts.SyntaxKind.ObjectLiteralExpression: { - const n = node as ts.ObjectLiteralExpression; - children.push(...n.properties); - break; - } - case ts.SyntaxKind.PropertyAccessExpression: { - const n = node as ts.PropertyAccessExpression; - children.push(n.expression, n.name); - break; - } - case ts.SyntaxKind.ElementAccessExpression: { - const n = node as ts.ElementAccessExpression; - pushall(children, n.expression, n.argumentExpression); - break; - } - case ts.SyntaxKind.CallExpression: { - const n = node as ts.CallExpression; - pushall(children, n.name, n.expression, ...n.arguments); - if (n.typeArguments) { - children.push(...n.typeArguments); - } - break; - } - case ts.SyntaxKind.NewExpression: { - const n = node as ts.NewExpression; - if (n.name) { - yield* walkMostAST(n.name); - } - yield* walkMostAST(n.expression); - if (n.arguments) { - for (const argument of n.arguments) { - yield* walkMostAST(argument); - } - } - if (n.typeArguments) { - for (const typeArgument of n.typeArguments) { - yield* walkMostAST(typeArgument); - } - } - break; - } - case ts.SyntaxKind.TaggedTemplateExpression: { - const n = node as ts.TaggedTemplateExpression; - children.push(n.tag, n.template); - break; - } - case ts.SyntaxKind.TypeAssertionExpression: { - const n = node as ts.TypeAssertion; - children.push(n.type, n.expression); - break; - } - case ts.SyntaxKind.ParenthesizedExpression: { - const n = node as ts.ParenthesizedExpression; - children.push(n.expression); - break; - } - case ts.SyntaxKind.FunctionExpression: { - const n = node as ts.FunctionExpression; - pushall(children, n.name, n.body); - break; - } - case ts.SyntaxKind.ArrowFunction: { - const n = node as ts.ArrowFunction; - children.push(n.body); - break; - } - case ts.SyntaxKind.DeleteExpression: { - const n = node as ts.DeleteExpression; - children.push(n.expression); - break; - } - case ts.SyntaxKind.TypeOfExpression: { - const n = node as ts.TypeOfExpression; - children.push(n.expression); - break; - } - case ts.SyntaxKind.VoidExpression: { - const n = node as ts.VoidExpression; - children.push(n.expression); - break; - } - case ts.SyntaxKind.AwaitExpression: { - const n = node as ts.AwaitExpression; - children.push(n.expression); - break; - } - case ts.SyntaxKind.PrefixUnaryExpression: { - const n = node as ts.PrefixUnaryExpression; - children.push(n.operand); - break; - } - case ts.SyntaxKind.PostfixUnaryExpression: { - const n = node as ts.PostfixUnaryExpression; - children.push(n.operand); - break; - } - case ts.SyntaxKind.BinaryExpression: { - const n = node as ts.BinaryExpression; - children.push(n.left, n.right); - break; - } - case ts.SyntaxKind.ConditionalExpression: { - const n = node as ts.ConditionalExpression; - children.push(n.condition, n.whenTrue, n.whenFalse); - break; - } - case ts.SyntaxKind.TemplateExpression: { - const n = node as ts.TemplateExpression; - children.push(n.head, ...n.templateSpans); - break; - } - case ts.SyntaxKind.YieldExpression: { - const n = node as ts.YieldExpression; - pushall(children, n.expression); - break; - } - case ts.SyntaxKind.SpreadElement: { - const n = node as ts.SpreadElement; - children.push(n.expression); - break; - } - case ts.SyntaxKind.ClassExpression: { - const n = node as ts.ClassExpression; - pushall(children, n.name, ...n.members); - if (n.typeParameters) { - children.push(...n.typeParameters); - } - if (n.heritageClauses) { - children.push(...n.heritageClauses); - } - break; - } - case ts.SyntaxKind.ExpressionWithTypeArguments: { - const n = node as ts.ExpressionWithTypeArguments; - children.push(n.expression); - if (n.typeArguments) { - children.push(...n.typeArguments); - } - break; - } - case ts.SyntaxKind.AsExpression: { - const n = node as ts.AsExpression; - children.push(n.expression, n.type); - break; - } - case ts.SyntaxKind.NonNullExpression: { - const n = node as ts.NonNullExpression; - children.push(n.expression); - break; - } - case ts.SyntaxKind.TemplateSpan: { - const n = node as ts.TemplateSpan; - children.push(n.expression, n.literal); - break; - } - case ts.SyntaxKind.SemicolonClassElement: { - const n = node as ts.SemicolonClassElement; - if (n.name) { - children.push(n.name); - } - break; - } - case ts.SyntaxKind.Block: { - const n = node as ts.Block; - children.push(...n.statements); - break; - } - case ts.SyntaxKind.VariableStatement: { - const n = node as ts.VariableStatement; - children.push(n.declarationList); - break; - } - case ts.SyntaxKind.ExpressionStatement: { - const n = node as ts.ExpressionStatement; - children.push(n.expression); - break; - } - case ts.SyntaxKind.IfStatement: { - const n = node as ts.IfStatement; - pushall(children, n.expression, n.thenStatement, n.elseStatement); - break; - } - case ts.SyntaxKind.DoStatement: { - const n = node as ts.DoStatement; - children.push(n.expression, n.statement); - break; - } - case ts.SyntaxKind.WhileStatement: { - const n = node as ts.WhileStatement; - children.push(n.expression, n.statement); - break; - } - case ts.SyntaxKind.ForStatement: { - const n = node as ts.ForStatement; - pushall(children, n.initializer, n.condition, n.incrementor, n.statement); - break; - } - case ts.SyntaxKind.ForInStatement: { - const n = node as ts.ForInStatement; - children.push(n.initializer, n.expression, n.statement); - break; - } - case ts.SyntaxKind.ForOfStatement: { - const n = node as ts.ForOfStatement; - children.push(n.initializer, n.expression, n.statement); - break; - } - case ts.SyntaxKind.ContinueStatement: { - const n = node as ts.ContinueStatement; - if (n.label) { - children.push(n.label); - } - break; - } - case ts.SyntaxKind.BreakStatement: { - const n = node as ts.BreakStatement; - if (n.label) { - children.push(n.label); - } - break; - } - case ts.SyntaxKind.ReturnStatement: { - const n = node as ts.ReturnStatement; - if (n.expression) { - children.push(n.expression); - } - break; - } - case ts.SyntaxKind.WithStatement: { - const n = node as ts.WithStatement; - children.push(n.expression, n.statement); - break; - } - case ts.SyntaxKind.SwitchStatement: { - const n = node as ts.SwitchStatement; - children.push(n.expression, n.caseBlock); - break; - } - case ts.SyntaxKind.LabeledStatement: { - const n = node as ts.LabeledStatement; - children.push(n.label, n.statement); - break; - } - case ts.SyntaxKind.ThrowStatement: { - const n = node as ts.ThrowStatement; - children.push(n.expression); - break; - } - case ts.SyntaxKind.TryStatement: { - const n = node as ts.TryStatement; - pushall(children, n.tryBlock, n.catchClause, n.finallyBlock); - break; - } - case ts.SyntaxKind.VariableDeclaration: { - const n = node as ts.VariableDeclaration; - pushall(children, n.name, n.type, n.initializer); - break; - } - case ts.SyntaxKind.VariableDeclarationList: { - const n = node as ts.VariableDeclarationList; - children.push(...n.declarations); - break; - } - case ts.SyntaxKind.FunctionDeclaration: { - const n = node as ts.FunctionDeclaration; - pushall(children, n.name, n.body, n.type, ...n.parameters); - if (n.typeParameters) { - children.push(...n.typeParameters); - } - break; - } - case ts.SyntaxKind.ClassDeclaration: { - const n = node as ts.ClassDeclaration; - pushall(children, n.name, ...n.members); - if (n.typeParameters) { - children.push(...n.typeParameters); - } - if (n.heritageClauses) { - children.push(...n.heritageClauses); - } - break; - } - case ts.SyntaxKind.InterfaceDeclaration: { - const n = node as ts.InterfaceDeclaration; - children.push(n.name, ...n.members); - if (n.typeParameters) { - children.push(...n.typeParameters); - } - if (n.heritageClauses) { - children.push(...n.heritageClauses); - } - break; - } - case ts.SyntaxKind.TypeAliasDeclaration: { - const n = node as ts.TypeAliasDeclaration; - children.push(n.name, n.type); - if (n.typeParameters) { - children.push(...n.typeParameters); - } - break; - } - case ts.SyntaxKind.EnumDeclaration: { - const n = node as ts.EnumDeclaration; - children.push(n.name, ...n.members); - break; - } - case ts.SyntaxKind.ModuleDeclaration: { - const n = node as ts.ModuleDeclaration; - pushall(children, n.name, n.body); - break; - } - case ts.SyntaxKind.ModuleBlock: { - const n = node as ts.ModuleBlock; - children.push(...n.statements); - break; - } - case ts.SyntaxKind.CaseBlock: { - const n = node as ts.CaseBlock; - children.push(...n.clauses); - break; - } - case ts.SyntaxKind.NamespaceExportDeclaration: { - const n = node as ts.NamespaceExportDeclaration; - yield* walkMostAST(n.name); - break; - } - case ts.SyntaxKind.ImportEqualsDeclaration: { - const n = node as ts.ImportEqualsDeclaration; - children.push(n.name, n.moduleReference); - break; - } - case ts.SyntaxKind.ImportDeclaration: { - const n = node as ts.ImportDeclaration; - pushall(children, n.importClause, n.moduleSpecifier); - break; - } - case ts.SyntaxKind.ImportClause: { - const n = node as ts.ImportClause; - pushall(children, n.name, n.namedBindings); - break; - } - case ts.SyntaxKind.NamespaceImport: { - const n = node as ts.NamespaceImport; - children.push(n.name); - break; - } - case ts.SyntaxKind.NamedImports: { - const n = node as ts.NamedImports; - children.push(...n.elements); - break; - } - case ts.SyntaxKind.ImportSpecifier: { - const n = node as ts.ImportSpecifier; - pushall(children, n.propertyName, n.name); - break; - } - case ts.SyntaxKind.ExportAssignment: { - const n = node as ts.ExportAssignment; - pushall(children, n.name, n.expression); - break; - } - case ts.SyntaxKind.ExportDeclaration: { - const n = node as ts.ExportDeclaration; - pushall(children, n.exportClause, n.moduleSpecifier, n.name); - break; - } - case ts.SyntaxKind.NamedExports: { - const n = node as ts.NamedExports; - children.push(...n.elements); - break; - } - case ts.SyntaxKind.ExportSpecifier: { - const n = node as ts.ExportSpecifier; - pushall(children, n.propertyName, n.name); - break; - } - case ts.SyntaxKind.MissingDeclaration: { - const n = node as ts.MissingDeclaration; - if (n.name) { - children.push(n.name); - } - break; - } - case ts.SyntaxKind.ExternalModuleReference: { - const n = node as ts.ExternalModuleReference; - pushall(children, n.expression); - break; - } - case ts.SyntaxKind.JsxElement: { - const n = node as ts.JsxElement; - children.push(n.openingElement, n.closingElement, ...n.children); - break; - } - case ts.SyntaxKind.JsxSelfClosingElement: { - const n = node as ts.JsxSelfClosingElement; - yield* walkMostAST(n.tagName); - for (const property of n.attributes.properties) { - yield* walkMostAST(property); - } - break; - } - case ts.SyntaxKind.JsxOpeningElement: { - const n = node as ts.JsxOpeningElement; - yield* walkMostAST(n.tagName); - yield* walkMostAST(n.attributes); - break; - } - case ts.SyntaxKind.JsxClosingElement: { - const n = node as ts.JsxClosingElement; - children.push(n.tagName); - break; - } - case ts.SyntaxKind.JsxAttribute: { - const n = node as ts.JsxAttribute; - pushall(children, n.name, n.initializer); - break; - } - case ts.SyntaxKind.JsxSpreadAttribute: { - const n = node as ts.JsxSpreadAttribute; - children.push(n.expression); - break; - } - case ts.SyntaxKind.JsxExpression: { - const n = node as ts.JsxExpression; - if (n.expression) { - children.push(n.expression); - } - break; - } - case ts.SyntaxKind.CaseClause: { - const n = node as ts.CaseClause; - children.push(n.expression, ...n.statements); - break; - } - case ts.SyntaxKind.DefaultClause: { - const n = node as ts.DefaultClause; - children.push(...n.statements); - break; - } - case ts.SyntaxKind.HeritageClause: { - const n = node as ts.HeritageClause; - if (n.types) { - children.push(...n.types); - } - break; - } - case ts.SyntaxKind.CatchClause: { - const n = node as ts.CatchClause; - children.push(n.variableDeclaration, n.block); - break; - } - case ts.SyntaxKind.PropertyAssignment: { - const n = node as ts.PropertyAssignment; - children.push(n.name, n.initializer); - break; - } - case ts.SyntaxKind.ShorthandPropertyAssignment: { - const n = node as ts.ShorthandPropertyAssignment; - pushall(children, n.name, n.objectAssignmentInitializer); - break; - } - case ts.SyntaxKind.EnumMember: { - const n = node as ts.EnumMember; - pushall(children, n.name, n.initializer); - break; - } - case ts.SyntaxKind.SourceFile: { - const n = node as ts.SourceFile; - children.push(...n.statements); - break; - } - case ts.SyntaxKind.JSDocTypeExpression: { - const n = node as ts.JSDocTypeExpression; - children.push(n.type); - break; - } - case ts.SyntaxKind.JSDocArrayType: { - const n = node as ts.JSDocArrayType; - children.push(n.elementType); - break; - } - case ts.SyntaxKind.JSDocUnionType: { - const n = node as ts.JSDocUnionType; - children.push(...n.types); - break; - } - case ts.SyntaxKind.JSDocTupleType: { - const n = node as ts.JSDocTupleType; - children.push(...n.types); - break; - } - case ts.SyntaxKind.JSDocNullableType: { - const n = node as ts.JSDocNullableType; - children.push(n.type); - break; - } - case ts.SyntaxKind.JSDocNonNullableType: { - const n = node as ts.JSDocNonNullableType; - children.push(n.type); - break; - } - case ts.SyntaxKind.JSDocRecordType: { - const n = node as ts.JSDocRecordType; - children.push(n.literal); - break; - } - case ts.SyntaxKind.JSDocRecordMember: { - const n = node as ts.JSDocRecordMember; - pushall(children, n.name, n.type, n.initializer); - break; - } - case ts.SyntaxKind.JSDocTypeReference: { - const n = node as ts.JSDocTypeReference; - children.push(n.name, ...n.typeArguments); - break; - } - case ts.SyntaxKind.JSDocOptionalType: { - const n = node as ts.JSDocOptionalType; - children.push(n.type); - break; - } - case ts.SyntaxKind.JSDocFunctionType: { - const n = node as ts.JSDocFunctionType; - pushall(children, n.name, n.type, ...n.parameters); - if (n.typeParameters) { - children.push(...n.typeParameters); - } - break; - } - case ts.SyntaxKind.JSDocVariadicType: { - const n = node as ts.JSDocVariadicType; - children.push(n.type); - break; - } - case ts.SyntaxKind.JSDocConstructorType: { - const n = node as ts.JSDocConstructorType; - children.push(n.type); - break; - } - case ts.SyntaxKind.JSDocThisType: { - const n = node as ts.JSDocThisType; - children.push(n.type); - break; - } - case ts.SyntaxKind.JSDocComment: { - const n = node as ts.JSDoc; - if (n.tags) { - children.push(...n.tags); - } - break; - } - case ts.SyntaxKind.JSDocTag: { - const n = node as ts.JSDocTag; - children.push(n.tagName); - break; - } - case ts.SyntaxKind.JSDocParameterTag: { - const n = node as ts.JSDocParameterTag; - pushall(children, n.typeExpression, n.postParameterName, n.parameterName); - if (n.preParameterName) { - children.push(n.preParameterName); - } - break; - } - case ts.SyntaxKind.JSDocReturnTag: { - const n = node as ts.JSDocReturnTag; - children.push(n.typeExpression); - break; - } - case ts.SyntaxKind.JSDocTypeTag: { - const n = node as ts.JSDocTypeTag; - children.push(n.typeExpression); - break; - } - case ts.SyntaxKind.JSDocTemplateTag: { - const n = node as ts.JSDocTemplateTag; - children.push(...n.typeParameters); - break; - } - case ts.SyntaxKind.JSDocTypedefTag: { - const n = node as ts.JSDocTypedefTag; - pushall(children, n.fullName, n.typeExpression, n.jsDocTypeLiteral); - if (n.name) { - children.push(n.name); - } - break; - } - case ts.SyntaxKind.JSDocPropertyTag: { - const n = node as ts.JSDocPropertyTag; - children.push(n.name, n.typeExpression); - break; - } - case ts.SyntaxKind.JSDocTypeLiteral: { - const n = node as ts.JSDocTypeLiteral; - if (n.jsDocPropertyTags) { - children.push(...n.jsDocPropertyTags); - } - if (n.jsDocTypeTag) { - children.push(n.jsDocTypeTag); - } - break; - } - case ts.SyntaxKind.JSDocLiteralType: { - const n = node as ts.JSDocLiteralType; - children.push(n.literal); - break; - } - case ts.SyntaxKind.SyntaxList: { - const n = node as ts.SyntaxList; - children.push(...n._children); - break; - } - default: - break; - } + const children = node.getChildren(); for (const child of children) { if (child) { yield* walkMostAST(child); } } } - -function pushall(arr: T[], ...elems: (T | null | undefined)[]): number { - for (const e of elems) { - if (e) { - arr.push(e); - } - } - return arr.length; -} From 8908437479a97a4485c5493218a3350fd4c1e1ea Mon Sep 17 00:00:00 2001 From: Tom van Ommeren Date: Sat, 23 Sep 2017 12:29:16 +0200 Subject: [PATCH 08/13] fix: instances where generics typing needed to be preserved --- src/fs.ts | 4 ++-- src/project-manager.ts | 9 +++++---- src/util.ts | 7 +++++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/fs.ts b/src/fs.ts index ba901bf25..e2bddfe13 100644 --- a/src/fs.ts +++ b/src/fs.ts @@ -139,7 +139,7 @@ export class FileSystemUpdater { }) .ignoreElements() .publishReplay() - .refCount(); + .refCount() as Observable; this.fetches.set(uri, observable); return observable; } @@ -174,7 +174,7 @@ export class FileSystemUpdater { }) .ignoreElements() .publishReplay() - .refCount() + .refCount() as Observable ); this.structureFetch = observable; return observable; diff --git a/src/project-manager.ts b/src/project-manager.ts index 973729f4f..424598ece 100644 --- a/src/project-manager.ts +++ b/src/project-manager.ts @@ -16,6 +16,7 @@ import { isJSTSFile, isPackageJsonFile, observableFromIterable, + pairOf, path2uri, toUnixPath, uri2path @@ -146,7 +147,7 @@ export class ProjectManager implements Disposable { // Whenever a file with content is added to the InMemoryFileSystem, check if it's a tsconfig.json and add a new ProjectConfiguration this.subscriptions.add( - Observable.fromEvent<[string, string]>(inMemoryFileSystem, 'add', Array.of) + Observable.fromEvent<[string, string]>(inMemoryFileSystem, 'add', pairOf) .filter(([uri, content]) => !!content && /\/[tj]sconfig\.json/.test(uri) && !uri.includes('/node_modules/')) .subscribe(([uri, content]) => { const filePath = uri2path(uri); @@ -241,7 +242,7 @@ export class ProjectManager implements Disposable { this.invalidateReferencedFiles(); }) .publishReplay() - .refCount(); + .refCount() as Observable; } return this.ensuredModuleStructure; }); @@ -272,7 +273,7 @@ export class ProjectManager implements Disposable { this.ensuredOwnFiles = undefined; }) .publishReplay() - .refCount(); + .refCount() as Observable; } return this.ensuredOwnFiles; }); @@ -293,7 +294,7 @@ export class ProjectManager implements Disposable { this.ensuredAllFiles = undefined; }) .publishReplay() - .refCount(); + .refCount() as Observable; } return this.ensuredAllFiles; }); diff --git a/src/util.ts b/src/util.ts index 619d33827..069602b5b 100644 --- a/src/util.ts +++ b/src/util.ts @@ -27,6 +27,13 @@ export function docstring(parts: ts.SymbolDisplayPart[]): string { return ts.displayPartsToString(parts); } +/** + * Typecasted version of Array.of producing arrays of two. + */ +export function pairOf(...args: T[]): [T, T] { + return Array.of(...args) as [T, T]; +} + /** * Normalizes path to match POSIX standard (slashes) * This conversion should only be necessary to convert windows paths when calling TS APIs. From 379d805f0036307d59e5298f67110c8f7a62cc21 Mon Sep 17 00:00:00 2001 From: Tom van Ommeren Date: Sat, 23 Sep 2017 17:22:49 +0200 Subject: [PATCH 09/13] fix: test with triple-slash references should use declaration files These files were not pre-loaded by ensure, so addSourceFile only added empty content. They were present in TS, but had no symbols. --- src/test/typescript-service-helpers.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/typescript-service-helpers.ts b/src/test/typescript-service-helpers.ts index 1c293b19d..474be7b4d 100644 --- a/src/test/typescript-service-helpers.ts +++ b/src/test/typescript-service-helpers.ts @@ -2759,9 +2759,9 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor beforeEach(initializeTypeScriptService(createService, rootUri, new Map([ [rootUri + 'keywords-in-path/class/constructor/a.ts', 'export function a() {}'], [rootUri + 'special-characters-in-path/%40foo/b.ts', 'export function b() {}'], - [rootUri + 'windows/app/master.ts', '/// \nc();'], - [rootUri + 'windows/lib/master.ts', '/// '], - [rootUri + 'windows/lib/slave.ts', 'function c() {}'] + [rootUri + 'windows/app/master.ts', '/// \nc();'], + [rootUri + 'windows/lib/master.d.ts', '/// '], + [rootUri + 'windows/lib/slave.d.ts', 'function c() {}'] ]))); afterEach(shutdownService); @@ -2820,7 +2820,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor ] }); }); - it('should handle Windows-style paths in triple slash references', async function (this: TestContext & ITestCallbackContext) { + it.only('should handle Windows-style paths in triple slash references', async function (this: TestContext & ITestCallbackContext) { const result = await this.service.textDocumentDefinition({ textDocument: { uri: rootUri + 'windows/app/master.ts' @@ -2841,7 +2841,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor character: 10 } }, - uri: rootUri + 'windows/lib/slave.ts' + uri: rootUri + 'windows/lib/slave.d.ts' }]); }); }); From 3c09ac7f8ea8cabd0ab092aa3140cda731b84c83 Mon Sep 17 00:00:00 2001 From: Tom van Ommeren Date: Sat, 23 Sep 2017 17:24:24 +0200 Subject: [PATCH 10/13] fix: remove accidentally committed test filter --- src/test/typescript-service-helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/typescript-service-helpers.ts b/src/test/typescript-service-helpers.ts index 474be7b4d..0cefd7781 100644 --- a/src/test/typescript-service-helpers.ts +++ b/src/test/typescript-service-helpers.ts @@ -2820,7 +2820,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor ] }); }); - it.only('should handle Windows-style paths in triple slash references', async function (this: TestContext & ITestCallbackContext) { + it('should handle Windows-style paths in triple slash references', async function (this: TestContext & ITestCallbackContext) { const result = await this.service.textDocumentDefinition({ textDocument: { uri: rootUri + 'windows/app/master.ts' From 65c815d713c4761f16fecc8ab89e3a8e2256643c Mon Sep 17 00:00:00 2001 From: Tom van Ommeren Date: Mon, 25 Sep 2017 19:52:15 +0200 Subject: [PATCH 11/13] fix: implement missing functions, revert ensureSourceFile hack compilerHost now assumes fileExists and readFile are implemented on LanguageServiceHost. --- src/project-manager.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/project-manager.ts b/src/project-manager.ts index 424598ece..13c821c6e 100644 --- a/src/project-manager.ts +++ b/src/project-manager.ts @@ -369,7 +369,6 @@ export class ProjectManager implements Disposable { const config = this.getConfiguration(referencingFilePath); config.ensureBasicFiles(span); const contents = this.inMemoryFs.getContent(uri); - config.ensureSourceFile(referencingFilePath, span); const info = ts.preProcessFile(contents, true, true); const compilerOpt = config.getHost().getCompilationSettings(); const pathResolver = referencingFilePath.includes('\\') ? path.win32 : path.posix; @@ -675,6 +674,13 @@ export class InMemoryLanguageServiceHost implements ts.LanguageServiceHost { this.logger.error(message); } + readFile(path: string, encoding?: string): string { + return this.fs.readFile(path); + } + + fileExists(path: string): boolean { + return this.fs.fileExists(path); + } } /** From 7ec6eb568e2c3fbfe18779c37bd2aceb5f673055 Mon Sep 17 00:00:00 2001 From: Tom van Ommeren Date: Mon, 25 Sep 2017 19:59:11 +0200 Subject: [PATCH 12/13] fix: revert unneeded fix to triple-slash tests --- src/test/typescript-service-helpers.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/typescript-service-helpers.ts b/src/test/typescript-service-helpers.ts index 0cefd7781..1c293b19d 100644 --- a/src/test/typescript-service-helpers.ts +++ b/src/test/typescript-service-helpers.ts @@ -2759,9 +2759,9 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor beforeEach(initializeTypeScriptService(createService, rootUri, new Map([ [rootUri + 'keywords-in-path/class/constructor/a.ts', 'export function a() {}'], [rootUri + 'special-characters-in-path/%40foo/b.ts', 'export function b() {}'], - [rootUri + 'windows/app/master.ts', '/// \nc();'], - [rootUri + 'windows/lib/master.d.ts', '/// '], - [rootUri + 'windows/lib/slave.d.ts', 'function c() {}'] + [rootUri + 'windows/app/master.ts', '/// \nc();'], + [rootUri + 'windows/lib/master.ts', '/// '], + [rootUri + 'windows/lib/slave.ts', 'function c() {}'] ]))); afterEach(shutdownService); @@ -2841,7 +2841,7 @@ export function describeTypeScriptService(createService: TypeScriptServiceFactor character: 10 } }, - uri: rootUri + 'windows/lib/slave.d.ts' + uri: rootUri + 'windows/lib/slave.ts' }]); }); }); From 832c560dc39178c5b0a4eeb1049ea6c4b372c991 Mon Sep 17 00:00:00 2001 From: Felix Becker Date: Tue, 26 Sep 2017 19:05:42 -0700 Subject: [PATCH 13/13] refactor: remove pairOf --- src/project-manager.ts | 4 ++-- src/util.ts | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/project-manager.ts b/src/project-manager.ts index 13c821c6e..ea29f9e9c 100644 --- a/src/project-manager.ts +++ b/src/project-manager.ts @@ -1,4 +1,5 @@ import { Observable, Subscription } from '@reactivex/rxjs'; +import { SelectorMethodSignature } from '@reactivex/rxjs/dist/cjs/observable/FromEventObservable'; import iterate from 'iterare'; import { noop } from 'lodash'; import { Span } from 'opentracing'; @@ -16,7 +17,6 @@ import { isJSTSFile, isPackageJsonFile, observableFromIterable, - pairOf, path2uri, toUnixPath, uri2path @@ -147,7 +147,7 @@ export class ProjectManager implements Disposable { // Whenever a file with content is added to the InMemoryFileSystem, check if it's a tsconfig.json and add a new ProjectConfiguration this.subscriptions.add( - Observable.fromEvent<[string, string]>(inMemoryFileSystem, 'add', pairOf) + Observable.fromEvent(inMemoryFileSystem, 'add', Array.of as SelectorMethodSignature<[string, string]>) .filter(([uri, content]) => !!content && /\/[tj]sconfig\.json/.test(uri) && !uri.includes('/node_modules/')) .subscribe(([uri, content]) => { const filePath = uri2path(uri); diff --git a/src/util.ts b/src/util.ts index 069602b5b..619d33827 100644 --- a/src/util.ts +++ b/src/util.ts @@ -27,13 +27,6 @@ export function docstring(parts: ts.SymbolDisplayPart[]): string { return ts.displayPartsToString(parts); } -/** - * Typecasted version of Array.of producing arrays of two. - */ -export function pairOf(...args: T[]): [T, T] { - return Array.of(...args) as [T, T]; -} - /** * Normalizes path to match POSIX standard (slashes) * This conversion should only be necessary to convert windows paths when calling TS APIs.