diff --git a/src/harness/unittests/organizeImports.ts b/src/harness/unittests/organizeImports.ts index 94f99856777e7..9dea2d0d51e85 100644 --- a/src/harness/unittests/organizeImports.ts +++ b/src/harness/unittests/organizeImports.ts @@ -506,7 +506,29 @@ D(); }, libFile); - testOrganizeImports("JsxFactoryUsed", + testOrganizeImports("JsxFactoryUsedJsx", + { + path: "/test.jsx", + content: ` +import { React, Other } from "react"; + +
; +`, + }, + reactLibFile); + + testOrganizeImports("JsxFactoryUsedJs", + { + path: "/test.js", + content: ` +import { React, Other } from "react"; + +
; +`, + }, + reactLibFile); + + testOrganizeImports("JsxFactoryUsedTsx", { path: "/test.tsx", content: ` @@ -517,7 +539,39 @@ import { React, Other } from "react"; }, reactLibFile); - // This is descriptive, rather than normative + // TS files are not JSX contexts, so the parser does not treat + // `
` as a JSX element. + testOrganizeImports("JsxFactoryUsedTs", + { + path: "/test.ts", + content: ` +import { React, Other } from "react"; + +
; +`, + }, + reactLibFile); + + testOrganizeImports("JsxFactoryUnusedJsx", + { + path: "/test.jsx", + content: ` +import { React, Other } from "react"; +`, + }, + reactLibFile); + + // Note: Since the file extension does not end with "x", the jsx compiler option + // will not be enabled. The import should be retained regardless. + testOrganizeImports("JsxFactoryUnusedJs", + { + path: "/test.js", + content: ` +import { React, Other } from "react"; +`, + }, + reactLibFile); + testOrganizeImports("JsxFactoryUnusedTsx", { path: "/test.tsx", diff --git a/src/services/organizeImports.ts b/src/services/organizeImports.ts index 99bac64973f80..225e9fae57d76 100644 --- a/src/services/organizeImports.ts +++ b/src/services/organizeImports.ts @@ -92,7 +92,7 @@ namespace ts.OrganizeImports { function removeUnusedImports(oldImports: ReadonlyArray, sourceFile: SourceFile, program: Program) { const typeChecker = program.getTypeChecker(); const jsxNamespace = typeChecker.getJsxNamespace(); - const jsxContext = sourceFile.languageVariant === LanguageVariant.JSX && program.getCompilerOptions().jsx; + const jsxElementsPresent = !!(sourceFile.transformFlags & TransformFlags.ContainsJsx); const usedImports: ImportDeclaration[] = []; @@ -138,8 +138,8 @@ namespace ts.OrganizeImports { return usedImports; function isDeclarationUsed(identifier: Identifier) { - // The JSX factory symbol is always used. - return jsxContext && (identifier.text === jsxNamespace) || FindAllReferences.Core.isSymbolReferencedInFile(identifier, typeChecker, sourceFile); + // The JSX factory symbol is always used if JSX elements are present - even if they are not allowed. + return jsxElementsPresent && (identifier.text === jsxNamespace) || FindAllReferences.Core.isSymbolReferencedInFile(identifier, typeChecker, sourceFile); } } diff --git a/tests/baselines/reference/organizeImports/JsxFactoryUnusedJs.ts b/tests/baselines/reference/organizeImports/JsxFactoryUnusedJs.ts new file mode 100644 index 0000000000000..60afb95a19257 --- /dev/null +++ b/tests/baselines/reference/organizeImports/JsxFactoryUnusedJs.ts @@ -0,0 +1,6 @@ +// ==ORIGINAL== + +import { React, Other } from "react"; + +// ==ORGANIZED== + diff --git a/tests/baselines/reference/organizeImports/JsxFactoryUnusedJsx.ts b/tests/baselines/reference/organizeImports/JsxFactoryUnusedJsx.ts new file mode 100644 index 0000000000000..60afb95a19257 --- /dev/null +++ b/tests/baselines/reference/organizeImports/JsxFactoryUnusedJsx.ts @@ -0,0 +1,6 @@ +// ==ORIGINAL== + +import { React, Other } from "react"; + +// ==ORGANIZED== + diff --git a/tests/baselines/reference/organizeImports/JsxFactoryUnusedTsx.ts b/tests/baselines/reference/organizeImports/JsxFactoryUnusedTsx.ts index 6a97e7f660ae1..60afb95a19257 100644 --- a/tests/baselines/reference/organizeImports/JsxFactoryUnusedTsx.ts +++ b/tests/baselines/reference/organizeImports/JsxFactoryUnusedTsx.ts @@ -4,4 +4,3 @@ import { React, Other } from "react"; // ==ORGANIZED== -import { React } from "react"; diff --git a/tests/baselines/reference/organizeImports/JsxFactoryUsed.ts b/tests/baselines/reference/organizeImports/JsxFactoryUsedJs.ts similarity index 100% rename from tests/baselines/reference/organizeImports/JsxFactoryUsed.ts rename to tests/baselines/reference/organizeImports/JsxFactoryUsedJs.ts diff --git a/tests/baselines/reference/organizeImports/JsxFactoryUsedJsx.ts b/tests/baselines/reference/organizeImports/JsxFactoryUsedJsx.ts new file mode 100644 index 0000000000000..430a5b12cd4d4 --- /dev/null +++ b/tests/baselines/reference/organizeImports/JsxFactoryUsedJsx.ts @@ -0,0 +1,11 @@ +// ==ORIGINAL== + +import { React, Other } from "react"; + +
; + +// ==ORGANIZED== + +import { React } from "react"; + +
; diff --git a/tests/baselines/reference/organizeImports/JsxFactoryUsedTs.ts b/tests/baselines/reference/organizeImports/JsxFactoryUsedTs.ts new file mode 100644 index 0000000000000..74da2f99139e0 --- /dev/null +++ b/tests/baselines/reference/organizeImports/JsxFactoryUsedTs.ts @@ -0,0 +1,10 @@ +// ==ORIGINAL== + +import { React, Other } from "react"; + +
; + +// ==ORGANIZED== + + +
; diff --git a/tests/baselines/reference/organizeImports/JsxFactoryUsedTsx.ts b/tests/baselines/reference/organizeImports/JsxFactoryUsedTsx.ts new file mode 100644 index 0000000000000..430a5b12cd4d4 --- /dev/null +++ b/tests/baselines/reference/organizeImports/JsxFactoryUsedTsx.ts @@ -0,0 +1,11 @@ +// ==ORIGINAL== + +import { React, Other } from "react"; + +
; + +// ==ORGANIZED== + +import { React } from "react"; + +
;