Merge pull request #859 from Microsoft/useProperMeaningAtLocation

Use proper meanings when requesting information about a node
This commit is contained in:
Daniel Rosenwasser
2014-10-08 17:59:29 -07:00
3 changed files with 245 additions and 237 deletions

View File

@@ -7143,6 +7143,22 @@ module ts {
return mapToArray(symbols);
}
function isTypeDeclarationName(name: Node): boolean {
return name.kind == SyntaxKind.Identifier &&
isTypeDeclaration(name.parent) &&
(<Declaration>name.parent).name === name;
}
function isTypeDeclaration(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.TypeParameter:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
return true;
}
}
// True if the given identifier is part of a type reference
function isTypeReferenceIdentifier(entityName: EntityName): boolean {
var node: Node = entityName;
@@ -7221,6 +7237,78 @@ module ts {
return false;
}
function isTypeNode(node: Node): boolean {
if (SyntaxKind.FirstTypeNode <= node.kind && node.kind <= SyntaxKind.LastTypeNode) {
return true;
}
switch (node.kind) {
case SyntaxKind.AnyKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.BooleanKeyword:
return true;
case SyntaxKind.VoidKeyword:
return node.parent.kind !== SyntaxKind.PrefixOperator;
case SyntaxKind.StringLiteral:
// Specialized signatures can have string literals as their parameters' type names
return node.parent.kind === SyntaxKind.Parameter;
// Identifiers and qualified names may be type nodes, depending on their context. Climb
// above them to find the lowest container
case SyntaxKind.Identifier:
// If the identifier is the RHS of a qualified name, then it's a type iff its parent is.
if (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
}
// fall through
case SyntaxKind.QualifiedName:
// At this point, node is either a qualified name or an identifier
Debug.assert(node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName, "'node' was expected to be a qualified name or identifier in 'isTypeNode'.");
var parent = node.parent;
if (parent.kind === SyntaxKind.TypeQuery) {
return false;
}
// Do not recursively call isTypeNode on the parent. In the example:
//
// var a: A.B.C;
//
// Calling isTypeNode would consider the qualified name A.B a type node. Only C or
// A.B.C is a type node.
if (SyntaxKind.FirstTypeNode <= parent.kind && parent.kind <= SyntaxKind.LastTypeNode) {
return true;
}
switch (parent.kind) {
case SyntaxKind.TypeParameter:
return node === (<TypeParameterDeclaration>parent).constraint;
case SyntaxKind.Property:
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
return node === (<VariableDeclaration>parent).type;
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.Constructor:
case SyntaxKind.Method:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return node === (<FunctionDeclaration>parent).type;
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
return node === (<SignatureDeclaration>parent).type;
case SyntaxKind.TypeAssertion:
return node === (<TypeAssertion>parent).type;
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
return (<CallExpression>parent).typeArguments && (<CallExpression>parent).typeArguments.indexOf(node) >= 0;
}
}
return false;
}
function isInRightSideOfImportOrExportAssignment(node: EntityName) {
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;

View File

@@ -391,100 +391,6 @@ module ts {
return false;
}
/**
* Note: this function only works when given a node with valid parent pointers.
*/
export function isTypeNode(node: Node): boolean {
if (node.kind >= SyntaxKind.FirstTypeNode && node.kind <= SyntaxKind.LastTypeNode) {
return true;
}
switch (node.kind) {
case SyntaxKind.AnyKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.BooleanKeyword:
return true;
case SyntaxKind.VoidKeyword:
return node.parent.kind !== SyntaxKind.PrefixOperator;
case SyntaxKind.StringLiteral:
// Specialized signatures can have string literals as their parameters' type names
return node.parent.kind === SyntaxKind.Parameter;
// Identifiers and qualified names may be type nodes, depending on their context. Climb
// above them to find the lowest container
case SyntaxKind.Identifier:
// If the identifier is the RHS of a qualified name, then it's a type iff its parent is.
if (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
}
// Fall through
case SyntaxKind.QualifiedName:
// At this point, node is either a qualified name or an identifier
var parent = node.parent;
if (parent.kind === SyntaxKind.TypeQuery) {
return false;
}
// Do not recursively call isTypeNode on the parent. In the example:
//
// var a: A.B.C;
//
// Calling isTypeNode would consider the qualified name A.B a type node. Only C or
// A.B.C is a type node.
if (parent.kind >= SyntaxKind.FirstTypeNode && parent.kind <= SyntaxKind.LastTypeNode) {
return true;
}
switch (parent.kind) {
case SyntaxKind.TypeParameter:
return node === (<TypeParameterDeclaration>parent).constraint;
case SyntaxKind.Property:
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
return node === (<VariableDeclaration>parent).type;
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.Constructor:
case SyntaxKind.Method:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return node === (<FunctionDeclaration>parent).type;
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
return node === (<SignatureDeclaration>parent).type;
case SyntaxKind.TypeAssertion:
return node === (<TypeAssertion>parent).type;
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
return (<CallExpression>parent).typeArguments && (<CallExpression>parent).typeArguments.indexOf(node) >= 0;
}
}
return false;
}
/**
* Note: this function only works when given a node with valid parent pointers.
*
* returns true if the given identifier is the name of a type declaration node (class, interface, enum, type parameter, etc)
*/
export function isTypeDeclarationName(name: Node): boolean {
return name.kind == SyntaxKind.Identifier &&
isTypeDeclaration(name.parent) &&
(<Declaration>name.parent).name === name;
}
export function isTypeDeclaration(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.TypeParameter:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
return true;
}
}
export function getContainingFunction(node: Node): SignatureDeclaration {
while (true) {
node = node.parent;

View File

@@ -1100,9 +1100,9 @@ module ts {
filename: string; // the file where the completion was requested
position: number; // position in the file where the completion was requested
entries: CompletionEntry[]; // entries for this completion
symbols: Map<Symbol>; // symbols by entry name map
location: Node; // the node where the completion was requested
typeChecker: TypeChecker;// the typeChecker used to generate this completion
symbols: Map<Symbol>; // symbols by entry name map
location: Node; // the node where the completion was requested
typeChecker: TypeChecker; // the typeChecker used to generate this completion
}
interface FormattingOptions {
@@ -1639,11 +1639,12 @@ module ts {
(node.parent.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node.parent).externalModuleName === node));
}
enum SearchMeaning {
enum SemanticMeaning {
None = 0x0,
Value = 0x1,
Type = 0x2,
Namespace = 0x4
Namespace = 0x4,
All = Value | Type | Namespace
}
enum BreakContinueSearchType {
@@ -1934,16 +1935,20 @@ module ts {
return undefined;
}
// TODO(drosen): Right now we just permit *all* semantic meanings when calling 'getSymbolKind'
// which is permissible given that it is backwards compatible; but really we should consider
// passing the meaning for the node so that we don't report that a suggestion for a value is an interface.
// We COULD also just do what 'getSymbolModifiers' does, which is to use the first declaration.
return {
name: displayName,
kind: getSymbolKind(symbol),
kind: getSymbolKind(symbol, SemanticMeaning.All),
kindModifiers: getSymbolModifiers(symbol)
};
}
function getCompletionsAtPosition(filename: string, position: number, isMemberCompletion: boolean) {
function getCompletionEntriesFromSymbols(symbols: Symbol[], session: CompletionSession): void {
forEach(symbols, (symbol) => {
forEach(symbols, symbol => {
var entry = createCompletionEntry(symbol);
if (entry && !lookUp(session.symbols, entry.name)) {
session.entries.push(entry);
@@ -2328,13 +2333,20 @@ module ts {
}
}
function getSymbolKind(symbol: Symbol): string {
function getSymbolKind(symbol: Symbol, meaningAtLocation: SemanticMeaning): string {
var flags = typeInfoResolver.getRootSymbol(symbol).getFlags();
if (flags & SymbolFlags.Module) return ScriptElementKind.moduleElement;
if (flags & SymbolFlags.Class) return ScriptElementKind.classElement;
if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
if (flags & SymbolFlags.Enum) return ScriptElementKind.enumElement;
// The following should only apply if encountered at a type position,
// and need to have precedence over other meanings if this is the case.
if (meaningAtLocation & SemanticMeaning.Type) {
if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
}
if (flags & SymbolFlags.Module) return ScriptElementKind.moduleElement;
if (flags & SymbolFlags.Variable) return ScriptElementKind.variableElement;
if (flags & SymbolFlags.Function) return ScriptElementKind.functionElement;
if (flags & SymbolFlags.GetAccessor) return ScriptElementKind.memberGetAccessorElement;
@@ -2345,7 +2357,6 @@ module ts {
if (flags & SymbolFlags.ConstructSignature) return ScriptElementKind.constructSignatureElement;
if (flags & SymbolFlags.CallSignature) return ScriptElementKind.callSignatureElement;
if (flags & SymbolFlags.Constructor) return ScriptElementKind.constructorImplementationElement;
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement;
if (flags & SymbolFlags.Import) return ScriptElementKind.alias;
@@ -2404,6 +2415,8 @@ module ts {
return undefined;
}
var semanticMeaning = getMeaningFromLocation(node);
var symbol = typeInfoResolver.getSymbolInfo(node);
if (!symbol) {
return undefined;
@@ -2420,11 +2433,6 @@ module ts {
totalParts.push(spacePart());
totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol, sourceFile));
}
else if (symbol.flags & SymbolFlags.Interface) {
totalParts.push(keywordPart(SyntaxKind.InterfaceKeyword));
totalParts.push(spacePart());
totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol, sourceFile));
}
else if (symbol.flags & SymbolFlags.Enum) {
totalParts.push(keywordPart(SyntaxKind.EnumKeyword));
totalParts.push(spacePart());
@@ -2435,12 +2443,19 @@ module ts {
totalParts.push(spacePart());
totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol, sourceFile));
}
else if (symbol.flags & SymbolFlags.TypeParameter) {
totalParts.push(punctuationPart(SyntaxKind.OpenParenToken));
totalParts.push(new SymbolDisplayPart("type parameter", SymbolDisplayPartKind.text, undefined));
totalParts.push(punctuationPart(SyntaxKind.CloseParenToken));
totalParts.push(spacePart());
totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol));
else if (semanticMeaning & SemanticMeaning.Type) {
if (symbol.flags & SymbolFlags.Interface) {
totalParts.push(keywordPart(SyntaxKind.InterfaceKeyword));
totalParts.push(spacePart());
totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol, sourceFile));
}
else if (symbol.flags & SymbolFlags.TypeParameter) {
totalParts.push(punctuationPart(SyntaxKind.OpenParenToken));
totalParts.push(new SymbolDisplayPart("type parameter", SymbolDisplayPartKind.text, undefined));
totalParts.push(punctuationPart(SyntaxKind.CloseParenToken));
totalParts.push(spacePart());
totalParts.push.apply(totalParts, typeInfoResolver.symbolToDisplayParts(symbol));
}
}
else {
totalParts.push(punctuationPart(SyntaxKind.OpenParenToken));
@@ -2494,7 +2509,7 @@ module ts {
}
return {
kind: getSymbolKind(symbol),
kind: getSymbolKind(symbol, semanticMeaning),
kindModifiers: getSymbolModifiers(symbol),
textSpan: new TypeScript.TextSpan(node.getStart(), node.getWidth()),
displayParts: totalParts,
@@ -2519,7 +2534,7 @@ module ts {
memberName: new TypeScript.MemberNameString(typeInfoResolver.typeToString(type)),
docComment: "",
fullSymbolName: typeInfoResolver.symbolToString(symbol, getContainerNode(node)),
kind: getSymbolKind(symbol),
kind: getSymbolKind(symbol, SemanticMeaning.Type),
textSpan: TypeScript.TextSpan.fromBounds(node.pos, node.end)
};
}
@@ -2632,10 +2647,9 @@ module ts {
var declarations = symbol.getDeclarations();
var symbolName = typeInfoResolver.symbolToString(symbol); // Do not get scoped name, just the name of the symbol
var symbolKind = getSymbolKind(symbol);
var symbolKind = getSymbolKind(symbol, getMeaningFromLocation(node));
var containerSymbol = symbol.parent;
var containerName = containerSymbol ? typeInfoResolver.symbolToString(containerSymbol, node) : "";
var containerKind = containerSymbol ? getSymbolKind(symbol) : "";
if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) &&
!tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) {
@@ -3340,7 +3354,7 @@ module ts {
searchSymbol: Symbol,
searchText: string,
searchLocation: Node,
searchMeaning: SearchMeaning,
searchMeaning: SemanticMeaning,
findInStrings: boolean,
findInComments: boolean,
result: ReferenceEntry[]): void {
@@ -3639,114 +3653,6 @@ module ts {
return undefined;
}
function getMeaningFromDeclaration(node: Declaration): SearchMeaning {
switch (node.kind) {
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Property:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.EnumMember:
case SyntaxKind.Method:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.CatchBlock:
return SearchMeaning.Value;
case SyntaxKind.TypeParameter:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeLiteral:
return SearchMeaning.Type;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.EnumDeclaration:
return SearchMeaning.Value | SearchMeaning.Type;
case SyntaxKind.ModuleDeclaration:
if ((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral) {
return SearchMeaning.Namespace | SearchMeaning.Value;
}
else if (isInstantiated(node)) {
return SearchMeaning.Namespace | SearchMeaning.Value;
}
else {
return SearchMeaning.Namespace;
}
break;
case SyntaxKind.ImportDeclaration:
return SearchMeaning.Value | SearchMeaning.Type | SearchMeaning.Namespace;
}
Debug.fail("Unknown declaration type");
}
function isTypeReference(node: Node): boolean {
if (node.parent.kind === SyntaxKind.QualifiedName && (<QualifiedName>node.parent).right === node)
node = node.parent;
return node.parent.kind === SyntaxKind.TypeReference;
}
function isNamespaceReference(node: Node): boolean {
var root = node;
var isLastClause = true;
if (root.parent.kind === SyntaxKind.QualifiedName) {
while (root.parent && root.parent.kind === SyntaxKind.QualifiedName)
root = root.parent;
isLastClause = (<QualifiedName>root).right === node;
}
return root.parent.kind === SyntaxKind.TypeReference && !isLastClause;
}
function isInRightSideOfImport(node: EntityName) {
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
}
return node.parent.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node.parent).entityName === node;
}
function getMeaningFromRightHandSideOfImport(node: Node) {
Debug.assert(node.kind === SyntaxKind.Identifier);
// import a = |b|; // Namespace
// import a = |b.c|; // Value, type, namespace
// import a = |b.c|.d; // Namespace
if (node.parent.kind === SyntaxKind.QualifiedName &&
(<QualifiedName>node.parent).right === node &&
node.parent.parent.kind === SyntaxKind.ImportDeclaration) {
return SearchMeaning.Value | SearchMeaning.Type | SearchMeaning.Namespace;
}
return SearchMeaning.Namespace;
}
function getMeaningFromLocation(node: Node): SearchMeaning {
if (node.parent.kind === SyntaxKind.ExportAssignment) {
return SearchMeaning.Value | SearchMeaning.Type | SearchMeaning.Namespace;
}
else if (isInRightSideOfImport(node)) {
return getMeaningFromRightHandSideOfImport(node);
}
else if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) {
return getMeaningFromDeclaration(node.parent);
}
else if (isTypeReference(node)) {
return SearchMeaning.Type;
}
else if (isNamespaceReference(node)) {
return SearchMeaning.Namespace;
}
else {
return SearchMeaning.Value;
}
}
/** Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations
* of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class
* then we need to widen the search to include type positions as well.
@@ -3754,7 +3660,7 @@ module ts {
* module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module)
* do not intersect in any of the three spaces.
*/
function getIntersectingMeaningFromDeclarations(meaning: SearchMeaning, declarations: Declaration[]): SearchMeaning {
function getIntersectingMeaningFromDeclarations(meaning: SemanticMeaning, declarations: Declaration[]): SemanticMeaning {
if (declarations) {
do {
// The result is order-sensitive, for instance if initialMeaning === Namespace, and declarations = [class, instantiated module]
@@ -3964,6 +3870,114 @@ module ts {
return emitOutput;
}
function getMeaningFromDeclaration(node: Declaration): SemanticMeaning {
switch (node.kind) {
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Property:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.EnumMember:
case SyntaxKind.Method:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.CatchBlock:
return SemanticMeaning.Value;
case SyntaxKind.TypeParameter:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeLiteral:
return SemanticMeaning.Type;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.EnumDeclaration:
return SemanticMeaning.Value | SemanticMeaning.Type;
case SyntaxKind.ModuleDeclaration:
if ((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral) {
return SemanticMeaning.Namespace | SemanticMeaning.Value;
}
else if (isInstantiated(node)) {
return SemanticMeaning.Namespace | SemanticMeaning.Value;
}
else {
return SemanticMeaning.Namespace;
}
break;
case SyntaxKind.ImportDeclaration:
return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace;
}
Debug.fail("Unknown declaration type");
}
function isTypeReference(node: Node): boolean {
if (node.parent.kind === SyntaxKind.QualifiedName && (<QualifiedName>node.parent).right === node)
node = node.parent;
return node.parent.kind === SyntaxKind.TypeReference;
}
function isNamespaceReference(node: Node): boolean {
var root = node;
var isLastClause = true;
if (root.parent.kind === SyntaxKind.QualifiedName) {
while (root.parent && root.parent.kind === SyntaxKind.QualifiedName)
root = root.parent;
isLastClause = (<QualifiedName>root).right === node;
}
return root.parent.kind === SyntaxKind.TypeReference && !isLastClause;
}
function isInRightSideOfImport(node: EntityName) {
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
}
return node.parent.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node.parent).entityName === node;
}
function getMeaningFromRightHandSideOfImport(node: Node) {
Debug.assert(node.kind === SyntaxKind.Identifier);
// import a = |b|; // Namespace
// import a = |b.c|; // Value, type, namespace
// import a = |b.c|.d; // Namespace
if (node.parent.kind === SyntaxKind.QualifiedName &&
(<QualifiedName>node.parent).right === node &&
node.parent.parent.kind === SyntaxKind.ImportDeclaration) {
return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace;
}
return SemanticMeaning.Namespace;
}
function getMeaningFromLocation(node: Node): SemanticMeaning {
if (node.parent.kind === SyntaxKind.ExportAssignment) {
return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace;
}
else if (isInRightSideOfImport(node)) {
return getMeaningFromRightHandSideOfImport(node);
}
else if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) {
return getMeaningFromDeclaration(node.parent);
}
else if (isTypeReference(node)) {
return SemanticMeaning.Type;
}
else if (isNamespaceReference(node)) {
return SemanticMeaning.Namespace;
}
else {
return SemanticMeaning.Value;
}
}
// Signature help
/**
* This is a semantic operation.
@@ -4132,7 +4146,7 @@ module ts {
return result;
function classifySymbol(symbol: Symbol, isInTypePosition: boolean) {
function classifySymbol(symbol: Symbol, meaningAtPosition: SemanticMeaning) {
var flags = symbol.getFlags();
if (flags & SymbolFlags.Class) {
@@ -4141,10 +4155,7 @@ module ts {
else if (flags & SymbolFlags.Enum) {
return ClassificationTypeNames.enumName;
}
else if (flags & SymbolFlags.Module) {
return ClassificationTypeNames.moduleName;
}
else if (isInTypePosition) {
else if (meaningAtPosition & SemanticMeaning.Type) {
if (flags & SymbolFlags.Interface) {
return ClassificationTypeNames.interfaceName;
}
@@ -4152,6 +4163,9 @@ module ts {
return ClassificationTypeNames.typeParameterName;
}
}
else if (flags & SymbolFlags.Module) {
return ClassificationTypeNames.moduleName;
}
}
function processNode(node: Node) {
@@ -4160,7 +4174,7 @@ module ts {
if (node.kind === SyntaxKind.Identifier && node.getWidth() > 0) {
var symbol = typeInfoResolver.getSymbolInfo(node);
if (symbol) {
var type = classifySymbol(symbol, isTypeNode(node) || isTypeDeclarationName(node));
var type = classifySymbol(symbol, getMeaningFromLocation(node));
if (type) {
result.push({
textSpan: new TypeScript.TextSpan(node.getStart(), node.getWidth()),
@@ -4621,7 +4635,7 @@ module ts {
// Only allow a symbol to be renamed if it actually has at least one declaration.
if (symbol && symbol.getDeclarations() && symbol.getDeclarations().length > 0) {
var kind = getSymbolKind(symbol);
var kind = getSymbolKind(symbol, getMeaningFromLocation(node));
if (kind) {
return getRenameInfo(symbol.name, typeInfoResolver.getFullyQualifiedName(symbol), kind,
getSymbolModifiers(symbol),