diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 60381824125..faac9105e29 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -92,7 +92,7 @@ module ts { getReturnTypeOfSignature: getReturnTypeOfSignature, resolveEntityName: resolveEntityName, getSymbolsInScope: getSymbolsInScope, - getSymbolOfIdentifier: getSymbolOfIdentifier, + getSymbolOfIdentifierLikeNode: getSymbolOfIdentifierLikeNode, getTypeOfExpression: getTypeOfExpression, typeToString: typeToString, symbolToString: symbolToString, @@ -6311,8 +6311,49 @@ module ts { meaning |= SymbolFlags.Import; return resolveEntityName(entityName, entityName, meaning); } + } - Debug.fail("identifier is neither at a type nor value position"); + function getSymbolOfIdentifierLikeNode(node: Node) { + switch (node.kind) { + case SyntaxKind.Identifier: + return getSymbolOfIdentifier(node); + break; + + case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: + var type = checkExpression(node); + return type.symbol; + + case SyntaxKind.ConstructorKeyword: + // constructor keyword for an overload, should take us to the definition if it exist + var constructorDeclaration = node.parent; + if (constructorDeclaration && constructorDeclaration.kind === SyntaxKind.Constructor) { + return (constructorDeclaration.parent).symbol; + } + return undefined; + + case SyntaxKind.StringLiteral: + // Property access + if (node.parent.kind === SyntaxKind.IndexedAccess && (node.parent).index === node) { + var objectType = checkExpression((node.parent).object); + if (objectType === unknownType) return undefined; + var apparentType = getApparentType(objectType); + if (apparentType === unknownType) return undefined; + return getPropertyOfApparentType(apparentType, (node).text); + } + // External module name in an import declaration + else if (node.parent.kind === SyntaxKind.ImportDeclaration && (node.parent).externalModuleName === node) { + var importSymbol = getSymbolOfNode(node.parent); + var moduleType = getTypeOfSymbol(importSymbol); + return moduleType ? moduleType.symbol : undefined; + } + // External module name in an ambient declaration + else if (node.parent.kind === SyntaxKind.ModuleDeclaration) { + return getSymbolOfNode(node.parent); + } + break; + } + return undefined; } function getTypeOfExpression(node: Node) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 73a758f53e5..706641df801 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -599,7 +599,7 @@ module ts { getReturnTypeOfSignature(signature: Signature): Type; resolveEntityName(location: Node, name: EntityName, meaning: SymbolFlags): Symbol; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; - getSymbolOfIdentifier(identifier: Identifier): Symbol; + getSymbolOfIdentifierLikeNode(node: Node): Symbol; getTypeOfExpression(node: Expression, contextualType?: Type, contextualMapper?: TypeMapper): Type; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string; diff --git a/src/services/services.ts b/src/services/services.ts index fdb570017fe..095d7f7631f 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1847,43 +1847,20 @@ module ts { var node = getNodeAtPosition(document.getSourceFile(), position); if (!node) return undefined; - switch (node.kind) { - // A declaration - case SyntaxKind.Identifier: - if (node.parent.kind === SyntaxKind.CallExpression || node.parent.kind === SyntaxKind.NewExpression) { - // TODO: handle new and call expressions - } - - var symbol = typeChecker.getSymbolOfIdentifier(node); - Debug.assert(symbol, "getTypeAtPosition: Could not find symbol for node"); - var type = typeChecker.getTypeOfSymbol(symbol); - - return { - memberName: new TypeScript.MemberNameString(typeChecker.typeToString(type)), - docComment: "", - fullSymbolName: typeChecker.symbolToString(symbol, getContainerNode(node)), - kind: getSymbolKind(symbol), - minChar: node.pos, - limChar: node.end - }; - - // An Expression - case SyntaxKind.ThisKeyword: - case SyntaxKind.QualifiedName: - case SyntaxKind.SuperKeyword: - case SyntaxKind.StringLiteral: - var type = typeChecker.getTypeOfExpression(node); - Debug.assert(type, "getTypeAtPosition: Could not find type for node"); - return { - memberName: new TypeScript.MemberNameString(""), - docComment: "", - fullSymbolName: typeChecker.typeToString(type, getContainerNode(node)), - kind: getTypeKind(type), - minChar: node.pos, - limChar: node.end - }; - break; + var symbol = typeChecker.getSymbolOfIdentifierLikeNode(node); + var type = symbol && typeChecker.getTypeOfSymbol(symbol); + if (type) { + return { + memberName: new TypeScript.MemberNameString(typeChecker.typeToString(type)), + docComment: "", + fullSymbolName: typeChecker.symbolToString(symbol, getContainerNode(node)), + kind: getSymbolKind(symbol), + minChar: node.pos, + limChar: node.end + }; } + + return undefined; } /// Goto definition @@ -2038,46 +2015,7 @@ module ts { return undefined; } - var symbol: Symbol; - - switch (node.kind) { - case SyntaxKind.Identifier: - symbol = typeChecker.getSymbolOfIdentifier(node); - break; - - case SyntaxKind.ThisKeyword: - case SyntaxKind.SuperKeyword: - var type = typeChecker.getTypeOfExpression(node); - symbol = type.getSymbol(); - break; - - case SyntaxKind.ConstructorKeyword: - // constructor keyword for an overload, should take us to the definition if it exist - var container = getContainerNode(node); - if (container && container.kind === SyntaxKind.ClassDeclaration) { - symbol = (container).symbol; - } - break; - - case SyntaxKind.StringLiteral: - // Property access - if (node.parent.kind === SyntaxKind.IndexedAccess && (node.parent).index === node) { - var objectType = typeChecker.getTypeOfExpression((node.parent).object); - Debug.assert(objectType); - symbol = objectType.getProperty((node).text); - } - // External module name in an import declaration - else if (node.parent.kind === SyntaxKind.ImportDeclaration && (node.parent).externalModuleName === node) { - var importSymbol = typeChecker.getSymbolOfNode(node.parent); - var moduleType = typeChecker.getTypeOfSymbol(importSymbol); - symbol = moduleType ? moduleType.symbol : undefined; - } - // External module name in an ambient declaration - else if (node.parent.kind === SyntaxKind.ModuleDeclaration) { - symbol = typeChecker.getSymbolOfNode(node.parent); - } - break; - } + var symbol = typeChecker.getSymbolOfIdentifierLikeNode(node); // Could not find a symbol e.g. node is string or number keyword, // or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol