Skip to content

Commit

Permalink
feat: Add "tsconfigPath" option to ts ext mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
scagood committed Sep 10, 2023
1 parent 1cf4877 commit 4ae382d
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 15 deletions.
4 changes: 4 additions & 0 deletions docs/rules/no-missing-import.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ Default is:
]
```

#### tsconfigPath

Adds the ability to specify the tsconfig used by the typescriptExtensionMap tool.

### Shared Settings

The following options can be set by [shared settings](http://eslint.org/docs/user-guide/configuring.html#adding-shared-settings).
Expand Down
4 changes: 4 additions & 0 deletions docs/rules/no-missing-require.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ Default is:
]
```

#### tsconfigPath

Adds the ability to specify the tsconfig used by the typescriptExtensionMap tool.

### Shared Settings

The following options can be set by [shared settings](http://eslint.org/docs/user-guide/configuring.html#adding-shared-settings).
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/no-missing-import.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
const { checkExistence, messages } = require("../util/check-existence")
const getAllowModules = require("../util/get-allow-modules")
const getResolvePaths = require("../util/get-resolve-paths")
const getTSConfig = require("../util/get-tsconfig")
const getTypescriptExtensionMap = require("../util/get-typescript-extension-map")
const visitImport = require("../util/visit-import")

Expand All @@ -28,6 +29,7 @@ module.exports = {
allowModules: getAllowModules.schema,
resolvePaths: getResolvePaths.schema,
typescriptExtensionMap: getTypescriptExtensionMap.schema,
tsconfigPath: getTSConfig.schema,
},
additionalProperties: false,
},
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/no-missing-require.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
const { checkExistence, messages } = require("../util/check-existence")
const getAllowModules = require("../util/get-allow-modules")
const getResolvePaths = require("../util/get-resolve-paths")
const getTSConfig = require("../util/get-tsconfig")
const getTryExtensions = require("../util/get-try-extensions")
const getTypescriptExtensionMap = require("../util/get-typescript-extension-map")
const visitRequire = require("../util/visit-require")
Expand All @@ -30,6 +31,7 @@ module.exports = {
tryExtensions: getTryExtensions.schema,
resolvePaths: getResolvePaths.schema,
typescriptExtensionMap: getTypescriptExtensionMap.schema,
tsconfigPath: getTSConfig.schema,
},
additionalProperties: false,
},
Expand Down
31 changes: 31 additions & 0 deletions lib/util/get-tsconfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"use strict"

const { getTsconfig, parseTsconfig } = require("get-tsconfig")
const fsCache = new Map()

/**
* Attempts to get the ExtensionMap from the tsconfig given the path to the tsconfig file.
*
* @param {string} filename - The path to the tsconfig.json file
* @returns {import("get-tsconfig").TsConfigJsonResolved}
*/
function getTSConfig(filename) {
return parseTsconfig(filename, fsCache)
}

/**
* Attempts to get the ExtensionMap from the tsconfig of a given file.
*
* @param {string} filename - The path to the file we need to find the tsconfig.json of
* @returns {import("get-tsconfig").TsConfigResult}
*/
function getTSConfigForFile(filename) {
return getTsconfig(filename, "tsconfig.json", fsCache)
}

module.exports = {
getTSConfig,
getTSConfigForFile,
}

module.exports.schema = { type: "string" }
45 changes: 32 additions & 13 deletions lib/util/get-typescript-extension-map.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use strict"

const { getTsconfig } = require("get-tsconfig")
const fsCache = new Map()
const { getTSConfig, getTSConfigForFile } = require("./get-tsconfig")

const DEFAULT_MAPPING = normalise([
["", ".js"],
Expand Down Expand Up @@ -47,6 +46,22 @@ function normalise(typescriptExtensionMap) {
return { forward, backward }
}

/**
* Attempts to get the ExtensionMap from the resolved tsconfig.
*
* @param {import("get-tsconfig").TsConfigJsonResolved} [tsconfig] - The resolved tsconfig
* @returns {ExtensionMap} The `typescriptExtensionMap` value, or `null`.
*/
function getMappingFromTSConfig(tsconfig) {
const jsx = tsconfig?.compilerOptions?.jsx

if ({}.hasOwnProperty.call(tsConfigMapping, jsx)) {
return tsConfigMapping[jsx]
}

return null
}

/**
* Gets `typescriptExtensionMap` property from a given option object.
*
Expand All @@ -64,6 +79,10 @@ function get(option) {
return normalise(option.typescriptExtensionMap)
}

if (option?.tsconfigPath) {
return getMappingFromTSConfig(getTSConfig(option?.tsconfigPath))
}

return null
}

Expand All @@ -73,15 +92,8 @@ function get(option) {
* @param {string} filename - The filename we're getting from
* @returns {ExtensionMap} The `typescriptExtensionMap` value, or `null`.
*/
function getFromTSConfig(filename) {
const tsconfig = getTsconfig(filename, "tsconfig.json", fsCache)

const jsx = tsconfig?.config?.compilerOptions?.jsx
if ({}.hasOwnProperty.call(tsConfigMapping, jsx)) {
return tsConfigMapping[jsx]
}

return null
function getFromTSConfigFromFile(filename) {
return getMappingFromTSConfig(getTSConfigForFile(filename)?.config)
}

/**
Expand All @@ -103,8 +115,15 @@ module.exports = function getTypescriptExtensionMap(context) {
return (
get(context.options?.[0]) ||
get(context.settings?.n ?? context.settings?.node) ||
getFromTSConfig(
context.physicalFilename ?? context.getPhysicalFilename()
getFromTSConfigFromFile(
// eslint ^8
context.physicalFilename ??
// eslint ^7.28 (deprecated ^8)
context.getPhysicalFilename?.() ??
// eslint ^8 (if physicalFilename undefined)
context.filename ??
// eslint ^7 (deprecated ^8)
context.getFilename?.()
) ||
PRESERVE_MAPPING
)
Expand Down
36 changes: 35 additions & 1 deletion tests/lib/rules/no-missing-import.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,41 @@ ruleTester.run("no-missing-import", rule, {
env: { node: true },
},

// tsx from config
// explicit tsx from config
{
// name: "options[0] - preserve - e.tsx as e.jsx",
filename: fixture("ts-react/test.tsx"),
code: "import e from './e.jsx';",
options: [{ tsconfigPath: fixture("ts-preserve/tsconfig.json") }],
env: { node: true },
},
{
// name: "options[0] - react - e.tsx as e.js",
filename: fixture("ts-preserve/test.tsx"),
code: "import e from './e.js';",
options: [{ tsconfigPath: fixture("ts-react/tsconfig.json") }],
env: { node: true },
},
{
// name: "settings.node - preserve - e.tsx as e.jsx",
filename: fixture("ts-react/test.tsx"),
code: "import e from './e.jsx';",
settings: {
node: { tsconfigPath: fixture("ts-preserve/tsconfig.json") },
},
env: { node: true },
},
{
// name: "settings.node - react - e.tsx as e.js",
filename: fixture("ts-preserve/test.tsx"),
code: "import e from './e.js';",
settings: {
node: { tsconfigPath: fixture("ts-react/tsconfig.json") },
},
env: { node: true },
},

// implicit tsx from config
{
// name: "tsconfig - jsx: react - e.tsx as e.js",
filename: fixture("ts-react/test.tsx"),
Expand Down
36 changes: 35 additions & 1 deletion tests/lib/rules/no-missing-require.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,41 @@ ruleTester.run("no-missing-require", rule, {
env: { node: true },
},

// tsx from config
// explicit tsx from config
{
// name: "options[0] - preserve - e.tsx as e.jsx",
filename: fixture("ts-react/test.tsx"),
code: "require('./e.jsx');",
options: [{ tsconfigPath: fixture("ts-preserve/tsconfig.json") }],
env: { node: true },
},
{
// name: "options[0] - react - e.tsx as e.js",
filename: fixture("ts-preserve/test.tsx"),
code: "require('./e.js');",
options: [{ tsconfigPath: fixture("ts-react/tsconfig.json") }],
env: { node: true },
},
{
// name: "settings.node - preserve - e.tsx as e.jsx",
filename: fixture("ts-react/test.tsx"),
code: "require('./e.jsx');",
settings: {
node: { tsconfigPath: fixture("ts-preserve/tsconfig.json") },
},
env: { node: true },
},
{
// name: "settings.node - react - e.tsx as e.js",
filename: fixture("ts-preserve/test.tsx"),
code: "require('./e.js');",
settings: {
node: { tsconfigPath: fixture("ts-react/tsconfig.json") },
},
env: { node: true },
},

// implicit tsx from config
{
filename: fixture("ts-react/test.tsx"),
code: "require('./e.js');",
Expand Down

0 comments on commit 4ae382d

Please sign in to comment.