From 1939c7f2cd210347281e0351892f341649598148 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 3 Dec 2014 14:47:13 -0800 Subject: [PATCH] Fix the getSymbolInfo and getTypeOfNode entry points to resolve the context sensitive information before resolving the actual node --- src/compiler/checker.ts | 29 ++++++++++++++----- src/compiler/types.ts | 4 +-- src/harness/typeWriter.ts | 2 +- src/services/services.ts | 22 +++++++------- src/services/signatureHelp.ts | 2 +- .../memberListOfVarInArrowExpression.ts | 18 ++++++++++++ 6 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 tests/cases/fourslash/memberListOfVarInArrowExpression.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 63ea9f1ae2b..056d4895e8c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -93,9 +93,9 @@ module ts { getIndexTypeOfType, getReturnTypeOfSignature, getSymbolsInScope, - getSymbolInfo, + getSymbolInfoOfLocation, getShorthandAssignmentValueSymbol, - getTypeOfNode, + getTypeOfLocation, typeToString, getSymbolDisplayBuilder, symbolToString, @@ -4385,18 +4385,33 @@ module ts { } } - function getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type { + function resolveLocation(node: Node) { + // Resolve location from top down towards node if it is a context sensitive expression + // That helps in making sure not assigning types as any when resolved out of order var containerNodes: Node[] = []; for (var parent = node.parent; parent; parent = parent.parent) { - if (isExpression(parent) && isContextSensitiveExpression(parent)) { - containerNodes.unshift(parent) - }; + if (isExpression(parent) && isContextSensitiveExpression(parent)) { + containerNodes.unshift(parent); + } } ts.forEach(containerNodes, node => { getTypeOfNode(node); }); + } + function getSymbolInfoOfLocation(node: Node): Symbol { + resolveLocation(node); + return getSymbolInfo(node); + } + + function getTypeOfLocation(node: Node): Type { + resolveLocation(node); + return getTypeOfNode(node); + } + + function getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type { + resolveLocation(node); return getNarrowedTypeOfSymbol(symbol, node); - } + } // Get the narrowed type of a given symbol at a given location function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 261a6fbfa31..befd9c9def4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -891,9 +891,9 @@ module ts { getIndexTypeOfType(type: Type, kind: IndexKind): Type; getReturnTypeOfSignature(signature: Signature): Type; getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; - getSymbolInfo(node: Node): Symbol; + getSymbolInfoOfLocation(node: Node): Symbol; getShorthandAssignmentValueSymbol(location: Node): Symbol; - getTypeOfNode(node: Node): Type; + getTypeOfLocation(node: Node): Type; typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string; symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string; getSymbolDisplayBuilder(): SymbolDisplayBuilder; diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index 83aaaaf920a..11d2e62e10a 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -94,7 +94,7 @@ class TypeWriterWalker { } private getTypeOfNode(node: ts.Node): ts.Type { - var type = this.checker.getTypeOfNode(node); + var type = this.checker.getTypeOfLocation(node); ts.Debug.assert(type !== undefined, "type doesn't exist"); return type; } diff --git a/src/services/services.ts b/src/services/services.ts index e7c964fb7e3..08f3d1fa11d 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2428,7 +2428,7 @@ module ts { isMemberCompletion = true; if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName || node.kind === SyntaxKind.PropertyAccessExpression) { - var symbol = typeInfoResolver.getSymbolInfo(node); + var symbol = typeInfoResolver.getSymbolInfoOfLocation(node); // This is an alias, follow what it aliases if (symbol && symbol.flags & SymbolFlags.Import) { @@ -2445,7 +2445,7 @@ module ts { } } - var type = typeInfoResolver.getTypeOfNode(node); + var type = typeInfoResolver.getTypeOfLocation(node); if (type) { // Filter private properties forEach(type.getApparentProperties(), symbol => { @@ -3089,7 +3089,7 @@ module ts { displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); } else { - var internalAliasSymbol = typeResolver.getSymbolInfo(importDeclaration.moduleReference); + var internalAliasSymbol = typeResolver.getSymbolInfoOfLocation(importDeclaration.moduleReference); if (internalAliasSymbol) { displayParts.push(spacePart()); displayParts.push(operatorPart(SyntaxKind.EqualsToken)); @@ -3199,7 +3199,7 @@ module ts { return undefined; } - var symbol = typeInfoResolver.getSymbolInfo(node); + var symbol = typeInfoResolver.getSymbolInfoOfLocation(node); if (!symbol) { // Try getting just type at this position and show switch (node.kind) { @@ -3209,7 +3209,7 @@ module ts { case SyntaxKind.ThisKeyword: case SyntaxKind.SuperKeyword: // For the identifiers/this/super etc get the type at position - var type = typeInfoResolver.getTypeOfNode(node); + var type = typeInfoResolver.getTypeOfLocation(node); if (type) { return { kind: ScriptElementKind.unknown, @@ -3326,7 +3326,7 @@ module ts { return undefined; } - var symbol = typeInfoResolver.getSymbolInfo(node); + var symbol = typeInfoResolver.getSymbolInfoOfLocation(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 @@ -3958,7 +3958,7 @@ module ts { return getReferencesForSuperKeyword(node); } - var symbol = typeInfoResolver.getSymbolInfo(node); + var symbol = typeInfoResolver.getSymbolInfoOfLocation(node); // Could not find a symbol e.g. unknown identifier if (!symbol) { @@ -4210,7 +4210,7 @@ module ts { return; } - var referenceSymbol = typeInfoResolver.getSymbolInfo(referenceLocation); + var referenceSymbol = typeInfoResolver.getSymbolInfoOfLocation(referenceLocation); if (referenceSymbol) { var referenceSymbolDeclaration = referenceSymbol.valueDeclaration; var shorthandValueSymbol = typeInfoResolver.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration); @@ -4443,7 +4443,7 @@ module ts { function getPropertySymbolFromTypeReference(typeReference: TypeReferenceNode) { if (typeReference) { - var type = typeInfoResolver.getTypeOfNode(typeReference); + var type = typeInfoResolver.getTypeOfLocation(typeReference); if (type) { var propertySymbol = typeInfoResolver.getPropertyOfType(type, propertyName); if (propertySymbol) { @@ -4967,7 +4967,7 @@ module ts { // Only walk into nodes that intersect the requested span. if (node && span.intersectsWith(node.getStart(), node.getWidth())) { if (node.kind === SyntaxKind.Identifier && node.getWidth() > 0) { - var symbol = typeInfoResolver.getSymbolInfo(node); + var symbol = typeInfoResolver.getSymbolInfoOfLocation(node); if (symbol) { var type = classifySymbol(symbol, getMeaningFromLocation(node)); if (type) { @@ -5396,7 +5396,7 @@ module ts { // Can only rename an identifier. if (node && node.kind === SyntaxKind.Identifier) { - var symbol = typeInfoResolver.getSymbolInfo(node); + var symbol = typeInfoResolver.getSymbolInfoOfLocation(node); // Only allow a symbol to be renamed if it actually has at least one declaration. if (symbol && symbol.getDeclarations() && symbol.getDeclarations().length > 0) { diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 93363b4676b..a8e0ce185f6 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -457,7 +457,7 @@ module ts.SignatureHelp { var invocation = argumentListInfo.invocation; var callTarget = getInvokedExpression(invocation) - var callTargetSymbol = typeInfoResolver.getSymbolInfo(callTarget); + var callTargetSymbol = typeInfoResolver.getSymbolInfoOfLocation(callTarget); var callTargetDisplayParts = callTargetSymbol && symbolToDisplayParts(typeInfoResolver, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined); var items: SignatureHelpItem[] = map(candidates, candidateSignature => { var signatureHelpParameters: SignatureHelpParameter[]; diff --git a/tests/cases/fourslash/memberListOfVarInArrowExpression.ts b/tests/cases/fourslash/memberListOfVarInArrowExpression.ts new file mode 100644 index 00000000000..03da06989ae --- /dev/null +++ b/tests/cases/fourslash/memberListOfVarInArrowExpression.ts @@ -0,0 +1,18 @@ +/// + +////interface IMap { +//// [key: string]: T; +////} +////var map: IMap<{ a1: string; }[]>; +////var categories: string[]; +////each(categories, category => { +//// var changes = map[category]; +//// changes[0]./*1*/a1; +//// return each(changes, change => { +//// }); +////}); +////function each(items: T[], handler: (item: T) => void) { } + +goTo.marker('1'); +verify.quickInfoIs("(property) a1: string"); +verify.memberListContains("a1", "(property) a1: string"); \ No newline at end of file