From 6e827c759e3294a3bd284c28de1f2d1f05f38ecb Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 13 Nov 2025 00:24:30 +0000 Subject: [PATCH 1/3] Use symbol of contextual type for object literal elements in hovers/quick info. --- internal/ls/hover.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/internal/ls/hover.go b/internal/ls/hover.go index 6d5dffee0d..ebb479241b 100644 --- a/internal/ls/hover.go +++ b/internal/ls/hover.go @@ -28,7 +28,8 @@ func (l *LanguageService) ProvideHover(ctx context.Context, documentURI lsproto. c, done := program.GetTypeCheckerForFile(ctx, file) defer done() rangeNode := getNodeForQuickInfo(node) - quickInfo, documentation := l.getQuickInfoAndDocumentationForSymbol(c, c.GetSymbolAtLocation(node), rangeNode, contentFormat) + symbol := getSymbolAtLocationForQuickInfo(c, node) + quickInfo, documentation := l.getQuickInfoAndDocumentationForSymbol(c, symbol, rangeNode, contentFormat) if quickInfo == "" { return lsproto.HoverOrNull{}, nil } @@ -282,6 +283,21 @@ func getNodeForQuickInfo(node *ast.Node) *ast.Node { return node } +func getSymbolAtLocationForQuickInfo(c *checker.Checker, node *ast.Node) *ast.Symbol { + objectElement := getContainingObjectLiteralElement(node) + if objectElement != nil { + contextualType := c.GetContextualType(objectElement.Parent, checker.ContextFlagsNone) + if contextualType != nil { + properties := c.GetPropertySymbolsFromContextualType(objectElement, contextualType, false /*unionSymbolOk*/) + if len(properties) == 1 { + return properties[0] + } + } + } + + return c.GetSymbolAtLocation(node) +} + func inConstructorContext(node *ast.Node) bool { if node.Kind == ast.KindConstructorKeyword { return true From 8363567e61629dc4fadae7e1a1ff86d1112ffc3e Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 13 Nov 2025 00:25:06 +0000 Subject: [PATCH 2/3] Update passing tests. --- internal/fourslash/_scripts/failingTests.txt | 3 --- .../fourslash/tests/gen/quickInfoFromContextualType_test.go | 2 +- .../fourslash/tests/gen/quickInfoMappedTypeMethods_test.go | 2 +- .../fourslash/tests/gen/quickInfoUnion_discriminated_test.go | 2 +- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/internal/fourslash/_scripts/failingTests.txt b/internal/fourslash/_scripts/failingTests.txt index 7e671cbede..a54667b7b0 100644 --- a/internal/fourslash/_scripts/failingTests.txt +++ b/internal/fourslash/_scripts/failingTests.txt @@ -454,7 +454,6 @@ TestQuickInfoForTypeParameterInTypeAlias1 TestQuickInfoForTypeParameterInTypeAlias2 TestQuickInfoForTypeofParameter TestQuickInfoForUMDModuleAlias -TestQuickInfoFromContextualType TestQuickInfoFunctionKeyword TestQuickInfoGenerics TestQuickInfoGetterSetter @@ -471,7 +470,6 @@ TestQuickInfoJsDocNonDiscriminatedUnionSharedProp TestQuickInfoJsdocTypedefMissingType TestQuickInfoMappedSpreadTypes TestQuickInfoMappedType -TestQuickInfoMappedTypeMethods TestQuickInfoMappedTypeRecursiveInference TestQuickInfoModuleVariables TestQuickInfoNarrowedTypeOfAliasSymbol @@ -526,7 +524,6 @@ TestQuickInfoTypeError TestQuickInfoTypeOfThisInStatics TestQuickInfoTypeOnlyNamespaceAndClass TestQuickInfoUnionOfNamespaces -TestQuickInfoUnion_discriminated TestQuickInfoWidenedTypes TestQuickInfo_notInsideComment TestQuickInforForSucessiveInferencesIsNotAny diff --git a/internal/fourslash/tests/gen/quickInfoFromContextualType_test.go b/internal/fourslash/tests/gen/quickInfoFromContextualType_test.go index cffaadcafc..7ce07026be 100644 --- a/internal/fourslash/tests/gen/quickInfoFromContextualType_test.go +++ b/internal/fourslash/tests/gen/quickInfoFromContextualType_test.go @@ -9,7 +9,7 @@ import ( func TestQuickInfoFromContextualType(t *testing.T) { t.Parallel() - t.Skip() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") const content = `// @Filename: quickInfoExportAssignmentOfGenericInterface_0.ts interface I { diff --git a/internal/fourslash/tests/gen/quickInfoMappedTypeMethods_test.go b/internal/fourslash/tests/gen/quickInfoMappedTypeMethods_test.go index aa599f2a08..60a3ef6150 100644 --- a/internal/fourslash/tests/gen/quickInfoMappedTypeMethods_test.go +++ b/internal/fourslash/tests/gen/quickInfoMappedTypeMethods_test.go @@ -9,7 +9,7 @@ import ( func TestQuickInfoMappedTypeMethods(t *testing.T) { t.Parallel() - t.Skip() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") const content = `type M = { [K in 'one']: any }; const x: M = { diff --git a/internal/fourslash/tests/gen/quickInfoUnion_discriminated_test.go b/internal/fourslash/tests/gen/quickInfoUnion_discriminated_test.go index db39343a15..f4fbac65dc 100644 --- a/internal/fourslash/tests/gen/quickInfoUnion_discriminated_test.go +++ b/internal/fourslash/tests/gen/quickInfoUnion_discriminated_test.go @@ -9,7 +9,7 @@ import ( func TestQuickInfoUnion_discriminated(t *testing.T) { t.Parallel() - t.Skip() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") const content = `// @Filename: quickInfoJsDocTags.ts type U = A | B; From 6cba17b9c9f183c7935d6013e1b78fd54a58ca8d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 13 Nov 2025 00:33:53 +0000 Subject: [PATCH 3/3] Use some `if var := ...; {}`s instead. --- internal/ls/hover.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/internal/ls/hover.go b/internal/ls/hover.go index ebb479241b..808efe7dbf 100644 --- a/internal/ls/hover.go +++ b/internal/ls/hover.go @@ -284,17 +284,13 @@ func getNodeForQuickInfo(node *ast.Node) *ast.Node { } func getSymbolAtLocationForQuickInfo(c *checker.Checker, node *ast.Node) *ast.Symbol { - objectElement := getContainingObjectLiteralElement(node) - if objectElement != nil { - contextualType := c.GetContextualType(objectElement.Parent, checker.ContextFlagsNone) - if contextualType != nil { - properties := c.GetPropertySymbolsFromContextualType(objectElement, contextualType, false /*unionSymbolOk*/) - if len(properties) == 1 { + if objectElement := getContainingObjectLiteralElement(node); objectElement != nil { + if contextualType := c.GetContextualType(objectElement.Parent, checker.ContextFlagsNone); contextualType != nil { + if properties := c.GetPropertySymbolsFromContextualType(objectElement, contextualType, false /*unionSymbolOk*/); len(properties) == 1 { return properties[0] } } } - return c.GetSymbolAtLocation(node) }