diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts
index 8e411e1be757e..15c7f9a17fce8 100644
--- a/src/services/codefixes/importFixes.ts
+++ b/src/services/codefixes/importFixes.ts
@@ -491,12 +491,7 @@ namespace ts.codefix {
function getFixesInfoForNonUMDImport({ sourceFile, program, cancellationToken, host, preferences }: CodeFixContextBase, symbolToken: Identifier, useAutoImportProvider: boolean): FixesInfo | undefined {
const checker = program.getTypeChecker();
- // If we're at ``, we must check if `Foo` is already in scope, and if so, get an import for `React` instead.
- const symbolName = isJsxOpeningLikeElement(symbolToken.parent)
- && symbolToken.parent.tagName === symbolToken
- && (isIntrinsicJsxName(symbolToken.text) || checker.resolveName(symbolToken.text, symbolToken, SymbolFlags.All, /*excludeGlobals*/ false))
- ? checker.getJsxNamespace(sourceFile)
- : symbolToken.text;
+ const symbolName = getSymbolName(sourceFile, checker, symbolToken);
// "default" is a keyword and not a legal identifier for the import, so we don't expect it here
Debug.assert(symbolName !== InternalSymbolName.Default, "'default' isn't a legal identifier and couldn't occur here");
@@ -509,6 +504,17 @@ namespace ts.codefix {
return { fixes, symbolName };
}
+ function getSymbolName(sourceFile: SourceFile, checker: TypeChecker, symbolToken: Identifier): string {
+ const parent = symbolToken.parent;
+ if ((isJsxOpeningLikeElement(parent) || isJsxClosingElement(parent)) && parent.tagName === symbolToken) {
+ const jsxNamespace = checker.getJsxNamespace(sourceFile);
+ if (isIntrinsicJsxName(symbolToken.text) || !checker.resolveName(jsxNamespace, parent, SymbolFlags.Value, /*excludeGlobals*/ true)) {
+ return jsxNamespace;
+ }
+ }
+ return symbolToken.text;
+ }
+
// Returns a map from an exported symbol's ID to a list of every way it's (re-)exported.
function getExportInfos(
symbolName: string,
diff --git a/tests/cases/fourslash/importNameCodeFix_jsx.ts b/tests/cases/fourslash/importNameCodeFix_jsx1.ts
similarity index 100%
rename from tests/cases/fourslash/importNameCodeFix_jsx.ts
rename to tests/cases/fourslash/importNameCodeFix_jsx1.ts
diff --git a/tests/cases/fourslash/importNameCodeFix_jsx2.ts b/tests/cases/fourslash/importNameCodeFix_jsx2.ts
new file mode 100644
index 0000000000000..f740876ed7ec3
--- /dev/null
+++ b/tests/cases/fourslash/importNameCodeFix_jsx2.ts
@@ -0,0 +1,31 @@
+///
+
+// @jsx: react
+// @module: esnext
+// @esModuleInterop: true
+// @moduleResolution: node
+
+// @Filename: /node_modules/react/index.d.ts
+////export = React;
+////export as namespace React;
+////declare namespace React {
+//// class Component {}
+////}
+
+// @Filename: /node_modules/react-native/index.d.ts
+////import * as React from "react";
+////export class Text extends React.Component {};
+
+// @Filename: /a.tsx
+////import React from "react";
+////<[|Text|]>;
+
+goTo.file("/a.tsx");
+verify.codeFix({
+ index: 0,
+ description: [ts.Diagnostics.Import_0_from_module_1.message, "Text", "react-native"],
+ newFileContent:
+`import React from "react";
+import { Text } from "react-native";
+;`
+});
diff --git a/tests/cases/fourslash/importNameCodeFix_jsx3.ts b/tests/cases/fourslash/importNameCodeFix_jsx3.ts
new file mode 100644
index 0000000000000..f889076734823
--- /dev/null
+++ b/tests/cases/fourslash/importNameCodeFix_jsx3.ts
@@ -0,0 +1,31 @@
+///
+
+// @jsx: react
+// @module: esnext
+// @esModuleInterop: true
+// @moduleResolution: node
+
+// @Filename: /node_modules/react/index.d.ts
+////export = React;
+////export as namespace React;
+////declare namespace React {
+//// class Component {}
+////}
+
+// @Filename: /node_modules/react-native/index.d.ts
+////import * as React from "react";
+////export class Text extends React.Component {};
+
+// @Filename: /a.tsx
+////import React from "react";
+////[|Text|]>;
+
+goTo.file("/a.tsx");
+verify.codeFix({
+ index: 0,
+ description: [ts.Diagnostics.Import_0_from_module_1.message, "Text", "react-native"],
+ newFileContent:
+`import React from "react";
+import { Text } from "react-native";
+;`
+});
diff --git a/tests/cases/fourslash/importNameCodeFix_jsx4.ts b/tests/cases/fourslash/importNameCodeFix_jsx4.ts
new file mode 100644
index 0000000000000..2303336d83cb2
--- /dev/null
+++ b/tests/cases/fourslash/importNameCodeFix_jsx4.ts
@@ -0,0 +1,31 @@
+///
+
+// @jsx: react
+// @module: esnext
+// @esModuleInterop: true
+// @moduleResolution: node
+
+// @Filename: /node_modules/react/index.d.ts
+////export = React;
+////export as namespace React;
+////declare namespace React {
+//// class Component {}
+////}
+
+// @Filename: /node_modules/react-native/index.d.ts
+////import * as React from "react";
+////export class Text extends React.Component {};
+
+// @Filename: /a.tsx
+////import { Text } from "react-native";
+////;
+
+goTo.file("/a.tsx");
+verify.codeFix({
+ index: 0,
+ description: [ts.Diagnostics.Import_default_0_from_module_1.message, "React", "react"],
+ newFileContent:
+`import React from "react";
+import { Text } from "react-native";
+;`
+});
diff --git a/tests/cases/fourslash/importNameCodeFix_jsx5.ts b/tests/cases/fourslash/importNameCodeFix_jsx5.ts
new file mode 100644
index 0000000000000..510175f375f82
--- /dev/null
+++ b/tests/cases/fourslash/importNameCodeFix_jsx5.ts
@@ -0,0 +1,31 @@
+///
+
+// @jsx: react
+// @module: esnext
+// @esModuleInterop: true
+// @moduleResolution: node
+
+// @Filename: /node_modules/react/index.d.ts
+////export = React;
+////export as namespace React;
+////declare namespace React {
+//// class Component {}
+////}
+
+// @Filename: /node_modules/react-native/index.d.ts
+////import * as React from "react";
+////export class Text extends React.Component {};
+
+// @Filename: /a.tsx
+////import React from "react";
+////<[|Text|] />;
+
+goTo.file("/a.tsx");
+verify.codeFix({
+ index: 0,
+ description: [ts.Diagnostics.Import_0_from_module_1.message, "Text", "react-native"],
+ newFileContent:
+`import React from "react";
+import { Text } from "react-native";
+;`
+});
diff --git a/tests/cases/fourslash/importNameCodeFix_jsx6.ts b/tests/cases/fourslash/importNameCodeFix_jsx6.ts
new file mode 100644
index 0000000000000..d98117fae67cf
--- /dev/null
+++ b/tests/cases/fourslash/importNameCodeFix_jsx6.ts
@@ -0,0 +1,41 @@
+///
+
+// @jsx: react
+// @module: esnext
+// @esModuleInterop: true
+// @moduleResolution: node
+
+// @Filename: /node_modules/react/index.d.ts
+////export = React;
+////export as namespace React;
+////declare namespace React {
+//// class Component {}
+////}
+
+// @Filename: /node_modules/react-native/index.d.ts
+////import * as React from "react";
+////export class Text extends React.Component {};
+
+// @Filename: /a.tsx
+////<[|Text|]>;
+
+goTo.file("/a.tsx");
+verify.codeFix({
+ index: 0,
+ description: [ts.Diagnostics.Import_default_0_from_module_1.message, "React", "react"],
+ applyChanges: true,
+ newFileContent:
+`import React from "react";
+
+;`
+});
+
+verify.codeFix({
+ index: 0,
+ description: [ts.Diagnostics.Import_0_from_module_1.message, "Text", "react-native"],
+ newFileContent:
+`import React from "react";
+import { Text } from "react-native";
+
+;`
+});
diff --git a/tests/cases/fourslash/importNameCodeFix_jsx7.ts b/tests/cases/fourslash/importNameCodeFix_jsx7.ts
new file mode 100644
index 0000000000000..545d7db76e798
--- /dev/null
+++ b/tests/cases/fourslash/importNameCodeFix_jsx7.ts
@@ -0,0 +1,15 @@
+///
+
+// @jsx: react
+// @module: esnext
+// @esModuleInterop: true
+// @moduleResolution: node
+
+// @Filename: /node_modules/react/index.d.ts
+////// React was not defined
+
+// @Filename: /a.tsx
+////<[|Text|]>;
+
+goTo.file("/a.tsx");
+verify.not.codeFixAvailable();