diff --git a/src/services/completions.ts b/src/services/completions.ts
index a895be8a7da..71fe4ce1c78 100644
--- a/src/services/completions.ts
+++ b/src/services/completions.ts
@@ -20,6 +20,22 @@ namespace ts.Completions {
const { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, requestJsDocTagName, requestJsDocTag, hasFilteredClassMemberKeywords } = completionData;
+ if (sourceFile.languageVariant === LanguageVariant.JSX &&
+ location && location.parent && location.parent.kind === SyntaxKind.JsxClosingElement) {
+ // In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag,
+ // instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element.
+ // For example:
+ // var x =
/*1*/> completion list at "1" will contain "div" with type any
+ const tagName = (
location.parent.parent).openingElement.tagName;
+ return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false,
+ entries: [{
+ name: (tagName).getFullText(),
+ kind: ScriptElementKind.classElement,
+ kindModifiers: undefined,
+ sortText: "0",
+ }]};
+ }
+
if (requestJsDocTagName) {
// If the current position is a jsDoc tag name, only tag names should be provided for completion
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: JsDoc.getJSDocTagNameCompletions() };
@@ -38,21 +54,7 @@ namespace ts.Completions {
}
else {
if (!symbols || symbols.length === 0) {
- if (sourceFile.languageVariant === LanguageVariant.JSX &&
- location.parent && location.parent.kind === SyntaxKind.JsxClosingElement) {
- // In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag,
- // instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element.
- // For example:
- // var x = /*1*/> completion list at "1" will contain "div" with type any
- const tagName = (location.parent.parent).openingElement.tagName;
- entries.push({
- name: (tagName).text,
- kind: undefined,
- kindModifiers: undefined,
- sortText: "0",
- });
- }
- else if (!hasFilteredClassMemberKeywords) {
+ if (!hasFilteredClassMemberKeywords) {
return undefined;
}
}
@@ -495,7 +497,7 @@ namespace ts.Completions {
// It has a left-hand side, so we're not in an opening JSX tag.
break;
}
- // falls through
+ // falls through
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxElement:
@@ -1050,7 +1052,7 @@ namespace ts.Completions {
default:
if (isFromClassElementDeclaration(contextToken) &&
(isClassMemberCompletionKeyword(contextToken.kind) ||
- isClassMemberCompletionKeywordText(contextToken.getText()))) {
+ isClassMemberCompletionKeywordText(contextToken.getText()))) {
return contextToken.parent.parent as ClassLikeDeclaration;
}
}
@@ -1213,7 +1215,7 @@ namespace ts.Completions {
if (isFromClassElementDeclaration(contextToken)) {
return false;
}
- // falls through
+ // falls through
case SyntaxKind.ClassKeyword:
case SyntaxKind.EnumKeyword:
case SyntaxKind.InterfaceKeyword:
diff --git a/tests/cases/fourslash/jsxQualifiedTagCompletion.ts b/tests/cases/fourslash/jsxQualifiedTagCompletion.ts
new file mode 100644
index 00000000000..3d799324e7e
--- /dev/null
+++ b/tests/cases/fourslash/jsxQualifiedTagCompletion.ts
@@ -0,0 +1,15 @@
+///
+
+//@Filename: file.tsx
+//// declare var React: any;
+//// namespace NS {
+//// export var Foo: any = null;
+//// }
+//// const j = Hello!/**/
+////
+
+goTo.marker();
+edit.insert("");
+verify.completionListContains("NS.Foo");
+verify.not.completionListContains("Foo");
+verify.completionListCount(1);