Skip to content

Commit 3499951

Browse files
authored
Handle property access expressions in type node serialization (#3633)
1 parent 6bf24cc commit 3499951

4 files changed

Lines changed: 206 additions & 2 deletions

File tree

internal/ast/precedence.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,6 @@ func GetTypeNodePrecedence(n *TypeNode) TypePrecedence {
698698
KindLiteralType,
699699
KindTypePredicate,
700700
KindTypeReference,
701-
KindExpressionWithTypeArguments,
702701
KindTypeLiteral,
703702
KindTupleType,
704703
KindRestType,
@@ -707,7 +706,10 @@ func GetTypeNodePrecedence(n *TypeNode) TypePrecedence {
707706
KindMappedType,
708707
KindNamedTupleMember,
709708
KindTemplateLiteralType,
710-
KindImportType:
709+
KindImportType,
710+
// These occur in pseudo-types like `f<T>.C`, where `f` is a generic function and `C` is a local type
711+
KindPropertyAccessExpression,
712+
KindExpressionWithTypeArguments:
711713
return TypePrecedenceNonArray
712714
default:
713715
panic(fmt.Sprintf("unhandled TypeNode: %v", n.Kind))
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package fourslash_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/microsoft/typescript-go/internal/fourslash"
7+
"github.com/microsoft/typescript-go/internal/testutil"
8+
)
9+
10+
func TestQuickInfoGenericTypePath(t *testing.T) {
11+
fourslash.SkipIfFailing(t)
12+
t.Parallel()
13+
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
14+
const content = `
15+
function f<T>(x: T) {
16+
class C {
17+
value = x
18+
}
19+
return new C()
20+
}
21+
22+
class Box<T> {
23+
public value: T;
24+
constructor(value: T) {
25+
this.value = value;
26+
}
27+
}
28+
29+
const instance = f/*callF*/("hello");
30+
const b1/*b1*/ = new Box/*newBox*/(instance);
31+
declare const b2/*b2*/: Box<typeof instance>;
32+
`
33+
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
34+
defer done()
35+
f.VerifyBaselineHover(t)
36+
}

internal/printer/printer.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2322,6 +2322,9 @@ func (p *Printer) emitTypeNode(node *ast.TypeNode, precedence ast.TypePrecedence
23222322
case ast.KindImportType:
23232323
p.emitImportTypeNode(node.AsImportTypeNode())
23242324

2325+
case ast.KindPropertyAccessExpression:
2326+
// Occurs in pseudo-types such as `f<T>.C`, where `f` is a generic function and `C` is a local type
2327+
p.emitPropertyAccessExpression(node.AsPropertyAccessExpression())
23252328
case ast.KindExpressionWithTypeArguments:
23262329
// !!! Should this actually be considered a type?
23272330
p.emitExpressionWithTypeArguments(node.AsExpressionWithTypeArguments())
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// === QuickInfo ===
2+
=== /quickInfoGenericTypePath.ts ===
3+
//
4+
// function f<T>(x: T) {
5+
// class C {
6+
// value = x
7+
// }
8+
// return new C()
9+
// }
10+
//
11+
// class Box<T> {
12+
// public value: T;
13+
// constructor(value: T) {
14+
// this.value = value;
15+
// }
16+
// }
17+
//
18+
// const instance = f("hello");
19+
// ^
20+
// | ----------------------------------------------------------------------
21+
// | ```typescript
22+
// | function f<string>(x: string): f<string>.C
23+
// | ```
24+
// |
25+
// | ----------------------------------------------------------------------
26+
// const b1 = new Box(instance);
27+
// ^^
28+
// | ----------------------------------------------------------------------
29+
// | ```typescript
30+
// | const b1: Box<f<string>.C>
31+
// | ```
32+
// |
33+
// | ----------------------------------------------------------------------
34+
// ^^^
35+
// | ----------------------------------------------------------------------
36+
// | ```typescript
37+
// | constructor Box<f<string>.C>(value: f<string>.C): Box<f<string>.C>
38+
// | ```
39+
// |
40+
// | ----------------------------------------------------------------------
41+
// declare const b2: Box<typeof instance>;
42+
// ^^
43+
// | ----------------------------------------------------------------------
44+
// | ```typescript
45+
// | const b2: Box<f<string>.C>
46+
// | ```
47+
// |
48+
// | ----------------------------------------------------------------------
49+
//
50+
[
51+
{
52+
"marker": {
53+
"Position": 182,
54+
"LSPosition": {
55+
"line": 15,
56+
"character": 18
57+
},
58+
"Name": "callF",
59+
"Data": {}
60+
},
61+
"item": {
62+
"contents": {
63+
"kind": "markdown",
64+
"value": "```typescript\nfunction f<string>(x: string): f<string>.C\n```\n"
65+
},
66+
"range": {
67+
"start": {
68+
"line": 15,
69+
"character": 17
70+
},
71+
"end": {
72+
"line": 15,
73+
"character": 18
74+
}
75+
},
76+
"canIncreaseVerbosity": true
77+
}
78+
},
79+
{
80+
"marker": {
81+
"Position": 201,
82+
"LSPosition": {
83+
"line": 16,
84+
"character": 8
85+
},
86+
"Name": "b1",
87+
"Data": {}
88+
},
89+
"item": {
90+
"contents": {
91+
"kind": "markdown",
92+
"value": "```typescript\nconst b1: Box<f<string>.C>\n```\n"
93+
},
94+
"range": {
95+
"start": {
96+
"line": 16,
97+
"character": 6
98+
},
99+
"end": {
100+
"line": 16,
101+
"character": 8
102+
}
103+
},
104+
"canIncreaseVerbosity": true
105+
}
106+
},
107+
{
108+
"marker": {
109+
"Position": 211,
110+
"LSPosition": {
111+
"line": 16,
112+
"character": 18
113+
},
114+
"Name": "newBox",
115+
"Data": {}
116+
},
117+
"item": {
118+
"contents": {
119+
"kind": "markdown",
120+
"value": "```typescript\nconstructor Box<f<string>.C>(value: f<string>.C): Box<f<string>.C>\n```\n"
121+
},
122+
"range": {
123+
"start": {
124+
"line": 16,
125+
"character": 15
126+
},
127+
"end": {
128+
"line": 16,
129+
"character": 18
130+
}
131+
},
132+
"canIncreaseVerbosity": true
133+
}
134+
},
135+
{
136+
"marker": {
137+
"Position": 239,
138+
"LSPosition": {
139+
"line": 17,
140+
"character": 16
141+
},
142+
"Name": "b2",
143+
"Data": {}
144+
},
145+
"item": {
146+
"contents": {
147+
"kind": "markdown",
148+
"value": "```typescript\nconst b2: Box<f<string>.C>\n```\n"
149+
},
150+
"range": {
151+
"start": {
152+
"line": 17,
153+
"character": 14
154+
},
155+
"end": {
156+
"line": 17,
157+
"character": 16
158+
}
159+
},
160+
"canIncreaseVerbosity": true
161+
}
162+
}
163+
]

0 commit comments

Comments
 (0)