From 9eef4b8f4777196e49402d060a065c32168f08a9 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 26 Aug 2015 15:48:49 -0700 Subject: [PATCH 1/2] Added tests. --- ...ToDefinitionConstructorOfClassExpression01.ts | 11 +++++++++++ ...torOfClassWhenClassIsPrecededByNamespace01.ts | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 tests/cases/fourslash/goToDefinitionConstructorOfClassExpression01.ts create mode 100644 tests/cases/fourslash/goToDefinitionConstructorOfClassWhenClassIsPrecededByNamespace01.ts diff --git a/tests/cases/fourslash/goToDefinitionConstructorOfClassExpression01.ts b/tests/cases/fourslash/goToDefinitionConstructorOfClassExpression01.ts new file mode 100644 index 00000000000..aa96400a397 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionConstructorOfClassExpression01.ts @@ -0,0 +1,11 @@ +/// + +////var x = class C { +//// /*definition*/constructor() { +//// var other = new /*usage*/C; +//// } +////} + +goTo.marker("usage"); +goTo.definition(); +verify.caretAtMarker("definition"); \ No newline at end of file diff --git a/tests/cases/fourslash/goToDefinitionConstructorOfClassWhenClassIsPrecededByNamespace01.ts b/tests/cases/fourslash/goToDefinitionConstructorOfClassWhenClassIsPrecededByNamespace01.ts new file mode 100644 index 00000000000..dc5c362772c --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionConstructorOfClassWhenClassIsPrecededByNamespace01.ts @@ -0,0 +1,16 @@ +/// + +////namespace Foo { +//// export var x; +////} +//// +////class Foo { +//// /*definition*/constructor() { +//// } +////} +//// +////var x = new /*usage*/Foo(); + +goTo.marker("usage"); +goTo.definition(); +verify.caretAtMarker("definition"); \ No newline at end of file From 9f3c99e392fde4cfbf19bdd70fe6fdfc45016a1c Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 26 Aug 2015 16:19:55 -0700 Subject: [PATCH 2/2] Don't assume the class declaration will occur first, and that it is *only* a class declaration. --- src/compiler/utilities.ts | 4 ++-- src/services/services.ts | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index ac559645bb5..99ea06532a0 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -611,11 +611,11 @@ namespace ts { return false; } - export function isAccessor(node: Node): boolean { + export function isAccessor(node: Node): node is AccessorDeclaration { return node && (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor); } - export function isClassLike(node: Node): boolean { + export function isClassLike(node: Node): node is ClassLikeDeclaration { return node && (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression); } diff --git a/src/services/services.ts b/src/services/services.ts index 92b62458f64..4358c9d58a9 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -4480,10 +4480,19 @@ namespace ts { // and in either case the symbol has a construct signature definition, i.e. class if (isNewExpressionTarget(location) || location.kind === SyntaxKind.ConstructorKeyword) { if (symbol.flags & SymbolFlags.Class) { - let classDeclaration = symbol.getDeclarations()[0]; - Debug.assert(classDeclaration && classDeclaration.kind === SyntaxKind.ClassDeclaration); + // Find the first class-like declaration and try to get the construct signature. + for (let declaration of symbol.getDeclarations()) { + if (isClassLike(declaration)) { + return tryAddSignature(declaration.members, + /*selectConstructors*/ true, + symbolKind, + symbolName, + containerName, + result); + } + } - return tryAddSignature(classDeclaration.members, /*selectConstructors*/ true, symbolKind, symbolName, containerName, result); + Debug.fail("Expected declaration to have at least one class-like declaration"); } } return false;