diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index e3ef4d3e495..ad9ac88bdfc 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -75,10 +75,16 @@ namespace ts.SymbolDisplay { } return unionPropertyKind; } - if (location.parent && isJsxAttribute(location.parent)) { - return ScriptElementKind.jsxAttribute; + // If we requested completions after `x.` at the top-level, we may be at a source file location. + switch (location.parent && location.parent.kind) { + // If we've typed a character of the attribute name, will be 'JsxAttribute', else will be 'JsxOpeningElement'. + case SyntaxKind.JsxOpeningElement: + return location.kind === SyntaxKind.Identifier ? ScriptElementKind.memberVariableElement : ScriptElementKind.jsxAttribute; + case SyntaxKind.JsxAttribute: + return ScriptElementKind.jsxAttribute; + default: + return ScriptElementKind.memberVariableElement; } - return ScriptElementKind.memberVariableElement; } return ScriptElementKind.unknown; diff --git a/tests/cases/fourslash/completionsJsxAttribute.ts b/tests/cases/fourslash/completionsJsxAttribute.ts new file mode 100644 index 00000000000..29e6122ef18 --- /dev/null +++ b/tests/cases/fourslash/completionsJsxAttribute.ts @@ -0,0 +1,22 @@ +/// + +// @jsx: preserve + +// @Filename: /a.tsx +////declare namespace JSX { +//// interface Element {} +//// interface IntrinsicElements { +//// div: { +//// /** Doc */ +//// foo: string +//// } +//// } +////} +//// +////
; + +goTo.marker(); +verify.completionEntryDetailIs("foo", "(JSX attribute) foo: string", "Doc ", "JSX attribute", []); +edit.insert("f"); +verify.completionEntryDetailIs("foo", "(JSX attribute) foo: string", "Doc ", "JSX attribute", []); +