Skip to content

Commit 0434fe7

Browse files
author
Andy
authored
Get quickInfo from a contextual type if possible (#18119)
1 parent 8c714c3 commit 0434fe7

File tree

6 files changed

+56
-28
lines changed

6 files changed

+56
-28
lines changed

src/compiler/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,13 +744,15 @@ namespace ts {
744744
;
745745

746746
export interface PropertyAssignment extends ObjectLiteralElement {
747+
parent: ObjectLiteralExpression;
747748
kind: SyntaxKind.PropertyAssignment;
748749
name: PropertyName;
749750
questionToken?: QuestionToken;
750751
initializer: Expression;
751752
}
752753

753754
export interface ShorthandPropertyAssignment extends ObjectLiteralElement {
755+
parent: ObjectLiteralExpression;
754756
kind: SyntaxKind.ShorthandPropertyAssignment;
755757
name: Identifier;
756758
questionToken?: QuestionToken;
@@ -761,6 +763,7 @@ namespace ts {
761763
}
762764

763765
export interface SpreadAssignment extends ObjectLiteralElement {
766+
parent: ObjectLiteralExpression;
764767
kind: SyntaxKind.SpreadAssignment;
765768
expression: Expression;
766769
}

src/services/services.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1398,7 +1398,7 @@ namespace ts {
13981398
}
13991399

14001400
const typeChecker = program.getTypeChecker();
1401-
const symbol = typeChecker.getSymbolAtLocation(node);
1401+
const symbol = getSymbolAtLocationForQuickInfo(node, typeChecker);
14021402

14031403
if (!symbol || typeChecker.isUnknownSymbol(symbol)) {
14041404
// Try getting just type at this position and show
@@ -1437,6 +1437,21 @@ namespace ts {
14371437
};
14381438
}
14391439

1440+
function getSymbolAtLocationForQuickInfo(node: Node, checker: TypeChecker): Symbol | undefined {
1441+
if ((isIdentifier(node) || isStringLiteral(node))
1442+
&& isPropertyAssignment(node.parent)
1443+
&& node.parent.name === node) {
1444+
const type = checker.getContextualType(node.parent.parent);
1445+
if (type) {
1446+
const property = checker.getPropertyOfType(type, getTextOfIdentifierOrLiteral(node));
1447+
if (property) {
1448+
return property;
1449+
}
1450+
}
1451+
}
1452+
return checker.getSymbolAtLocation(node);
1453+
}
1454+
14401455
/// Goto definition
14411456
function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] {
14421457
synchronizeHostData();

tests/cases/fourslash/contextualTyping.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
////var /*13*/c3t5: (n: number) => IFoo = function(/*14*/n) { return <IFoo>({}) };
3333
////var /*15*/c3t6: (n: number, s: string) => IFoo = function(/*16*/n, /*17*/s) { return <IFoo>({}) };
3434
////var /*18*/c3t7: {
35-
//// (n: number): number;
35+
//// (n: number): number;
3636
//// (s1: string): number;
3737
////};
3838
////var /*20*/c3t8: (n: number, s: string) => number = function(/*21*/n) { return n; };
@@ -79,7 +79,7 @@
7979
//// t5: (n: number) => IFoo;
8080
//// t6: (n: number, s: string) => IFoo;
8181
//// t7: {
82-
//// (n: number, s: string): number;
82+
//// (n: number, s: string): number;
8383
//// //(s1: string, s2: string): number;
8484
//// };
8585
//// t8: (n: number, s: string) => number;
@@ -98,7 +98,7 @@
9898
//// t5: (n: number) => IFoo;
9999
//// t6: (n: number, s: string) => IFoo;
100100
//// t7: {
101-
//// (n: number, s: string): number;
101+
//// (n: number, s: string): number;
102102
//// //(s1: string, s2: string): number;
103103
//// };
104104
//// t8: (n: number, s: string) => number;
@@ -152,7 +152,7 @@
152152
////var /*80*/c12t5 = <(n: number) => IFoo> function(/*81*/n) { return <IFoo>({}) };
153153
////var /*82*/c12t6 = <(n: number, s: string) => IFoo> function(/*83*/n, /*84*/s) { return <IFoo>({}) };
154154
////var /*85*/c12t7 = <{
155-
//// (n: number, s: string): number;
155+
//// (n: number, s: string): number;
156156
//// //(s1: string, s2: string): number;
157157
////}> function(n:number) { return n };
158158
////var /*86*/c12t8 = <(n: number, s: string) => number> function (/*87*/n) { return n; };
@@ -221,13 +221,13 @@ verify.quickInfos({
221221
25: "(parameter) n: number",
222222
26: "(parameter) s: string",
223223
27: "var c3t12: IBar",
224-
28: "(property) foo: IFoo",
224+
28: "(property) IBar.foo: IFoo",
225225
29: "var c3t13: IFoo",
226-
30: "(property) f: (i: number, s: string) => string",
226+
30: "(method) IFoo.f(i: number, s: string): string",
227227
31: "(parameter) i: number",
228228
32: "(parameter) s: string",
229229
33: "var c3t14: IFoo",
230-
34: "(property) a: undefined[]",
230+
34: "(property) IFoo.a: number[]",
231231
35: "(property) C4T5.foo: (i: number, s: string) => string",
232232
36: "(parameter) i: number",
233233
37: "(parameter) s: string",
@@ -257,13 +257,13 @@ verify.quickInfos({
257257
61: "(parameter) n: number",
258258
62: "(parameter) s: string",
259259
63: "(property) t12: IBar",
260-
64: "(property) foo: IFoo",
260+
64: "(property) IBar.foo: IFoo",
261261
65: "(property) t13: IFoo",
262-
66: "(property) f: (i: number, s: string) => string",
262+
66: "(method) IFoo.f(i: number, s: string): string",
263263
67: "(parameter) i: number",
264264
68: "(parameter) s: string",
265265
69: "(property) t14: IFoo",
266-
70: "(property) a: undefined[]",
266+
70: "(property) IFoo.a: number[]",
267267
71: "(parameter) n: number",
268268
72: "var c10t5: () => (n: number) => IFoo",
269269
73: "(parameter) n: number",
@@ -287,13 +287,13 @@ verify.quickInfos({
287287
91: "(parameter) n: number",
288288
92: "(parameter) s: string",
289289
93: "var c12t12: IBar",
290-
94: "(property) foo: IFoo",
290+
94: "(property) IBar.foo: IFoo",
291291
95: "var c12t13: IFoo",
292-
96: "(property) f: (i: number, s: string) => string",
292+
96: "(method) IFoo.f(i: number, s: string): string",
293293
97: "(parameter) i: number",
294294
98: "(parameter) s: string",
295295
99: "var c12t14: IFoo",
296-
100: "(property) a: undefined[]",
296+
100: "(property) IFoo.a: number[]",
297297
101: "function EF1(a: number, b: number): number",
298298
102: "(parameter) a: any",
299299
103: "(parameter) b: any",
@@ -302,7 +302,7 @@ verify.quickInfos({
302302
112: "(method) Point.add(dx: number, dy: number): Point",
303303
113: "(parameter) dx: number",
304304
114: "(parameter) dy: number",
305-
115: "(property) add: (dx: number, dy: number) => Point",
305+
115: "(method) Point.add(dx: number, dy: number): Point",
306306
116: "(parameter) dx: number",
307307
117: "(parameter) dy: number"
308308
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @Filename: quickInfoExportAssignmentOfGenericInterface_0.ts
4+
////interface I {
5+
//// /** Documentation */
6+
//// x: number;
7+
////}
8+
////const i: I = { /**/x: 0 };
9+
10+
verify.quickInfoAt("", "(property) I.x: number", "Documentation ");
Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
/// <reference path="fourslash.ts" />
22

33
////module Test {
4-
//// class Mocked {
5-
//// myProp: string;
6-
//// }
7-
//// class Tester {
8-
//// willThrowError() {
9-
//// Mocked = Mocked || function () { // => Error: Invalid left-hand side of assignment expression.
10-
//// return { /**/myProp: "test" };
11-
//// };
12-
//// }
13-
//// }
4+
//// class Mocked {
5+
//// myProp: string;
6+
//// }
7+
//// class Tester {
8+
//// willThrowError() {
9+
//// Mocked = Mocked || function () { // => Error: Invalid left-hand side of assignment expression.
10+
//// return { /**/myProp: "test" };
11+
//// };
12+
//// }
13+
//// }
1414
////}
1515

16-
verify.quickInfoAt("", "(property) myProp: string");
16+
verify.quickInfoAt("", "(property) myProp: string");

tests/cases/fourslash/quickInfoTypeError.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
//// f() {}
66
////});
77

8-
// The symbol indicates that this is a funciton, but the type is `any`.
8+
// The symbol indicates that this is a function, but the type is `any`.
99
// Regression test that we don't crash (by trying to get signatures from `any`).
10-
verify.quickInfoAt("", "(method) f");
10+
verify.quickInfoAt("", "(method) f(): void");

0 commit comments

Comments
 (0)