Merge branch 'master' into symbolInfoFormatting

This commit is contained in:
Sheetal Nandi 2014-10-08 19:00:26 -07:00
commit 279791e99e
5 changed files with 257 additions and 234 deletions

View file

@ -7134,6 +7134,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;
@ -7212,6 +7228,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

@ -1259,9 +1259,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 {
@ -1968,11 +1968,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 {
@ -2258,16 +2259,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);
@ -2608,7 +2613,11 @@ module ts {
var type = session.typeChecker.getTypeOfSymbol(symbol);
Debug.assert(type, "Could not find type for symbol");
var completionEntry = createCompletionEntry(symbol);
var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getSourceFile(filename), session.location, session.typeChecker, session.location);
// 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.
var displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, getSourceFile(filename), session.location, session.typeChecker, session.location, SemanticMeaning.All);
return {
name: entryName,
kind: displayPartsDocumentationsAndSymbolKind.symbolKind,
@ -2651,13 +2660,19 @@ 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;
}
var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags);
if (result === ScriptElementKind.unknown) {
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
@ -2730,7 +2745,10 @@ module ts {
: ScriptElementKindModifier.none;
}
function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node, typeResolver: TypeChecker, location: Node) {
function getSymbolDisplayPartsDocumentationAndSymbolKind(symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node,
typeResolver: TypeChecker, location: Node,
// TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location
semanticMeaning = getMeaningFromLocation(location)) {
var displayParts: SymbolDisplayPart[] = [];
var documentation: SymbolDisplayPart[];
var symbolFlags = typeResolver.getRootSymbol(symbol).flags;
@ -2841,7 +2859,7 @@ module ts {
displayParts.push.apply(displayParts, symbolToDisplayParts(typeResolver, symbol, sourceFile, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments));
writeTypeParametersOfSymbol(symbol, sourceFile);
}
if (symbolFlags & SymbolFlags.Interface) {
if ((symbolFlags & SymbolFlags.Interface) && (semanticMeaning & SemanticMeaning.Type)) {
addNewLineIfDisplayPartsExist();
displayParts.push(keywordPart(SyntaxKind.InterfaceKeyword));
displayParts.push(spacePart());
@ -2860,7 +2878,7 @@ module ts {
displayParts.push(spacePart());
displayParts.push.apply(displayParts, symbolToDisplayParts(typeResolver, symbol, sourceFile));
}
if (symbolFlags & SymbolFlags.TypeParameter) {
if ((symbolFlags & SymbolFlags.TypeParameter) && (semanticMeaning & SemanticMeaning.Type)) {
addNewLineIfDisplayPartsExist();
displayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
displayParts.push(textPart("type parameter"));
@ -2940,9 +2958,9 @@ module ts {
}
}
else {
symbolKind = getSymbolKind(symbol);
symbolKind = getSymbolKind(symbol, semanticMeaning);
}
}
}
if (!documentation) {
documentation = symbol.getDocumentationComment();
@ -3033,8 +3051,8 @@ module ts {
var displayPartsDocumentationsAndKind = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, sourceFile, getContainerNode(node), typeInfoResolver, node);
return {
kind: getSymbolKind(symbol),
kindModifiers: displayPartsDocumentationsAndKind.symbolKind,
kind: displayPartsDocumentationsAndKind.symbolKind,
kindModifiers: getSymbolModifiers(symbol),
textSpan: new TypeScript.TextSpan(node.getStart(), node.getWidth()),
displayParts: displayPartsDocumentationsAndKind.displayParts,
documentation: displayPartsDocumentationsAndKind.documentation
@ -3146,10 +3164,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)) {
@ -3854,7 +3871,7 @@ module ts {
searchSymbol: Symbol,
searchText: string,
searchLocation: Node,
searchMeaning: SearchMeaning,
searchMeaning: SemanticMeaning,
findInStrings: boolean,
findInComments: boolean,
result: ReferenceEntry[]): void {
@ -4153,114 +4170,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.
@ -4268,7 +4177,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]
@ -4478,6 +4387,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.
@ -4646,7 +4663,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) {
@ -4655,10 +4672,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;
}
@ -4666,6 +4680,9 @@ module ts {
return ClassificationTypeNames.typeParameterName;
}
}
else if (flags & SymbolFlags.Module) {
return ClassificationTypeNames.moduleName;
}
}
function processNode(node: Node) {
@ -4674,7 +4691,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()),
@ -5135,7 +5152,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),

View file

@ -42,7 +42,7 @@
//// /** c1_nc_l1*/
//// public nc_l1: () => void;
////}
////var i1/*1iq*/_i: i1;
////var i1/*1iq*/_i: /*16i*/i1;
////i1_i./*1*/i/*2q*/1_f1(/*2*/);
////i1_i.i1_n/*3q*/c_f1(/*3*/);
////i1_i.f/*4q*/1(/*4*/);
@ -179,7 +179,7 @@
//// nc_f1(): void;
//// nc_l1: () => void;
////}
////var i2/*36iq*/_i: i2;
////var i2/*36iq*/_i: /*51i*/i2;
////var i3/*37iq*/_i: i3;
////i2_i./*36*/i2/*37q*/_f1(/*37*/);
////i2_i.i2_n/*38q*/c_f1(/*38*/);
@ -370,6 +370,9 @@ verify.completionListContains("i1_i", "(var) i1_i: i1", "");
verify.completionListContains("c1", "class c1", "");
verify.completionListContains("c1_i", "(var) c1_i: c1", "");
goTo.marker('16i');
verify.completionListContains("i1", "interface i1", "i1 is interface with properties");
goTo.marker('17iq');
verify.quickInfoIs("(var) c2_i: c2", "");
goTo.marker('18iq');
@ -653,6 +656,10 @@ verify.completionListContains("i2_i", "(var) i2_i: i2", "");
verify.completionListContains("i3", "interface i3", "");
verify.completionListContains("i3_i", "(var) i3_i: i3", "");
goTo.marker('51i');
verify.completionListContains("i2", "interface i2", "");
verify.completionListContains("i3", "interface i3", "");
goTo.marker('52');
verify.quickInfoIs("(constructor) c5(): c5", "");

View file

@ -26,7 +26,7 @@
//// fnfoo(/**param help*/b: number): string;
//// nc_fnfoo(b: number): string;
////}
////var i2/*6*/_i: i2;
////var i2/*6*/_i: /*34i*/i2;
////var i2_i/*7*/_x = i2_i./*8*/x;
////var i2_i/*9*/_foo = i2_i.f/*10*/oo;
////var i2_i_f/*11*/oo_r = i2_i.f/*12q*/oo(/*12*/30);
@ -218,6 +218,11 @@ verify.completionListContains("i2_i_fnfoo_r", "(var) i2_i_fnfoo_r: string", "");
verify.completionListContains("i2_i_nc_fnfoo", "(var) i2_i_nc_fnfoo: (b: number) => string", "");
verify.completionListContains("i2_i_nc_fnfoo_r", "(var) i2_i_nc_fnfoo_r: string", "");
goTo.marker('34i');
verify.completionListContains("i1", "interface i1", "this is interface 1");
verify.completionListContains("nc_i1", "interface nc_i1", "");
verify.completionListContains("i2", "interface i2", "this is interface 2 with memebers");
goTo.marker('36');
verify.completionListContains("a", "(parameter) a: number", "i3_i a");