Skip to content

Commit a815db3

Browse files
authoredApr 5, 2023
Support TypeScript 5 (#712)
1 parent 58225b7 commit a815db3

File tree

10 files changed

+111
-60
lines changed

10 files changed

+111
-60
lines changed
 

Diff for: ‎.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@ test/fixtures/project/node_modules/.cache
66
test/fixtures/typescript/extends-module/node_modules/.cache
77
!test/fixtures/typescript/extends-tsconfig-bases/node_modules
88
test/fixtures/typescript/extends-tsconfig-bases/node_modules/.cache
9+
!test/fixtures/typescript/extends-array/node_modules
10+
test/fixtures/typescript/extends-array/node_modules/.cache
911
.nyc_output
1012
coverage

Diff for: ‎lib/options-manager.js

+11-58
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import {existsSync, promises as fs} from 'node:fs';
22
import process from 'node:process';
33
import os from 'node:os';
44
import path from 'node:path';
5-
import {createRequire} from 'node:module';
65
import arrify from 'arrify';
76
import {mergeWith, flow, pick} from 'lodash-es';
87
import {findUpSync} from 'find-up';
@@ -11,12 +10,12 @@ import prettier from 'prettier';
1110
import semver from 'semver';
1211
import {cosmiconfig, defaultLoaders} from 'cosmiconfig';
1312
import micromatch from 'micromatch';
14-
import JSON5 from 'json5';
1513
import stringify from 'json-stable-stringify-without-jsonify';
1614
import {Legacy} from '@eslint/eslintrc';
1715
import createEsmUtils from 'esm-utils';
1816
import MurmurHash3 from 'imurmurhash';
1917
import slash from 'slash';
18+
import {getTsconfig} from 'get-tsconfig';
2019
import {
2120
DEFAULT_IGNORES,
2221
DEFAULT_EXTENSION,
@@ -159,26 +158,20 @@ const handleTSConfig = async options => {
159158
options.tsConfig = {};
160159
options.tsConfigPath = '';
161160

162-
const {project: tsConfigProjectPath, tsconfigRootDir} = options.parserOptions || {};
161+
const {project: tsConfigProjectPath} = options.parserOptions || {};
163162

164163
if (tsConfigProjectPath) {
165164
options.tsConfigPath = path.resolve(options.cwd, tsConfigProjectPath);
166-
options.tsConfig = JSON5.parse(await fs.readFile(options.tsConfigPath));
165+
options.tsConfig = tsConfigResolvePaths(getTsconfig(options.tsConfigPath).config, options.tsConfigPath);
167166
} else {
168-
const tsConfigExplorer = cosmiconfig([], {
169-
searchPlaces: ['tsconfig.json'],
170-
loaders: {'.json': (_, content) => JSON5.parse(content)},
171-
stopDir: tsconfigRootDir,
172-
});
173-
const searchResults = (await tsConfigExplorer.search(options.filePath)) || {};
174-
options.tsConfigPath = searchResults.filepath;
175-
options.tsConfig = searchResults.config;
176-
}
177-
178-
if (options.tsConfig) {
179-
// If the tsconfig extends from another file, we need to ensure that the file is covered by the tsconfig
180-
// or not. The basefile could have includes/excludes/files properties that should be applied to the final tsconfig representation.
181-
options.tsConfig = await recursiveBuildTsConfig(options.tsConfig, options.tsConfigPath);
167+
const {config: tsConfig, path: filepath} = getTsconfig(options.filePath) || {};
168+
options.tsConfigPath = filepath;
169+
options.tsConfig = tsConfig;
170+
if (options.tsConfigPath) {
171+
options.tsConfig = tsConfigResolvePaths(tsConfig, options.tsConfigPath);
172+
} else {
173+
delete options.tsConfig;
174+
}
182175
}
183176

184177
let hasMatch;
@@ -637,46 +630,6 @@ const getOptionGroups = async (files, options) => {
637630
return optionGroups;
638631
};
639632

640-
async function recursiveBuildTsConfig(tsConfig, tsConfigPath) {
641-
tsConfig = tsConfigResolvePaths(tsConfig, tsConfigPath);
642-
643-
if (!tsConfig.extends || (typeof tsConfig.extends === 'string' && tsConfig.extends.includes('node_modules'))) {
644-
return tsConfig;
645-
}
646-
647-
// If any of the following are missing, then we need to look up the base config as it could apply
648-
const require = createRequire(tsConfigPath);
649-
650-
let basePath;
651-
try {
652-
basePath = require.resolve(tsConfig.extends);
653-
} catch (error) {
654-
// Tsconfig resolution is odd, It allows behavior that is not exactly like node resolution
655-
// therefore we attempt to smooth this out here with this hack
656-
try {
657-
basePath = require.resolve(path.join(tsConfig.extends, 'tsconfig.json'));
658-
} catch {
659-
// Throw the orginal resolution error to let the user know their extends block is invalid
660-
throw error;
661-
}
662-
}
663-
664-
const baseTsConfig = JSON5.parse(await fs.readFile(basePath));
665-
666-
delete tsConfig.extends;
667-
668-
tsConfig = {
669-
compilerOptions: {
670-
...baseTsConfig.compilerOptions,
671-
...tsConfig.compilerOptions,
672-
},
673-
...baseTsConfig,
674-
...tsConfig,
675-
};
676-
677-
return recursiveBuildTsConfig(tsConfig, basePath);
678-
}
679-
680633
// Convert all include, files, and exclude to absolute paths
681634
// and or globs. This works because ts only allows simple glob subset
682635
const tsConfigResolvePaths = (tsConfig, tsConfigPath) => {

Diff for: ‎package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@
8181
"find-cache-dir": "^4.0.0",
8282
"find-up": "^6.3.0",
8383
"get-stdin": "^9.0.0",
84+
"get-tsconfig": "^4.5.0",
8485
"globby": "^13.1.2",
8586
"imurmurhash": "^0.1.4",
8687
"json-stable-stringify-without-jsonify": "^1.0.1",
87-
"json5": "^2.2.1",
8888
"lodash-es": "^4.17.21",
8989
"meow": "^11.0.0",
9090
"micromatch": "^4.0.5",
@@ -93,7 +93,7 @@
9393
"semver": "^7.3.8",
9494
"slash": "^5.0.0",
9595
"to-absolute-glob": "^2.0.2",
96-
"typescript": "^4.9.3"
96+
"typescript": "^5.0.3"
9797
},
9898
"devDependencies": {
9999
"ava": "^5.1.0",

Diff for: ‎test/fixtures/typescript/extends-array/node_modules/@sindresorhus/tsconfig/package.json

+26
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎test/fixtures/typescript/extends-array/node_modules/@sindresorhus/tsconfig/tsconfig.json

+35
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎test/fixtures/typescript/extends-array/node_modules/@tsconfig/node16/package.json

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎test/fixtures/typescript/extends-array/node_modules/@tsconfig/node16/tsconfig.json

+16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎test/fixtures/typescript/extends-array/package.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"xo": {}
3+
}

Diff for: ‎test/fixtures/typescript/extends-array/tsconfig.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"extends": [
3+
"@sindresorhus/tsconfig",
4+
"@tsconfig/node16"
5+
],
6+
}

Diff for: ‎test/options-manager.js

+9
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,15 @@ test('mergeWithFileConfig: tsconfig can properly extend tsconfig base node_modul
691691
t.is(options.tsConfigPath, expectedConfigPath);
692692
});
693693

694+
test('mergeWithFileConfig: tsconfig can properly resolve extends arrays introduced in ts 5', async t => {
695+
const cwd = path.resolve('fixtures', 'typescript', 'extends-array');
696+
const expectedConfigPath = path.join(cwd, 'tsconfig.json');
697+
const filePath = path.resolve(cwd, 'does-not-matter.ts');
698+
await t.notThrowsAsync(manager.mergeWithFileConfig({cwd, filePath}));
699+
const {options} = await manager.mergeWithFileConfig({cwd, filePath});
700+
t.is(options.tsConfigPath, expectedConfigPath);
701+
});
702+
694703
test('applyOverrides', t => {
695704
t.deepEqual(
696705
manager.applyOverrides(

0 commit comments

Comments
 (0)
Please sign in to comment.