diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts
index 060d409eaa9e1..757624cee7445 100644
--- a/src/services/codefixes/importFixes.ts
+++ b/src/services/codefixes/importFixes.ts
@@ -485,12 +485,7 @@ namespace ts.codefix {
function getFixesInfoForNonUMDImport({ sourceFile, program, cancellationToken, host, preferences }: CodeFixContextBase, symbolToken: Identifier): 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");
@@ -503,6 +498,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 (!checker.resolveName(jsxNamespace, parent, SymbolFlags.All, /*excludeGlobals*/ false)) {
+ 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..170c405f7b3bb
--- /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: `Import 'Text' from module "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..754f624d14b1f
--- /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: `Import 'Text' from module "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..ab2a423acb02c
--- /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: `Import default 'React' from module "react"`,
+ newFileContent:
+`import { Text } from "react-native";
+import React from "react";
+;`
+});
diff --git a/tests/cases/fourslash/importNameCodeFix_jsx5.ts b/tests/cases/fourslash/importNameCodeFix_jsx5.ts
new file mode 100644
index 0000000000000..be853204c2db0
--- /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: `Import 'Text' from module "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..a2a607e06b13e
--- /dev/null
+++ b/tests/cases/fourslash/importNameCodeFix_jsx6.ts
@@ -0,0 +1,40 @@
+///
+
+// @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,
+ applyChanges: true,
+ description: `Import 'Text' from module "react-native"`,
+ newFileContent:
+`import { Text } from "react-native";
+
+;`
+});
+
+verify.codeFix({
+ description: `Import default 'React' from module "react"`,
+ newFileContent:
+`import { Text } from "react-native";
+import React from "react";
+
+;`
+});