diff --git a/internal/fourslash/_scripts/failingTests.txt b/internal/fourslash/_scripts/failingTests.txt
index 6b5b6c602c4..21b8504355d 100644
--- a/internal/fourslash/_scripts/failingTests.txt
+++ b/internal/fourslash/_scripts/failingTests.txt
@@ -386,7 +386,6 @@ TestQuickInfoOnInternalAliases
TestQuickInfoOnJsxNamespacedNameWithDoc1
TestQuickInfoOnMergedModule
TestQuickInfoOnNarrowedTypeInModule
-TestQuickInfoOnNewKeyword01
TestQuickInfoOnObjectLiteralWithAccessors
TestQuickInfoOnObjectLiteralWithOnlyGetter
TestQuickInfoOnObjectLiteralWithOnlySetter
diff --git a/internal/fourslash/tests/completionsInJsxTag_test.go b/internal/fourslash/tests/completionsInJsxTag_test.go
index 8dc79999112..18f5ff820a3 100644
--- a/internal/fourslash/tests/completionsInJsxTag_test.go
+++ b/internal/fourslash/tests/completionsInJsxTag_test.go
@@ -66,3 +66,59 @@ class Foo {
},
})
}
+
+func TestCompletionsInJsxNamespacedIntrinsicTag(t *testing.T) {
+ t.Parallel()
+ defer testutil.RecoverAndFail(t, "Panic on fourslash test")
+ const content = `// @jsx: react
+// @Filename: /a.tsx
+declare const React: any;
+declare namespace JSX {
+ interface Element {}
+ interface IntrinsicElements {
+ /** Element docs */
+ "foo:bar": {
+ /** Foo docs */
+ foo: boolean
+ /** Bar docs */
+ bar: string
+ }
+ }
+}
+
+`
+ f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
+ defer done()
+ f.VerifyCompletions(t, []string{"1", "2"}, &fourslash.CompletionsExpectedList{
+ IsIncomplete: false,
+ ItemDefaults: &fourslash.CompletionsExpectedItemDefaults{
+ CommitCharacters: &DefaultCommitCharacters,
+ },
+ Items: &fourslash.CompletionsExpectedItems{
+ Exact: []fourslash.CompletionsExpectedItem{
+ &lsproto.CompletionItem{
+ Label: "bar",
+ Kind: new(lsproto.CompletionItemKindField),
+ Detail: new("(property) bar: string"),
+ Documentation: &lsproto.StringOrMarkupContent{
+ MarkupContent: &lsproto.MarkupContent{
+ Kind: lsproto.MarkupKindMarkdown,
+ Value: "Bar docs",
+ },
+ },
+ },
+ &lsproto.CompletionItem{
+ Label: "foo",
+ Kind: new(lsproto.CompletionItemKindField),
+ Detail: new("(property) foo: boolean"),
+ Documentation: &lsproto.StringOrMarkupContent{
+ MarkupContent: &lsproto.MarkupContent{
+ Kind: lsproto.MarkupKindMarkdown,
+ Value: "Foo docs",
+ },
+ },
+ },
+ },
+ },
+ })
+}
diff --git a/internal/fourslash/tests/quickInfoJsxNamespacedIntrinsic_test.go b/internal/fourslash/tests/quickInfoJsxNamespacedIntrinsic_test.go
new file mode 100644
index 00000000000..cf74c564ab3
--- /dev/null
+++ b/internal/fourslash/tests/quickInfoJsxNamespacedIntrinsic_test.go
@@ -0,0 +1,33 @@
+package fourslash_test
+
+import (
+ "testing"
+
+ "github.com/microsoft/typescript-go/internal/fourslash"
+ "github.com/microsoft/typescript-go/internal/testutil"
+)
+
+func TestQuickInfoJsxNamespacedIntrinsic(t *testing.T) {
+ t.Parallel()
+ defer testutil.RecoverAndFail(t, "Panic on fourslash test")
+ const content = `// @jsx: react
+// @Filename: /a.tsx
+declare const React: any;
+declare namespace JSX {
+ interface Element {}
+ interface IntrinsicElements {
+ /** Element docs */
+ "foo:bar": {
+ /** Foo docs */
+ foo: boolean
+ /** Bar docs */
+ bar: string
+ }
+ }
+}
+`
+ f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
+ defer done()
+ f.VerifyQuickInfoAt(t, "tag", "(property) JSX.IntrinsicElements[\"foo:bar\"]: {\n foo: boolean;\n bar: string;\n}", "Element docs")
+ f.VerifyQuickInfoAt(t, "attr", "(property) foo: boolean", "Foo docs")
+}
diff --git a/internal/ls/completions.go b/internal/ls/completions.go
index 5eb40157301..a68776a7273 100644
--- a/internal/ls/completions.go
+++ b/internal/ls/completions.go
@@ -4153,7 +4153,7 @@ func tryGetContainingJsxElement(contextToken *ast.Node, file *ast.SourceFile) *a
parent := contextToken.Parent
switch contextToken.Kind {
case ast.KindGreaterThanToken, ast.KindLessThanSlashToken, ast.KindSlashToken, ast.KindIdentifier,
- ast.KindPropertyAccessExpression, ast.KindJsxAttributes, ast.KindJsxAttribute, ast.KindJsxSpreadAttribute:
+ ast.KindPropertyAccessExpression, ast.KindJsxNamespacedName, ast.KindJsxAttributes, ast.KindJsxAttribute, ast.KindJsxSpreadAttribute:
if parent != nil && (parent.Kind == ast.KindJsxSelfClosingElement || parent.Kind == ast.KindJsxOpeningElement) {
if contextToken.Kind == ast.KindGreaterThanToken {
precedingToken := astnav.FindPrecedingToken(file, contextToken.Pos())
@@ -4163,6 +4163,9 @@ func tryGetContainingJsxElement(contextToken *ast.Node, file *ast.SourceFile) *a
}
}
return parent
+ } else if parent != nil && ast.IsJsxNamespacedName(parent) &&
+ parent.Parent != nil && (parent.Parent.Kind == ast.KindJsxSelfClosingElement || parent.Parent.Kind == ast.KindJsxOpeningElement) {
+ return parent.Parent
} else if parent != nil && parent.Kind == ast.KindJsxAttribute {
// Currently we parse JsxOpeningLikeElement as:
// JsxOpeningLikeElement
diff --git a/internal/ls/hover.go b/internal/ls/hover.go
index c7dbfb80b7a..da4f11883c0 100644
--- a/internal/ls/hover.go
+++ b/internal/ls/hover.go
@@ -41,7 +41,7 @@ func (l *LanguageService) ProvideHover(ctx context.Context, params *lsproto.Hove
c, done := program.GetTypeCheckerForFile(ctx, file)
defer done()
rangeNode := getNodeForQuickInfo(node)
- symbol := getSymbolAtLocationForQuickInfo(c, node)
+ symbol := getSymbolAtLocationForQuickInfo(c, rangeNode)
// Always create VerbosityContext for hover so that canExpandSymbol can signal
// canIncreaseVerbosity even at Level 0. The nodebuilder also detects expandable
diff --git a/testdata/baselines/reference/fourslash/quickInfo/quickInfoImportMeta.baseline b/testdata/baselines/reference/fourslash/quickInfo/quickInfoImportMeta.baseline
index 9e138c380a5..31230b9447f 100644
--- a/testdata/baselines/reference/fourslash/quickInfo/quickInfoImportMeta.baseline
+++ b/testdata/baselines/reference/fourslash/quickInfo/quickInfoImportMeta.baseline
@@ -9,9 +9,12 @@
// ^^^^^^^^^^^
// | ----------------------------------------------------------------------
// | ```typescript
-// | (property) ImportMetaExpression.meta: ImportMeta
+// | interface ImportMeta
// | ```
+// | The type of `import.meta`.
// |
+// | If you need to declare that a given property exists on `import.meta`,
+// | this type may be augmented via interface merging.
// | ----------------------------------------------------------------------
[
{
@@ -39,7 +42,7 @@
"item": {
"contents": {
"kind": "markdown",
- "value": "```typescript\n(property) ImportMetaExpression.meta: ImportMeta\n```\n"
+ "value": "```typescript\ninterface ImportMeta\n```\nThe type of `import.meta`.\n\nIf you need to declare that a given property exists on `import.meta`,\nthis type may be augmented via interface merging."
},
"range": {
"start": {
diff --git a/testdata/baselines/reference/fourslash/quickInfo/quickInfoOnJsxNamespacedName.baseline b/testdata/baselines/reference/fourslash/quickInfo/quickInfoOnJsxNamespacedName.baseline
index 8dbf51c068d..d130f3a1b1e 100644
--- a/testdata/baselines/reference/fourslash/quickInfo/quickInfoOnJsxNamespacedName.baseline
+++ b/testdata/baselines/reference/fourslash/quickInfo/quickInfoOnJsxNamespacedName.baseline
@@ -1,9 +1,14 @@
// === QuickInfo ===
=== /a.tsx ===
// ;
-// ^
+// ^^^
// | ----------------------------------------------------------------------
-// | No quickinfo at /**/.
+// | ```typescript
+// | (property) JSX.IntrinsicElements['a:b']: {
+// | a: string;
+// | }
+// | ```
+// |
// | ----------------------------------------------------------------------
[
{
@@ -16,6 +21,21 @@
"Name": "",
"Data": {}
},
- "item": null
+ "item": {
+ "contents": {
+ "kind": "markdown",
+ "value": "```typescript\n(property) JSX.IntrinsicElements['a:b']: {\n a: string;\n}\n```\n"
+ },
+ "range": {
+ "start": {
+ "line": 0,
+ "character": 1
+ },
+ "end": {
+ "line": 0,
+ "character": 4
+ }
+ }
+ }
}
]
\ No newline at end of file