Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions internal/fourslash/tests/destructuredInterfaceJSDoc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package fourslash_test

import (
"testing"

"github.com/microsoft/typescript-go/internal/fourslash"
"github.com/microsoft/typescript-go/internal/testutil"
)

func TestDestructuredInterfaceJSDoc(t *testing.T) {
t.Parallel()
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
const content = `
interface FooBar {
/** foo comment */
foo: number;
/** bar comment */
bar: string;
/** baz comment */
baz: string;
}

declare const fubar: FooBar;

const {/*1*/foo, /*2*/bar, /*3*/baz} = fubar;
`
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
defer done()
f.VerifyQuickInfoAt(t, "1", "const foo: number", "foo comment")
f.VerifyQuickInfoAt(t, "2", "const bar: string", "bar comment")
f.VerifyQuickInfoAt(t, "3", "const baz: string", "baz comment")
}

func TestDestructuredInterfaceJSDocWithRename(t *testing.T) {
t.Parallel()
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
const content = `
interface FooBar {
/** foo comment */
foo: number;
/** bar comment */
bar: string;
}

declare const fubar: FooBar;

const {foo: /*1*/myFoo, bar: /*2*/myBar} = fubar;
`
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
defer done()
f.VerifyQuickInfoAt(t, "1", "const myFoo: number", "foo comment")
f.VerifyQuickInfoAt(t, "2", "const myBar: string", "bar comment")
}
39 changes: 37 additions & 2 deletions internal/ls/hover.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,31 @@ func (l *LanguageService) getQuickInfoAndDocumentationForSymbol(c *checker.Check
if quickInfo == "" {
return "", ""
}
return quickInfo, l.getDocumentationFromDeclaration(c, declaration, contentFormat)
return quickInfo, l.getDocumentationFromDeclaration(c, symbol, declaration, node, contentFormat)
}

func (l *LanguageService) getDocumentationFromDeclaration(c *checker.Checker, declaration *ast.Node, contentFormat lsproto.MarkupKind) string {
func (l *LanguageService) getDocumentationFromDeclaration(c *checker.Checker, symbol *ast.Symbol, declaration *ast.Node, location *ast.Node, contentFormat lsproto.MarkupKind) string {
// Handle binding elements specially (variables created from destructuring) - we need to get the documentation from the property type
// The declaration passed in might be the binding element itself, but we need the interface property declaration
if symbol != nil && symbol.ValueDeclaration != nil && ast.IsBindingElement(symbol.ValueDeclaration) && ast.IsIdentifier(location) {
bindingElement := symbol.ValueDeclaration
parent := bindingElement.Parent
name := bindingElement.PropertyName()
if name == nil {
name = bindingElement.Name()
}
if ast.IsIdentifier(name) && ast.IsObjectBindingPattern(parent) {
propertyName := name.Text()
objectType := c.GetTypeAtLocation(parent)
if objectType != nil {
propertySymbol := findPropertyInType(c, objectType, propertyName)
if propertySymbol != nil && propertySymbol.ValueDeclaration != nil {
declaration = propertySymbol.ValueDeclaration
}
}
}
}

if declaration == nil {
return ""
}
Expand Down Expand Up @@ -582,6 +603,20 @@ func writeQuotedString(b *strings.Builder, str string, quote bool) {
}
}

// findPropertyInType finds a property in a type, handling union types by searching constituent types
func findPropertyInType(c *checker.Checker, objectType *checker.Type, propertyName string) *ast.Symbol {
// For union types, try to find the property in any of the constituent types
if objectType.IsUnion() {
for _, t := range objectType.Types() {
if prop := c.GetPropertyOfType(t, propertyName); prop != nil {
return prop
}
}
return nil
}
return c.GetPropertyOfType(objectType, propertyName)
}

func getEntityNameString(name *ast.Node) string {
var b strings.Builder
writeEntityNameParts(&b, name)
Expand Down
2 changes: 1 addition & 1 deletion internal/ls/signaturehelp.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ func (l *LanguageService) getSignatureHelpItem(candidate *checker.Signature, isT
// Generate documentation from the signature's declaration
var documentation *string
if declaration := candidate.Declaration(); declaration != nil {
doc := l.getDocumentationFromDeclaration(c, declaration, docFormat)
doc := l.getDocumentationFromDeclaration(c, nil, declaration, nil, docFormat)
if doc != "" {
documentation = &doc
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// | ```tsx
// | var foo: string
// | ```
// |
// | A description of foo
// | ----------------------------------------------------------------------
// }
[
Expand All @@ -31,7 +31,7 @@
"item": {
"contents": {
"kind": "markdown",
"value": "```tsx\nvar foo: string\n```\n"
"value": "```tsx\nvar foo: string\n```\nA description of foo"
},
"range": {
"start": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@
// | ```tsx
// | var a: { b: string; }
// | ```
// |
// | A description of 'a'
// | ----------------------------------------------------------------------
// b;
// ^
// | ----------------------------------------------------------------------
// | ```tsx
// | var b: string
// | ```
// |
// | A description of 'b'
// | ----------------------------------------------------------------------
// }
[
Expand All @@ -44,7 +44,7 @@
"item": {
"contents": {
"kind": "markdown",
"value": "```tsx\nvar a: { b: string; }\n```\n"
"value": "```tsx\nvar a: { b: string; }\n```\nA description of 'a'"
},
"range": {
"start": {
Expand All @@ -71,7 +71,7 @@
"item": {
"contents": {
"kind": "markdown",
"value": "```tsx\nvar b: string\n```\n"
"value": "```tsx\nvar b: string\n```\nA description of 'b'"
},
"range": {
"start": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// | ```tsx
// | var a: string | number
// | ```
// |
// | A description of a
// | ----------------------------------------------------------------------
// }
[
Expand All @@ -34,7 +34,7 @@
"item": {
"contents": {
"kind": "markdown",
"value": "```tsx\nvar a: string | number\n```\n"
"value": "```tsx\nvar a: string | number\n```\nA description of a"
},
"range": {
"start": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
// | ```tsx
// | const isBar: boolean
// | ```
// |
// | Thing is a baz
// | ----------------------------------------------------------------------
[
{
Expand All @@ -39,7 +39,7 @@
"item": {
"contents": {
"kind": "markdown",
"value": "```tsx\nconst isBar: boolean\n```\n"
"value": "```tsx\nconst isBar: boolean\n```\nThing is a baz"
},
"range": {
"start": {
Expand Down
Loading