diff --git a/internal/fourslash/_scripts/failingTests.txt b/internal/fourslash/_scripts/failingTests.txt index a5eb335eac4..7220ad6ae42 100644 --- a/internal/fourslash/_scripts/failingTests.txt +++ b/internal/fourslash/_scripts/failingTests.txt @@ -327,7 +327,6 @@ TestQuickInfoJSDocFunctionThis TestQuickInfoJsDocGetterSetterNoCrash1 TestQuickInfoJsdocTypedefMissingType TestQuickInfoJSExport -TestQuickInfoMappedSpreadTypes TestQuickInfoMappedType TestQuickInfoMeaning TestQuickInfoModuleVariables @@ -364,7 +363,6 @@ TestQuickInfoTypeOfThisInStatics TestQuickInfoTypeOnlyNamespaceAndClass TestQuickInfoUnionOfNamespaces TestQuickInfoUntypedModuleImport -TestQuickinfoWrongComment TestRecursiveInternalModuleImport TestRegexDetection TestSelfReferencedExternalModule diff --git a/internal/fourslash/tests/quickInfoMappedTypeJSDoc_test.go b/internal/fourslash/tests/quickInfoMappedTypeJSDoc_test.go new file mode 100644 index 00000000000..a24f06a3622 --- /dev/null +++ b/internal/fourslash/tests/quickInfoMappedTypeJSDoc_test.go @@ -0,0 +1,35 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestQuickInfoMappedTypeJSDoc(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + + // https://github.com/microsoft/typescript-go/issues/3659 + const content = ` +type Test = { + /** a's comment */ + a: string; +}; + +type Mapped = { + [K in keyof Test]: number; +}; + +const x: Mapped = { + a: 123 +}; + +x./*1*/a +` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + + f.VerifyQuickInfoAt(t, "1", "(property) a: number", "a's comment") +} diff --git a/internal/fourslash/tests/quickInfoRootSymbolJSDocAggregation_test.go b/internal/fourslash/tests/quickInfoRootSymbolJSDocAggregation_test.go new file mode 100644 index 00000000000..a5d0b9b50e4 --- /dev/null +++ b/internal/fourslash/tests/quickInfoRootSymbolJSDocAggregation_test.go @@ -0,0 +1,55 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestQuickInfoRootSymbolJSDocAggregation(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + + const content = ` +declare const distinct: { + /** first */ + a: number; +} & { + /** second */ + a: number; +}; + +declare const duplicate: { + /** same */ + a: number; +} & { + /** same */ + a: number; +} & { + /** third */ + a: number; +}; + +declare const mixed: { + /** first */ + a: number; +} & { + /** second */ + a: number; +} & { + /** first */ + a: number; +}; + +distinct./*distinct*/a +duplicate./*duplicate*/a +mixed./*mixed*/a +` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + + f.VerifyQuickInfoAt(t, "distinct", "(property) a: number", "first\nsecond") + f.VerifyQuickInfoAt(t, "duplicate", "(property) a: number", "same\nthird") + f.VerifyQuickInfoAt(t, "mixed", "(property) a: number", "first\nsecond") +} diff --git a/internal/ls/hover.go b/internal/ls/hover.go index 1ba8bf22e7b..cea83a89406 100644 --- a/internal/ls/hover.go +++ b/internal/ls/hover.go @@ -98,6 +98,11 @@ func (l *LanguageService) getQuickInfoAndDocumentationForSymbol(c *checker.Check return quickInfo, documentation } + documentation = l.documentationFromRootSymbols(c, symbol, node, contentFormat) + if documentation != "" { + return quickInfo, documentation + } + return quickInfo, l.documentationFromAlias(c, symbol, node, contentFormat) } @@ -148,6 +153,44 @@ func (l *LanguageService) documentationFromAlias(c *checker.Checker, symbol *ast return "" } +func (l *LanguageService) documentationFromRootSymbols(c *checker.Checker, symbol *ast.Symbol, node *ast.Node, contentFormat lsproto.MarkupKind) string { + if symbol == nil { + return "" + } + + var docs []string + for _, rootSymbol := range c.GetRootSymbols(symbol) { + if rootSymbol == nil { + continue + } + declaration := rootSymbol.ValueDeclaration + if declaration == nil { + declaration = core.FirstOrNil(rootSymbol.Declarations) + } + if declaration == nil { + continue + } + if documentation := l.getDocumentationFromDeclaration(c, rootSymbol, declaration, node, contentFormat, false /*commentOnly*/); documentation != "" { + docs = core.AppendIfUnique(docs, documentation) + } + } + + if len(docs) == 0 { + return "" + } + if len(docs) == 1 { + return docs[0] + } + + var b strings.Builder + b.WriteString(docs[0]) + for _, doc := range docs[1:] { + b.WriteString("\n") + b.WriteString(doc) + } + return b.String() +} + func (l *LanguageService) getDocumentationFromDeclaration(c *checker.Checker, symbol *ast.Symbol, declaration *ast.Node, location *ast.Node, contentFormat lsproto.MarkupKind, commentOnly bool) string { if declaration == nil { return "" diff --git a/testdata/baselines/reference/fourslash/quickInfo/quickInfoOnUnionPropertiesWithIdenticalJSDocComments01.baseline b/testdata/baselines/reference/fourslash/quickInfo/quickInfoOnUnionPropertiesWithIdenticalJSDocComments01.baseline index eb716512b25..40219f5b8db 100644 --- a/testdata/baselines/reference/fourslash/quickInfo/quickInfoOnUnionPropertiesWithIdenticalJSDocComments01.baseline +++ b/testdata/baselines/reference/fourslash/quickInfo/quickInfoOnUnionPropertiesWithIdenticalJSDocComments01.baseline @@ -30,7 +30,7 @@ // | ```typescript // | (property) language?: string | undefined // | ``` -// | +// | A language id, like `typescript`. // | ---------------------------------------------------------------------- [ { @@ -46,7 +46,7 @@ "item": { "contents": { "kind": "markdown", - "value": "```typescript\n(property) language?: string | undefined\n```\n" + "value": "```typescript\n(property) language?: string | undefined\n```\nA language id, like `typescript`." }, "range": { "start": {