Skip to content

Commit 9c70e77

Browse files
authored
Align Quick Info display more closely with old language service (#864)
1 parent 7d71d08 commit 9c70e77

File tree

2 files changed

+119
-20
lines changed

2 files changed

+119
-20
lines changed

internal/checker/printer.go

Lines changed: 118 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package checker
22

33
import (
4+
"fmt"
45
"strings"
56

67
"github.com/microsoft/typescript-go/internal/ast"
@@ -79,6 +80,107 @@ func (c *Checker) typeToStringEx(t *Type, enclosingDeclaration *ast.Node, flags
7980
return p.string()
8081
}
8182

83+
func (c *Checker) GetQuickInfoAtLocation(node *ast.Node) string {
84+
symbol := c.GetSymbolAtLocation(node)
85+
isAlias := symbol != nil && symbol.Flags&ast.SymbolFlagsAlias != 0
86+
if isAlias {
87+
symbol = c.resolveAlias(symbol)
88+
}
89+
if symbol == nil || symbol == c.unknownSymbol {
90+
return ""
91+
}
92+
flags := symbol.Flags
93+
if flags&ast.SymbolFlagsType != 0 && !ast.IsInExpressionContext(node) {
94+
// If the symbol has a type meaning and we're not in an expression context, remove any value meanings
95+
flags &^= ast.SymbolFlagsValue
96+
}
97+
p := c.newPrinter(TypeFormatFlagsNone)
98+
if isAlias {
99+
p.print("(alias) ")
100+
}
101+
switch {
102+
case flags&(ast.SymbolFlagsVariable|ast.SymbolFlagsProperty|ast.SymbolFlagsAccessor) != 0:
103+
switch {
104+
case flags&ast.SymbolFlagsProperty != 0:
105+
p.print("(property) ")
106+
case flags&ast.SymbolFlagsAccessor != 0:
107+
p.print("(accessor) ")
108+
default:
109+
decl := symbol.ValueDeclaration
110+
if decl != nil {
111+
switch {
112+
case ast.IsParameter(decl):
113+
p.print("(parameter) ")
114+
case ast.IsVarLet(decl):
115+
p.print("let ")
116+
case ast.IsVarConst(decl):
117+
p.print("const ")
118+
case ast.IsVarUsing(decl):
119+
p.print("using ")
120+
case ast.IsVarAwaitUsing(decl):
121+
p.print("await using ")
122+
default:
123+
p.print("var ")
124+
}
125+
}
126+
}
127+
p.printName(symbol)
128+
p.print(": ")
129+
p.printType(c.getTypeOfSymbol(symbol))
130+
case flags&ast.SymbolFlagsEnumMember != 0:
131+
p.print("(enum member) ")
132+
t := c.getTypeOfSymbol(symbol)
133+
p.printType(t)
134+
if t.flags&TypeFlagsLiteral != 0 {
135+
p.print(" = ")
136+
p.printValue(t.AsLiteralType().value)
137+
}
138+
case flags&(ast.SymbolFlagsFunction|ast.SymbolFlagsMethod) != 0:
139+
t := c.getTypeOfSymbol(symbol)
140+
signatures := c.getSignaturesOfType(t, SignatureKindCall)
141+
prefix := core.IfElse(symbol.Flags&ast.SymbolFlagsMethod != 0, "(method) ", "function ")
142+
for i, sig := range signatures {
143+
if i != 0 {
144+
p.print("\n")
145+
}
146+
if i == 3 && len(signatures) >= 5 {
147+
p.print(fmt.Sprintf("// +%v more overloads", len(signatures)-3))
148+
break
149+
}
150+
p.print(prefix)
151+
p.printName(symbol)
152+
p.printSignature(sig, ": ")
153+
}
154+
case flags&(ast.SymbolFlagsClass|ast.SymbolFlagsInterface) != 0:
155+
p.print(core.IfElse(symbol.Flags&ast.SymbolFlagsClass != 0, "class ", "interface "))
156+
p.printName(symbol)
157+
p.printTypeParameters(c.getDeclaredTypeOfSymbol(symbol).AsInterfaceType().LocalTypeParameters())
158+
case flags&ast.SymbolFlagsEnum != 0:
159+
p.print("enum ")
160+
p.printName(symbol)
161+
case flags&ast.SymbolFlagsModule != 0:
162+
p.print(core.IfElse(symbol.ValueDeclaration != nil && ast.IsSourceFile(symbol.ValueDeclaration), "module ", "namespace "))
163+
p.printName(symbol)
164+
case flags&ast.SymbolFlagsTypeParameter != 0:
165+
p.print("(type parameter) ")
166+
p.printTypeParameterAndConstraint(c.getDeclaredTypeOfSymbol(symbol))
167+
case flags&ast.SymbolFlagsTypeAlias != 0:
168+
p.print("type ")
169+
p.printName(symbol)
170+
p.printTypeParameters(c.typeAliasLinks.Get(symbol).typeParameters)
171+
if len(symbol.Declarations) != 0 {
172+
p.print(" = ")
173+
p.printTypeNoAlias(c.getDeclaredTypeOfSymbol(symbol))
174+
}
175+
case flags&ast.SymbolFlagsAlias != 0:
176+
p.print("import ")
177+
p.printName(symbol)
178+
default:
179+
p.printType(c.getTypeOfSymbol(symbol))
180+
}
181+
return p.string()
182+
}
183+
82184
func (c *Checker) signatureToString(s *Signature) string {
83185
p := c.newPrinter(TypeFormatFlagsNone)
84186
if s.flags&SignatureFlagsConstruct != 0 {
@@ -333,6 +435,21 @@ func (p *Printer) printTypeArguments(typeArguments []*Type) {
333435
}
334436
}
335437

438+
func (p *Printer) printTypeParameters(typeParameters []*Type) {
439+
if len(typeParameters) != 0 {
440+
p.print("<")
441+
var tail bool
442+
for _, tp := range typeParameters {
443+
if tail {
444+
p.print(", ")
445+
}
446+
p.printTypeParameterAndConstraint(tp)
447+
tail = true
448+
}
449+
p.print(">")
450+
}
451+
}
452+
336453
func (p *Printer) printArrayType(t *Type) {
337454
d := t.AsTypeReference()
338455
if d.target != p.c.globalArrayType {
@@ -460,18 +577,7 @@ func (p *Printer) printAnonymousType(t *Type) {
460577
}
461578

462579
func (p *Printer) printSignature(sig *Signature, returnSeparator string) {
463-
if len(sig.typeParameters) != 0 {
464-
p.print("<")
465-
var tail bool
466-
for _, tp := range sig.typeParameters {
467-
if tail {
468-
p.print(", ")
469-
}
470-
p.printTypeParameterAndConstraint(tp)
471-
tail = true
472-
}
473-
p.print(">")
474-
}
580+
p.printTypeParameters(sig.typeParameters)
475581
p.print("(")
476582
var tail bool
477583
if sig.thisParameter != nil {

internal/ls/hover.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,5 @@ func (l *LanguageService) ProvideHover(fileName string, position int) string {
1212
// Avoid giving quickInfo for the sourceFile as a whole.
1313
return ""
1414
}
15-
16-
checker := program.GetTypeChecker()
17-
if symbol := checker.GetSymbolAtLocation(node); symbol != nil {
18-
if t := checker.GetTypeOfSymbolAtLocation(symbol, node); t != nil {
19-
return checker.TypeToString(t)
20-
}
21-
}
22-
return ""
15+
return program.GetTypeChecker().GetQuickInfoAtLocation(node)
2316
}

0 commit comments

Comments
 (0)