From d5996006fbb94ebe26cb8b641551d9a7cbad6b0f Mon Sep 17 00:00:00 2001 From: Boshen Date: Tue, 18 Nov 2025 22:27:07 +0800 Subject: [PATCH 1/2] feat: port tsconfck (find tsconfig files) --- .gitignore | 1 + Cargo.lock | 16 ++ Cargo.toml | 1 + README.md | 17 +- benches/resolver.rs | 13 ++ fixtures/tsconfck/find/a/.gitignore | 1 + fixtures/tsconfck/find/a/b/bar.ts | 1 + fixtures/tsconfck/find/a/b/c/jsconfig.json | 1 + fixtures/tsconfck/find/a/b/c/x.ts | 0 fixtures/tsconfck/find/a/b/c/y.js | 0 fixtures/tsconfck/find/a/b/qoox.js | 1 + fixtures/tsconfck/find/a/baz.js | 1 + fixtures/tsconfck/find/a/foo.ts | 1 + fixtures/tsconfck/find/a/jsconfig.json | 1 + .../a/node_modules/some-js-lib/jsconfig.json | 1 + .../a/node_modules/some-js-lib/src/foo.js | 0 .../find/a/node_modules/some-lib/src/foo.ts | 0 .../a/node_modules/some-lib/tsconfig.json | 1 + .../find/a/node_modules/tsconfig.json | 0 fixtures/tsconfck/find/a/tsconfig.json | 1 + .../tsconfck/node_modules/@tsconfig/node18 | 1 + .../node_modules/isaacscript-tsconfig | 1 + fixtures/tsconfck/package.json | 6 + .../tsconfck/parse/invalid/bom/tsconfig.json | 3 + .../parse/invalid/comma/tsconfig.json | 7 + .../parse/invalid/comments/tsconfig.json | 16 ++ .../invalid/extends-array-circular/src/foo.ts | 1 + .../extends-array-circular/tsconfig.a.b.json | 6 + .../extends-array-circular/tsconfig.a.json | 8 + .../extends-array-circular/tsconfig.b.json | 7 + .../extends-array-circular/tsconfig.c.json | 5 + .../extends-array-circular/tsconfig.json | 3 + .../deep/tsconfig.circular2.json | 3 + .../extends-circular/tsconfig.circular.json | 3 + .../invalid/extends-circular/tsconfig.json | 8 + .../invalid/extends-not-found/tsconfig.json | 8 + .../parse/invalid/mixed/tsconfig.json | 17 ++ .../parse/invalid/tsconfig.json/.gitkeep | 0 .../solution/jsconfig/jsconfig.base.json | 7 + .../parse/solution/jsconfig/jsconfig.json | 8 + .../parse/solution/jsconfig/jsconfig.src.json | 8 + .../solution/jsconfig/jsconfig.test.json | 7 + .../parse/solution/jsconfig/src/bar.mjs | 3 + .../parse/solution/jsconfig/src/baz.cjs | 4 + .../parse/solution/jsconfig/src/foo.js | 3 + .../parse/solution/jsconfig/src/foo.spec.js | 9 + .../tsconfck/parse/solution/mixed/src/bar.mts | 3 + .../tsconfck/parse/solution/mixed/src/baz.cts | 4 + .../parse/solution/mixed/src/foo.spec.ts | 9 + .../tsconfck/parse/solution/mixed/src/foo.ts | 3 + .../parse/solution/mixed/tsconfig.base.json | 6 + .../parse/solution/mixed/tsconfig.json | 8 + .../parse/solution/mixed/tsconfig.src.json | 8 + .../parse/solution/mixed/tsconfig.test.json | 7 + .../solution/referenced-exclude/src/bar.ts | 0 .../solution/referenced-exclude/src/foo.ts | 0 .../referenced-exclude/tsconfig.bar.json | 3 + .../referenced-exclude/tsconfig.foo.json | 3 + .../solution/referenced-exclude/tsconfig.json | 8 + .../referenced-extends-original/src/foo.ts | 3 + .../src/tsconfig.src.json | 8 + .../tests/foo.test.ts | 9 + .../tests/tsconfig.test.json | 8 + .../referenced-extends-original/tsconfig.json | 6 + .../solution/referenced-files/src/bar.ts | 0 .../solution/referenced-files/src/foo.ts | 0 .../referenced-files/tsconfig.foo.json | 3 + .../solution/referenced-files/tsconfig.json | 6 + .../solution/referenced-include/src/bar.ts | 0 .../solution/referenced-include/src/foo.ts | 0 .../referenced-include/tsconfig.bar.json | 2 + .../referenced-include/tsconfig.foo.json | 3 + .../solution/referenced-include/tsconfig.json | 8 + .../packages/foo/src/foo.ts | 3 + .../packages/foo/tsconfig.foo.json | 3 + .../tsconfig.base.json | 10 ++ .../tsconfig.json | 6 + .../referenced-with-configDir/src/foo.ts | 3 + .../referenced-with-configDir/tsconfig.json | 6 + .../tsconfig.src.json | 10 ++ .../referenced-with-implicit-globs/src/foo.ts | 3 + .../tests/foo.test.ts | 9 + .../tsconfig.json | 7 + .../tsconfig.src.json | 7 + .../tsconfig.test.json | 7 + .../tsconfck/parse/solution/simple/src/foo.ts | 3 + .../parse/solution/simple/src/tsconfig.json | 7 + .../parse/solution/simple/tests/foo.ts | 9 + .../parse/solution/simple/tests/tsconfig.json | 6 + .../parse/solution/simple/tsconfig.base.json | 6 + .../parse/solution/simple/tsconfig.json | 8 + .../tsconfck/parse/valid/bom/tsconfig.json | 5 + .../tsconfck/parse/valid/comma/tsconfig.json | 5 + .../parse/valid/comments/tsconfig.json | 15 ++ .../parse/valid/configDir/a/src/foo.ts | 3 + .../parse/valid/configDir/a/tsconfig.json | 3 + .../parse/valid/configDir/b/src/foo.ts | 3 + .../parse/valid/configDir/b/tsconfig.json | 3 + .../tsconfck/parse/valid/configDir/src/foo.ts | 3 + .../parse/valid/configDir/tsconfig.base.json | 11 ++ .../parse/valid/configDirNpm/tsconfig.json | 9 + .../tsconfck/parse/valid/empty/jsconfig.json | 0 .../tsconfck/parse/valid/empty/tsconfig.json | 0 .../tsconfck/parse/valid/lib/tsconfig.json | 8 + .../tsconfck/parse/valid/mixed/tsconfig.json | 16 ++ .../moduleResolution/bundler/tsconfig.json | 16 ++ .../moduleResolution/classic/tsconfig.json | 16 ++ .../moduleResolution/node16/tsconfig.json | 16 ++ .../moduleResolution/nodenext/tsconfig.json | 16 ++ .../parse/valid/regular/tsconfig.json | 16 ++ .../parse/valid/ts_node/tsconfig.json | 12 ++ .../parse/valid/with_extends/array/src/foo.ts | 1 + .../with_extends/array/tsconfig.a.b.json | 6 + .../valid/with_extends/array/tsconfig.a.json | 8 + .../valid/with_extends/array/tsconfig.b.json | 7 + .../valid/with_extends/array/tsconfig.c.json | 5 + .../valid/with_extends/array/tsconfig.json | 3 + .../parse/valid/with_extends/dot/main.js | 3 + .../parse/valid/with_extends/dot/package.json | 8 + .../parse/valid/with_extends/dot/src/foo.ts | 0 .../with_extends/dot/tsconfig.eslint.json | 3 + .../valid/with_extends/dot/tsconfig.json | 3 + .../parse/valid/with_extends/dotdot/main.js | 3 + .../valid/with_extends/dotdot/package.json | 8 + .../valid/with_extends/dotdot/src/foo.ts | 0 .../with_extends/dotdot/src/tsconfig.json | 3 + .../valid/with_extends/dotdot/tsconfig.json | 4 + .../valid/with_extends/nested/src/foo.ts | 0 .../with_extends/nested/src/nested/bar.ts | 0 .../nested/src/nested/tsconfig.json | 6 + .../with_extends/nested/src/tsconfig.json | 3 + .../valid/with_extends/nested/tsconfig.json | 4 + .../no_compileroptions/tsconfig.json | 4 + .../valid/with_extends/node/tsconfig.json | 8 + .../with_extends/node_fallback/tsconfig.json | 8 + .../parse/valid/with_extends/paths/lib/foo.ts | 1 + .../with_extends/paths/src/import-foo.ts | 2 + .../with_extends/paths/src/tsconfig.json | 7 + .../with_extends/paths/tsconfig.base.json | 11 ++ .../valid/with_extends/simple/tsconfig.json | 8 + .../valid/with_extends/tsconfig.parent.json | 18 ++ .../without_json_extension/tsconfig.json | 8 + package.json | 1 + pnpm-lock.yaml | 49 ++++++ pnpm-workspace.yaml | 1 + src/tests/mod.rs | 1 + src/tests/tsconfck.rs | 108 ++++++++++++ src/tests/tsconfig_extends.rs | 6 +- src/tsconfig.rs | 162 +++++++++++++++--- src/tsconfig_resolver.rs | 110 +++++++----- 150 files changed, 1138 insertions(+), 70 deletions(-) create mode 100644 fixtures/tsconfck/find/a/.gitignore create mode 100644 fixtures/tsconfck/find/a/b/bar.ts create mode 100644 fixtures/tsconfck/find/a/b/c/jsconfig.json create mode 100644 fixtures/tsconfck/find/a/b/c/x.ts create mode 100644 fixtures/tsconfck/find/a/b/c/y.js create mode 100644 fixtures/tsconfck/find/a/b/qoox.js create mode 100644 fixtures/tsconfck/find/a/baz.js create mode 100644 fixtures/tsconfck/find/a/foo.ts create mode 100644 fixtures/tsconfck/find/a/jsconfig.json create mode 100644 fixtures/tsconfck/find/a/node_modules/some-js-lib/jsconfig.json create mode 100644 fixtures/tsconfck/find/a/node_modules/some-js-lib/src/foo.js create mode 100644 fixtures/tsconfck/find/a/node_modules/some-lib/src/foo.ts create mode 100644 fixtures/tsconfck/find/a/node_modules/some-lib/tsconfig.json create mode 100644 fixtures/tsconfck/find/a/node_modules/tsconfig.json create mode 100644 fixtures/tsconfck/find/a/tsconfig.json create mode 120000 fixtures/tsconfck/node_modules/@tsconfig/node18 create mode 120000 fixtures/tsconfck/node_modules/isaacscript-tsconfig create mode 100644 fixtures/tsconfck/package.json create mode 100644 fixtures/tsconfck/parse/invalid/bom/tsconfig.json create mode 100644 fixtures/tsconfck/parse/invalid/comma/tsconfig.json create mode 100644 fixtures/tsconfck/parse/invalid/comments/tsconfig.json create mode 100644 fixtures/tsconfck/parse/invalid/extends-array-circular/src/foo.ts create mode 100644 fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.a.b.json create mode 100644 fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.a.json create mode 100644 fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.b.json create mode 100644 fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.c.json create mode 100644 fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.json create mode 100644 fixtures/tsconfck/parse/invalid/extends-circular/deep/tsconfig.circular2.json create mode 100644 fixtures/tsconfck/parse/invalid/extends-circular/tsconfig.circular.json create mode 100644 fixtures/tsconfck/parse/invalid/extends-circular/tsconfig.json create mode 100644 fixtures/tsconfck/parse/invalid/extends-not-found/tsconfig.json create mode 100644 fixtures/tsconfck/parse/invalid/mixed/tsconfig.json create mode 100644 fixtures/tsconfck/parse/invalid/tsconfig.json/.gitkeep create mode 100644 fixtures/tsconfck/parse/solution/jsconfig/jsconfig.base.json create mode 100644 fixtures/tsconfck/parse/solution/jsconfig/jsconfig.json create mode 100644 fixtures/tsconfck/parse/solution/jsconfig/jsconfig.src.json create mode 100644 fixtures/tsconfck/parse/solution/jsconfig/jsconfig.test.json create mode 100644 fixtures/tsconfck/parse/solution/jsconfig/src/bar.mjs create mode 100644 fixtures/tsconfck/parse/solution/jsconfig/src/baz.cjs create mode 100644 fixtures/tsconfck/parse/solution/jsconfig/src/foo.js create mode 100644 fixtures/tsconfck/parse/solution/jsconfig/src/foo.spec.js create mode 100644 fixtures/tsconfck/parse/solution/mixed/src/bar.mts create mode 100644 fixtures/tsconfck/parse/solution/mixed/src/baz.cts create mode 100644 fixtures/tsconfck/parse/solution/mixed/src/foo.spec.ts create mode 100644 fixtures/tsconfck/parse/solution/mixed/src/foo.ts create mode 100644 fixtures/tsconfck/parse/solution/mixed/tsconfig.base.json create mode 100644 fixtures/tsconfck/parse/solution/mixed/tsconfig.json create mode 100644 fixtures/tsconfck/parse/solution/mixed/tsconfig.src.json create mode 100644 fixtures/tsconfck/parse/solution/mixed/tsconfig.test.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-exclude/src/bar.ts create mode 100644 fixtures/tsconfck/parse/solution/referenced-exclude/src/foo.ts create mode 100644 fixtures/tsconfck/parse/solution/referenced-exclude/tsconfig.bar.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-exclude/tsconfig.foo.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-exclude/tsconfig.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-extends-original/src/foo.ts create mode 100644 fixtures/tsconfck/parse/solution/referenced-extends-original/src/tsconfig.src.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-extends-original/tests/foo.test.ts create mode 100644 fixtures/tsconfck/parse/solution/referenced-extends-original/tests/tsconfig.test.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-extends-original/tsconfig.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-files/src/bar.ts create mode 100644 fixtures/tsconfck/parse/solution/referenced-files/src/foo.ts create mode 100644 fixtures/tsconfck/parse/solution/referenced-files/tsconfig.foo.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-files/tsconfig.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-include/src/bar.ts create mode 100644 fixtures/tsconfck/parse/solution/referenced-include/src/foo.ts create mode 100644 fixtures/tsconfck/parse/solution/referenced-include/tsconfig.bar.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-include/tsconfig.foo.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-include/tsconfig.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/packages/foo/src/foo.ts create mode 100644 fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/packages/foo/tsconfig.foo.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/tsconfig.base.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/tsconfig.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-with-configDir/src/foo.ts create mode 100644 fixtures/tsconfck/parse/solution/referenced-with-configDir/tsconfig.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-with-configDir/tsconfig.src.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/src/foo.ts create mode 100644 fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tests/foo.test.ts create mode 100644 fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tsconfig.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tsconfig.src.json create mode 100644 fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tsconfig.test.json create mode 100644 fixtures/tsconfck/parse/solution/simple/src/foo.ts create mode 100644 fixtures/tsconfck/parse/solution/simple/src/tsconfig.json create mode 100644 fixtures/tsconfck/parse/solution/simple/tests/foo.ts create mode 100644 fixtures/tsconfck/parse/solution/simple/tests/tsconfig.json create mode 100644 fixtures/tsconfck/parse/solution/simple/tsconfig.base.json create mode 100644 fixtures/tsconfck/parse/solution/simple/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/bom/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/comma/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/comments/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/configDir/a/src/foo.ts create mode 100644 fixtures/tsconfck/parse/valid/configDir/a/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/configDir/b/src/foo.ts create mode 100644 fixtures/tsconfck/parse/valid/configDir/b/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/configDir/src/foo.ts create mode 100644 fixtures/tsconfck/parse/valid/configDir/tsconfig.base.json create mode 100644 fixtures/tsconfck/parse/valid/configDirNpm/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/empty/jsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/empty/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/lib/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/mixed/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/moduleResolution/bundler/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/moduleResolution/classic/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/moduleResolution/node16/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/moduleResolution/nodenext/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/regular/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/ts_node/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/array/src/foo.ts create mode 100644 fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.a.b.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.a.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.b.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.c.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/dot/main.js create mode 100644 fixtures/tsconfck/parse/valid/with_extends/dot/package.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/dot/src/foo.ts create mode 100644 fixtures/tsconfck/parse/valid/with_extends/dot/tsconfig.eslint.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/dot/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/dotdot/main.js create mode 100644 fixtures/tsconfck/parse/valid/with_extends/dotdot/package.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/dotdot/src/foo.ts create mode 100644 fixtures/tsconfck/parse/valid/with_extends/dotdot/src/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/dotdot/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/nested/src/foo.ts create mode 100644 fixtures/tsconfck/parse/valid/with_extends/nested/src/nested/bar.ts create mode 100644 fixtures/tsconfck/parse/valid/with_extends/nested/src/nested/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/nested/src/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/nested/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/no_compileroptions/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/node/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/node_fallback/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/paths/lib/foo.ts create mode 100644 fixtures/tsconfck/parse/valid/with_extends/paths/src/import-foo.ts create mode 100644 fixtures/tsconfck/parse/valid/with_extends/paths/src/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/paths/tsconfig.base.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/simple/tsconfig.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/tsconfig.parent.json create mode 100644 fixtures/tsconfck/parse/valid/with_extends/without_json_extension/tsconfig.json create mode 100644 src/tests/tsconfck.rs diff --git a/.gitignore b/.gitignore index 76adb0e5..830c58c2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ target/ /napi/node_modules /fixtures/pnpm/node_modules /fixtures/yarn/node_modules +/fixtures/tsconfck/node_modules fuzz/Cargo.lock diff --git a/Cargo.lock b/Cargo.lock index 17d82355..f1be8efb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,6 +44,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "autocfg" version = "1.5.0" @@ -387,6 +393,15 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "fast-glob" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d26eec0ae9682c457cb0f85de67ad417b716ae852736a5d94c2ad6e92a997c9" +dependencies = [ + "arrayvec", +] + [[package]] name = "filetime" version = "0.2.26" @@ -955,6 +970,7 @@ dependencies = [ "dirs", "document-features", "fancy-regex", + "fast-glob", "indexmap", "json-strip-comments", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index 1dfd1881..861b961a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,6 +79,7 @@ name = "resolver" [dependencies] cfg-if = "1" +fast-glob = "1" indexmap = { version = "2", features = ["serde"] } json-strip-comments = "3.1" once_cell = "1" # Use `std::sync::OnceLock::get_or_try_init` when it is stable. diff --git a/README.md b/README.md index 6784a930..82718655 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ # Oxc Resolver -Rust port of [enhanced-resolve]. +Rust port of [enhanced-resolve], [tsconfig-paths-webpack-plugin] and [tsconfck] - Released on [crates.io](https://crates.io/crates/oxc_resolver) and [npm](https://www.npmjs.com/package/oxc-resolver). - Implements the [ESM](https://nodejs.org/api/esm.html#resolution-algorithm) and [CommonJS](https://nodejs.org/api/modules.html#all-together) module resolution algorithm specification. @@ -28,6 +28,7 @@ Rust port of [enhanced-resolve]. - support paths alias defined in `tsconfig.compilerOptions.paths` - support project references defined `tsconfig.references` - support [template variable ${configDir} for substitution of config files directory path](https://github.com/microsoft/TypeScript/pull/58042) +- Built-in tsconfig discovery ([tsconfck]) - Supports in-memory file system via the `FileSystem` trait. - Contains `tracing` instrumentation. @@ -295,12 +296,13 @@ Irrelevant tests Oxc partially copies code from the following projects. -| Project | License | -| ------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | -| [webpack/enhanced-resolve](https://github.com/webpack/enhanced-resolve) | [MIT](https://github.com/webpack/enhanced-resolve/blob/main/LICENSE) | -| [dividab/tsconfig-paths](https://github.com/dividab/tsconfig-paths) | [MIT](https://github.com/dividab/tsconfig-paths/blob/master/LICENSE) | -| [parcel-bundler/parcel](https://github.com/parcel-bundler/parcel) | [MIT](https://github.com/parcel-bundler/parcel/blob/v2/LICENSE) | -| [tmccombs/json-comments-rs](https://github.com/tmccombs/json-comments-rs) | [Apache 2.0](https://github.com/tmccombs/json-comments-rs/blob/main/LICENSE) | +| Project | License | +| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | +| [webpack/enhanced-resolve](https://github.com/webpack/enhanced-resolve) | [MIT](https://github.com/webpack/enhanced-resolve/blob/main/LICENSE) | +| [dividab/tsconfig-paths](https://github.com/dividab/tsconfig-paths) | [MIT](https://github.com/dividab/tsconfig-paths/blob/master/LICENSE) | +| [parcel-bundler/parcel](https://github.com/parcel-bundler/parcel) | [MIT](https://github.com/parcel-bundler/parcel/blob/v2/LICENSE) | +| [tmccombs/json-comments-rs](https://github.com/tmccombs/json-comments-rs) | [Apache 2.0](https://github.com/tmccombs/json-comments-rs/blob/main/LICENSE) | +| [dominikg/tsconfck](https://github.com/dominikg/tsconfck) | [MIT](https://github.com/dominikg/tsconfck/blob/main/packages/tsconfck/LICENSE) | [enhanced-resolve]: https://github.com/webpack/enhanced-resolve [tsconfig-paths-webpack-plugin]: https://github.com/dividab/tsconfig-paths-webpack-plugin @@ -322,3 +324,4 @@ Oxc partially copies code from the following projects. [docs-url]: https://docs.rs/oxc_resolver/latest/oxc_resolver [npm-badge]: https://img.shields.io/npm/dw/oxc-resolver?label=npm [npm-url]: https://www.npmjs.com/package/oxc-resolver +[tsconfck]: https://github.com/dominikg/tsconfck diff --git a/benches/resolver.rs b/benches/resolver.rs index f5aa12e5..e2fe03c9 100644 --- a/benches/resolver.rs +++ b/benches/resolver.rs @@ -224,6 +224,19 @@ fn bench_resolver_memory(c: &mut Criterion) { }); }, ); + + group.bench_with_input(BenchmarkId::from_parameter("find tsconfig"), &data, |b, data| { + let oxc_resolver = oxc_resolver_memory(); + let paths = data + .iter() + .map(|(path, request)| oxc_resolver.resolve(path, request).unwrap().into_path_buf()) + .collect::>(); + b.iter(|| { + for path in &paths { + let _ = oxc_resolver.find_tsconfig(path); + } + }); + }); } fn bench_resolver_real(c: &mut Criterion) { diff --git a/fixtures/tsconfck/find/a/.gitignore b/fixtures/tsconfck/find/a/.gitignore new file mode 100644 index 00000000..cf4bab9d --- /dev/null +++ b/fixtures/tsconfck/find/a/.gitignore @@ -0,0 +1 @@ +!node_modules diff --git a/fixtures/tsconfck/find/a/b/bar.ts b/fixtures/tsconfck/find/a/b/bar.ts new file mode 100644 index 00000000..9f173868 --- /dev/null +++ b/fixtures/tsconfck/find/a/b/bar.ts @@ -0,0 +1 @@ +export const bar = 'bar'; diff --git a/fixtures/tsconfck/find/a/b/c/jsconfig.json b/fixtures/tsconfck/find/a/b/c/jsconfig.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/fixtures/tsconfck/find/a/b/c/jsconfig.json @@ -0,0 +1 @@ +{} diff --git a/fixtures/tsconfck/find/a/b/c/x.ts b/fixtures/tsconfck/find/a/b/c/x.ts new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/find/a/b/c/y.js b/fixtures/tsconfck/find/a/b/c/y.js new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/find/a/b/qoox.js b/fixtures/tsconfck/find/a/b/qoox.js new file mode 100644 index 00000000..a215de81 --- /dev/null +++ b/fixtures/tsconfck/find/a/b/qoox.js @@ -0,0 +1 @@ +export const qoox = "qoox"; diff --git a/fixtures/tsconfck/find/a/baz.js b/fixtures/tsconfck/find/a/baz.js new file mode 100644 index 00000000..6061cf07 --- /dev/null +++ b/fixtures/tsconfck/find/a/baz.js @@ -0,0 +1 @@ +export const baz = 'baz'; diff --git a/fixtures/tsconfck/find/a/foo.ts b/fixtures/tsconfck/find/a/foo.ts new file mode 100644 index 00000000..3329a7d9 --- /dev/null +++ b/fixtures/tsconfck/find/a/foo.ts @@ -0,0 +1 @@ +export const foo = 'foo'; diff --git a/fixtures/tsconfck/find/a/jsconfig.json b/fixtures/tsconfck/find/a/jsconfig.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/fixtures/tsconfck/find/a/jsconfig.json @@ -0,0 +1 @@ +{} diff --git a/fixtures/tsconfck/find/a/node_modules/some-js-lib/jsconfig.json b/fixtures/tsconfck/find/a/node_modules/some-js-lib/jsconfig.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/fixtures/tsconfck/find/a/node_modules/some-js-lib/jsconfig.json @@ -0,0 +1 @@ +{} diff --git a/fixtures/tsconfck/find/a/node_modules/some-js-lib/src/foo.js b/fixtures/tsconfck/find/a/node_modules/some-js-lib/src/foo.js new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/find/a/node_modules/some-lib/src/foo.ts b/fixtures/tsconfck/find/a/node_modules/some-lib/src/foo.ts new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/find/a/node_modules/some-lib/tsconfig.json b/fixtures/tsconfck/find/a/node_modules/some-lib/tsconfig.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/fixtures/tsconfck/find/a/node_modules/some-lib/tsconfig.json @@ -0,0 +1 @@ +{} diff --git a/fixtures/tsconfck/find/a/node_modules/tsconfig.json b/fixtures/tsconfck/find/a/node_modules/tsconfig.json new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/find/a/tsconfig.json b/fixtures/tsconfck/find/a/tsconfig.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/fixtures/tsconfck/find/a/tsconfig.json @@ -0,0 +1 @@ +{} diff --git a/fixtures/tsconfck/node_modules/@tsconfig/node18 b/fixtures/tsconfck/node_modules/@tsconfig/node18 new file mode 120000 index 00000000..a0c7f111 --- /dev/null +++ b/fixtures/tsconfck/node_modules/@tsconfig/node18 @@ -0,0 +1 @@ +../../../../node_modules/.pnpm/@tsconfig+node18@18.2.6/node_modules/@tsconfig/node18 \ No newline at end of file diff --git a/fixtures/tsconfck/node_modules/isaacscript-tsconfig b/fixtures/tsconfck/node_modules/isaacscript-tsconfig new file mode 120000 index 00000000..690f23e0 --- /dev/null +++ b/fixtures/tsconfck/node_modules/isaacscript-tsconfig @@ -0,0 +1 @@ +../../../node_modules/.pnpm/isaacscript-tsconfig@7.0.1/node_modules/isaacscript-tsconfig \ No newline at end of file diff --git a/fixtures/tsconfck/package.json b/fixtures/tsconfck/package.json new file mode 100644 index 00000000..9cd0dd77 --- /dev/null +++ b/fixtures/tsconfck/package.json @@ -0,0 +1,6 @@ +{ + "devDependencies": { + "@tsconfig/node18": "^18.2.4", + "isaacscript-tsconfig": "^7.0.1" + } +} diff --git a/fixtures/tsconfck/parse/invalid/bom/tsconfig.json b/fixtures/tsconfck/parse/invalid/bom/tsconfig.json new file mode 100644 index 00000000..d97ed3d1 --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/bom/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": x"" +} diff --git a/fixtures/tsconfck/parse/invalid/comma/tsconfig.json b/fixtures/tsconfck/parse/invalid/comma/tsconfig.json new file mode 100644 index 00000000..94b1bf40 --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/comma/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "", + "compilerOptions": { + "types": ["foo", ] , + } , x +} + diff --git a/fixtures/tsconfck/parse/invalid/comments/tsconfig.json b/fixtures/tsconfck/parse/invalid/comments/tsconfig.json new file mode 100644 index 00000000..f20ac12f --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/comments/tsconfig.json @@ -0,0 +1,16 @@ +/* +multi +line +*/ +{ + "extends": "", // trailing single line comment + "compilerOptions": { + "types": /* inline comment */ [ + "//keep this", + "/*", + // extra line single comment + "*/", + "/* this too */" + ] x + } +} diff --git a/fixtures/tsconfck/parse/invalid/extends-array-circular/src/foo.ts b/fixtures/tsconfck/parse/invalid/extends-array-circular/src/foo.ts new file mode 100644 index 00000000..3329a7d9 --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/extends-array-circular/src/foo.ts @@ -0,0 +1 @@ +export const foo = 'foo'; diff --git a/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.a.b.json b/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.a.b.json new file mode 100644 index 00000000..5c98d92f --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.a.b.json @@ -0,0 +1,6 @@ +{ + "extends": ["./tsconfig.a.json"], // extending a here introduces a loop because a extends a.b too + "compilerOptions": { + "disableSizeLimit": true + } +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.a.json b/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.a.json new file mode 100644 index 00000000..fdfc06d0 --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.a.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.a.b.json", + "compilerOptions": { + "strictNullChecks": false, + "noImplicitAny": false + }, + "files": ["src/foo.ts"] +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.b.json b/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.b.json new file mode 100644 index 00000000..b6cdd550 --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.b.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.a.b.json", + "compilerOptions": { + "noImplicitAny": true + }, + "files": ["src/**"] +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.c.json b/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.c.json new file mode 100644 index 00000000..c7d18b06 --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.c.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "strictNullChecks": true, + } +} diff --git a/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.json b/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.json new file mode 100644 index 00000000..07b733cd --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/extends-array-circular/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": ["./tsconfig.a.json","./tsconfig.b.json","./tsconfig.c.json"] +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/invalid/extends-circular/deep/tsconfig.circular2.json b/fixtures/tsconfck/parse/invalid/extends-circular/deep/tsconfig.circular2.json new file mode 100644 index 00000000..3c43903c --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/extends-circular/deep/tsconfig.circular2.json @@ -0,0 +1,3 @@ +{ + "extends": "../tsconfig.json" +} diff --git a/fixtures/tsconfck/parse/invalid/extends-circular/tsconfig.circular.json b/fixtures/tsconfck/parse/invalid/extends-circular/tsconfig.circular.json new file mode 100644 index 00000000..815b74f4 --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/extends-circular/tsconfig.circular.json @@ -0,0 +1,3 @@ +{ + "extends": "./deep/tsconfig.circular2.json" +} diff --git a/fixtures/tsconfck/parse/invalid/extends-circular/tsconfig.json b/fixtures/tsconfck/parse/invalid/extends-circular/tsconfig.json new file mode 100644 index 00000000..8be6c877 --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/extends-circular/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.circular.json", + "compilerOptions": { + "types": ["foo"], + "strictNullChecks": true + }, + "include": ["src/**/*"] +} diff --git a/fixtures/tsconfck/parse/invalid/extends-not-found/tsconfig.json b/fixtures/tsconfck/parse/invalid/extends-not-found/tsconfig.json new file mode 100644 index 00000000..5d571c0a --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/extends-not-found/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.doesnotexist.json", + "compilerOptions": { + "types": ["foo"], + "strictNullChecks": true + }, + "include": ["src/**/*"] +} diff --git a/fixtures/tsconfck/parse/invalid/mixed/tsconfig.json b/fixtures/tsconfck/parse/invalid/mixed/tsconfig.json new file mode 100644 index 00000000..624ba533 --- /dev/null +++ b/fixtures/tsconfck/parse/invalid/mixed/tsconfig.json @@ -0,0 +1,17 @@ +/* +multi +line +*/ +{ + "extends": "", // trailing single line comment + "compilerOptions": { + "types": /* inline comment */ [ + "//keep this", + "/*", + // extra line single comment + "*/", + "/* this too */" , //<-dangling + ] /* dangling->*/, + // still dangling ^ + } x +} diff --git a/fixtures/tsconfck/parse/invalid/tsconfig.json/.gitkeep b/fixtures/tsconfck/parse/invalid/tsconfig.json/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/parse/solution/jsconfig/jsconfig.base.json b/fixtures/tsconfck/parse/solution/jsconfig/jsconfig.base.json new file mode 100644 index 00000000..b47146f4 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/jsconfig/jsconfig.base.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "allowJs": true, //must be true so that js extensions are globbed correctly + "composite": true, + "strictNullChecks": true + } +} diff --git a/fixtures/tsconfck/parse/solution/jsconfig/jsconfig.json b/fixtures/tsconfck/parse/solution/jsconfig/jsconfig.json new file mode 100644 index 00000000..74ddb41e --- /dev/null +++ b/fixtures/tsconfck/parse/solution/jsconfig/jsconfig.json @@ -0,0 +1,8 @@ +{ + "files": [], + "include": [], + "references": [ + {"path": "./jsconfig.src.json"}, + {"path": "./jsconfig.test.json"} + ] +} diff --git a/fixtures/tsconfck/parse/solution/jsconfig/jsconfig.src.json b/fixtures/tsconfck/parse/solution/jsconfig/jsconfig.src.json new file mode 100644 index 00000000..4ccf8522 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/jsconfig/jsconfig.src.json @@ -0,0 +1,8 @@ +{ + "extends": "./jsconfig.base", + "include": ["src/**/*"], + "exclude": ["src/**/*.spec.js"], + "compilerOptions": { + "strict": true + } +} diff --git a/fixtures/tsconfck/parse/solution/jsconfig/jsconfig.test.json b/fixtures/tsconfck/parse/solution/jsconfig/jsconfig.test.json new file mode 100644 index 00000000..414d5efc --- /dev/null +++ b/fixtures/tsconfck/parse/solution/jsconfig/jsconfig.test.json @@ -0,0 +1,7 @@ +{ + "extends": "./jsconfig.base", + "include": ["src/**/*.spec.js"], + "compilerOptions": { + "strict": false + } +} diff --git a/fixtures/tsconfck/parse/solution/jsconfig/src/bar.mjs b/fixtures/tsconfck/parse/solution/jsconfig/src/bar.mjs new file mode 100644 index 00000000..808dbfe1 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/jsconfig/src/bar.mjs @@ -0,0 +1,3 @@ +export function bar() { + return 'bar'; +} diff --git a/fixtures/tsconfck/parse/solution/jsconfig/src/baz.cjs b/fixtures/tsconfck/parse/solution/jsconfig/src/baz.cjs new file mode 100644 index 00000000..07536443 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/jsconfig/src/baz.cjs @@ -0,0 +1,4 @@ +function baz() { + return 'baz'; +} +module.exports = {baz} diff --git a/fixtures/tsconfck/parse/solution/jsconfig/src/foo.js b/fixtures/tsconfck/parse/solution/jsconfig/src/foo.js new file mode 100644 index 00000000..b0711913 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/jsconfig/src/foo.js @@ -0,0 +1,3 @@ +export function foo() { + return 'foo'; +} diff --git a/fixtures/tsconfck/parse/solution/jsconfig/src/foo.spec.js b/fixtures/tsconfck/parse/solution/jsconfig/src/foo.spec.js new file mode 100644 index 00000000..e400a535 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/jsconfig/src/foo.spec.js @@ -0,0 +1,9 @@ +import { foo } from './foo.js'; +import * as assert from 'assert'; + +function test() { + const actual = foo(); + const expected = 'foo'; + assert.strictEqual(actual, expected); +} +test(); diff --git a/fixtures/tsconfck/parse/solution/mixed/src/bar.mts b/fixtures/tsconfck/parse/solution/mixed/src/bar.mts new file mode 100644 index 00000000..808dbfe1 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/mixed/src/bar.mts @@ -0,0 +1,3 @@ +export function bar() { + return 'bar'; +} diff --git a/fixtures/tsconfck/parse/solution/mixed/src/baz.cts b/fixtures/tsconfck/parse/solution/mixed/src/baz.cts new file mode 100644 index 00000000..07536443 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/mixed/src/baz.cts @@ -0,0 +1,4 @@ +function baz() { + return 'baz'; +} +module.exports = {baz} diff --git a/fixtures/tsconfck/parse/solution/mixed/src/foo.spec.ts b/fixtures/tsconfck/parse/solution/mixed/src/foo.spec.ts new file mode 100644 index 00000000..e400a535 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/mixed/src/foo.spec.ts @@ -0,0 +1,9 @@ +import { foo } from './foo.js'; +import * as assert from 'assert'; + +function test() { + const actual = foo(); + const expected = 'foo'; + assert.strictEqual(actual, expected); +} +test(); diff --git a/fixtures/tsconfck/parse/solution/mixed/src/foo.ts b/fixtures/tsconfck/parse/solution/mixed/src/foo.ts new file mode 100644 index 00000000..b0711913 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/mixed/src/foo.ts @@ -0,0 +1,3 @@ +export function foo() { + return 'foo'; +} diff --git a/fixtures/tsconfck/parse/solution/mixed/tsconfig.base.json b/fixtures/tsconfck/parse/solution/mixed/tsconfig.base.json new file mode 100644 index 00000000..39e49363 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/mixed/tsconfig.base.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "composite": true, + "strictNullChecks": true + } +} diff --git a/fixtures/tsconfck/parse/solution/mixed/tsconfig.json b/fixtures/tsconfck/parse/solution/mixed/tsconfig.json new file mode 100644 index 00000000..b97aa029 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/mixed/tsconfig.json @@ -0,0 +1,8 @@ +{ + "files": [], + "include": [], + "references": [ + {"path": "./tsconfig.src.json"}, + {"path": "./tsconfig.test.json"} + ] +} diff --git a/fixtures/tsconfck/parse/solution/mixed/tsconfig.src.json b/fixtures/tsconfck/parse/solution/mixed/tsconfig.src.json new file mode 100644 index 00000000..73e9427d --- /dev/null +++ b/fixtures/tsconfck/parse/solution/mixed/tsconfig.src.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.base", + "include": ["src/**/*"], + "exclude": ["src/**/*.spec.ts"], + "compilerOptions": { + "strict": true + } +} diff --git a/fixtures/tsconfck/parse/solution/mixed/tsconfig.test.json b/fixtures/tsconfck/parse/solution/mixed/tsconfig.test.json new file mode 100644 index 00000000..e4a89929 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/mixed/tsconfig.test.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.base", + "include": ["src/**/*.spec.ts"], + "compilerOptions": { + "strict": false + } +} diff --git a/fixtures/tsconfck/parse/solution/referenced-exclude/src/bar.ts b/fixtures/tsconfck/parse/solution/referenced-exclude/src/bar.ts new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/parse/solution/referenced-exclude/src/foo.ts b/fixtures/tsconfck/parse/solution/referenced-exclude/src/foo.ts new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/parse/solution/referenced-exclude/tsconfig.bar.json b/fixtures/tsconfck/parse/solution/referenced-exclude/tsconfig.bar.json new file mode 100644 index 00000000..503337f6 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-exclude/tsconfig.bar.json @@ -0,0 +1,3 @@ +{ + "exclude": ["src/foo.ts"] +} diff --git a/fixtures/tsconfck/parse/solution/referenced-exclude/tsconfig.foo.json b/fixtures/tsconfck/parse/solution/referenced-exclude/tsconfig.foo.json new file mode 100644 index 00000000..08197263 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-exclude/tsconfig.foo.json @@ -0,0 +1,3 @@ +{ + "exclude": ["src/bar.ts"] +} diff --git a/fixtures/tsconfck/parse/solution/referenced-exclude/tsconfig.json b/fixtures/tsconfck/parse/solution/referenced-exclude/tsconfig.json new file mode 100644 index 00000000..bebe75bb --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-exclude/tsconfig.json @@ -0,0 +1,8 @@ +{ + "files": [], + "references": [{ + "path": "./tsconfig.foo.json" + }, { + "path": "./tsconfig.bar.json" + }] +} diff --git a/fixtures/tsconfck/parse/solution/referenced-extends-original/src/foo.ts b/fixtures/tsconfck/parse/solution/referenced-extends-original/src/foo.ts new file mode 100644 index 00000000..b0711913 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-extends-original/src/foo.ts @@ -0,0 +1,3 @@ +export function foo() { + return 'foo'; +} diff --git a/fixtures/tsconfck/parse/solution/referenced-extends-original/src/tsconfig.src.json b/fixtures/tsconfck/parse/solution/referenced-extends-original/src/tsconfig.src.json new file mode 100644 index 00000000..f2cc89c7 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-extends-original/src/tsconfig.src.json @@ -0,0 +1,8 @@ +{ + "include": ["./foo.ts"], + "extends": "../tsconfig", + "compilerOptions": { + "composite": true, + "strict": true + } +} diff --git a/fixtures/tsconfck/parse/solution/referenced-extends-original/tests/foo.test.ts b/fixtures/tsconfck/parse/solution/referenced-extends-original/tests/foo.test.ts new file mode 100644 index 00000000..9e5f167b --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-extends-original/tests/foo.test.ts @@ -0,0 +1,9 @@ +import { foo } from '../src/foo'; +import * as assert from 'assert'; + +function test() { + const actual = foo(); + const expected = 'foo'; + assert.strictEqual(actual, expected); +} +test(); diff --git a/fixtures/tsconfck/parse/solution/referenced-extends-original/tests/tsconfig.test.json b/fixtures/tsconfck/parse/solution/referenced-extends-original/tests/tsconfig.test.json new file mode 100644 index 00000000..07633cd5 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-extends-original/tests/tsconfig.test.json @@ -0,0 +1,8 @@ +{ + "include": ["./*.test.ts"], + "extends": "../tsconfig", + "compilerOptions": { + "composite": true, + "strict": false + } +} diff --git a/fixtures/tsconfck/parse/solution/referenced-extends-original/tsconfig.json b/fixtures/tsconfck/parse/solution/referenced-extends-original/tsconfig.json new file mode 100644 index 00000000..ca6baff1 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-extends-original/tsconfig.json @@ -0,0 +1,6 @@ +{ + "references": [ + {"path": "./src/tsconfig.src.json"}, + {"path": "./tests/tsconfig.test.json"} + ] +} diff --git a/fixtures/tsconfck/parse/solution/referenced-files/src/bar.ts b/fixtures/tsconfck/parse/solution/referenced-files/src/bar.ts new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/parse/solution/referenced-files/src/foo.ts b/fixtures/tsconfck/parse/solution/referenced-files/src/foo.ts new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/parse/solution/referenced-files/tsconfig.foo.json b/fixtures/tsconfck/parse/solution/referenced-files/tsconfig.foo.json new file mode 100644 index 00000000..38dae32c --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-files/tsconfig.foo.json @@ -0,0 +1,3 @@ +{ + "files": ["src/foo.ts"] +} diff --git a/fixtures/tsconfck/parse/solution/referenced-files/tsconfig.json b/fixtures/tsconfck/parse/solution/referenced-files/tsconfig.json new file mode 100644 index 00000000..ef25a834 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-files/tsconfig.json @@ -0,0 +1,6 @@ +{ + "files": [], + "references": [{ + "path": "./tsconfig.foo.json" + }] +} diff --git a/fixtures/tsconfck/parse/solution/referenced-include/src/bar.ts b/fixtures/tsconfck/parse/solution/referenced-include/src/bar.ts new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/parse/solution/referenced-include/src/foo.ts b/fixtures/tsconfck/parse/solution/referenced-include/src/foo.ts new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/parse/solution/referenced-include/tsconfig.bar.json b/fixtures/tsconfck/parse/solution/referenced-include/tsconfig.bar.json new file mode 100644 index 00000000..2c63c085 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-include/tsconfig.bar.json @@ -0,0 +1,2 @@ +{ +} diff --git a/fixtures/tsconfck/parse/solution/referenced-include/tsconfig.foo.json b/fixtures/tsconfck/parse/solution/referenced-include/tsconfig.foo.json new file mode 100644 index 00000000..58dc63b9 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-include/tsconfig.foo.json @@ -0,0 +1,3 @@ +{ + "include": ["src/foo.ts"] +} diff --git a/fixtures/tsconfck/parse/solution/referenced-include/tsconfig.json b/fixtures/tsconfck/parse/solution/referenced-include/tsconfig.json new file mode 100644 index 00000000..bebe75bb --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-include/tsconfig.json @@ -0,0 +1,8 @@ +{ + "files": [], + "references": [{ + "path": "./tsconfig.foo.json" + }, { + "path": "./tsconfig.bar.json" + }] +} diff --git a/fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/packages/foo/src/foo.ts b/fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/packages/foo/src/foo.ts new file mode 100644 index 00000000..b0711913 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/packages/foo/src/foo.ts @@ -0,0 +1,3 @@ +export function foo() { + return 'foo'; +} diff --git a/fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/packages/foo/tsconfig.foo.json b/fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/packages/foo/tsconfig.foo.json new file mode 100644 index 00000000..9536a0f4 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/packages/foo/tsconfig.foo.json @@ -0,0 +1,3 @@ +{ + "extends": "../../tsconfig.base.json" +} diff --git a/fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/tsconfig.base.json b/fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/tsconfig.base.json new file mode 100644 index 00000000..0cdb92fa --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/tsconfig.base.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "ES2022", + "moduleResolution": "bundler", + "noUnusedLocals": true, + "skipLibCheck": true, + "experimentalDecorators": true, + }, + "include": ["${configDir}/src/*"] +} diff --git a/fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/tsconfig.json b/fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/tsconfig.json new file mode 100644 index 00000000..34df78b3 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-with-configDir-and-extends/tsconfig.json @@ -0,0 +1,6 @@ +{ + "files": [], + "references": [{ + "path": "./packages/foo/tsconfig.foo.json" + }] +} diff --git a/fixtures/tsconfck/parse/solution/referenced-with-configDir/src/foo.ts b/fixtures/tsconfck/parse/solution/referenced-with-configDir/src/foo.ts new file mode 100644 index 00000000..b0711913 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-with-configDir/src/foo.ts @@ -0,0 +1,3 @@ +export function foo() { + return 'foo'; +} diff --git a/fixtures/tsconfck/parse/solution/referenced-with-configDir/tsconfig.json b/fixtures/tsconfck/parse/solution/referenced-with-configDir/tsconfig.json new file mode 100644 index 00000000..1213882d --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-with-configDir/tsconfig.json @@ -0,0 +1,6 @@ +{ + "files": [], + "references": [{ + "path": "./tsconfig.src.json" + }] +} diff --git a/fixtures/tsconfck/parse/solution/referenced-with-configDir/tsconfig.src.json b/fixtures/tsconfck/parse/solution/referenced-with-configDir/tsconfig.src.json new file mode 100644 index 00000000..0cdb92fa --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-with-configDir/tsconfig.src.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "ES2022", + "moduleResolution": "bundler", + "noUnusedLocals": true, + "skipLibCheck": true, + "experimentalDecorators": true, + }, + "include": ["${configDir}/src/*"] +} diff --git a/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/src/foo.ts b/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/src/foo.ts new file mode 100644 index 00000000..b0711913 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/src/foo.ts @@ -0,0 +1,3 @@ +export function foo() { + return 'foo'; +} diff --git a/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tests/foo.test.ts b/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tests/foo.test.ts new file mode 100644 index 00000000..9e5f167b --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tests/foo.test.ts @@ -0,0 +1,9 @@ +import { foo } from '../src/foo'; +import * as assert from 'assert'; + +function test() { + const actual = foo(); + const expected = 'foo'; + assert.strictEqual(actual, expected); +} +test(); diff --git a/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tsconfig.json b/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tsconfig.json new file mode 100644 index 00000000..c8dcb3a2 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + {"path": "./tsconfig.src.json"}, + {"path": "./tsconfig.test.json"} + ] +} diff --git a/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tsconfig.src.json b/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tsconfig.src.json new file mode 100644 index 00000000..06030771 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tsconfig.src.json @@ -0,0 +1,7 @@ +{ + "include": ["src"], + "compilerOptions": { + "composite": true, + "strict": true + } +} diff --git a/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tsconfig.test.json b/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tsconfig.test.json new file mode 100644 index 00000000..6b9198b2 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/referenced-with-implicit-globs/tsconfig.test.json @@ -0,0 +1,7 @@ +{ + "include": ["tests"], + "compilerOptions": { + "composite": true, + "strict": false + } +} diff --git a/fixtures/tsconfck/parse/solution/simple/src/foo.ts b/fixtures/tsconfck/parse/solution/simple/src/foo.ts new file mode 100644 index 00000000..b0711913 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/simple/src/foo.ts @@ -0,0 +1,3 @@ +export function foo() { + return 'foo'; +} diff --git a/fixtures/tsconfck/parse/solution/simple/src/tsconfig.json b/fixtures/tsconfck/parse/solution/simple/src/tsconfig.json new file mode 100644 index 00000000..c1bdec09 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/simple/src/tsconfig.json @@ -0,0 +1,7 @@ +{ + "include": ["./foo.ts"], + "extends": "../tsconfig.base", + "compilerOptions": { + "strict": true + } +} diff --git a/fixtures/tsconfck/parse/solution/simple/tests/foo.ts b/fixtures/tsconfck/parse/solution/simple/tests/foo.ts new file mode 100644 index 00000000..9e5f167b --- /dev/null +++ b/fixtures/tsconfck/parse/solution/simple/tests/foo.ts @@ -0,0 +1,9 @@ +import { foo } from '../src/foo'; +import * as assert from 'assert'; + +function test() { + const actual = foo(); + const expected = 'foo'; + assert.strictEqual(actual, expected); +} +test(); diff --git a/fixtures/tsconfck/parse/solution/simple/tests/tsconfig.json b/fixtures/tsconfck/parse/solution/simple/tests/tsconfig.json new file mode 100644 index 00000000..28ee0aab --- /dev/null +++ b/fixtures/tsconfck/parse/solution/simple/tests/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig.base", + "compilerOptions": { + "strict": false + } +} diff --git a/fixtures/tsconfck/parse/solution/simple/tsconfig.base.json b/fixtures/tsconfck/parse/solution/simple/tsconfig.base.json new file mode 100644 index 00000000..39e49363 --- /dev/null +++ b/fixtures/tsconfck/parse/solution/simple/tsconfig.base.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "composite": true, + "strictNullChecks": true + } +} diff --git a/fixtures/tsconfck/parse/solution/simple/tsconfig.json b/fixtures/tsconfck/parse/solution/simple/tsconfig.json new file mode 100644 index 00000000..9541678c --- /dev/null +++ b/fixtures/tsconfck/parse/solution/simple/tsconfig.json @@ -0,0 +1,8 @@ +{ + "files": [], + "include": [], + "references": [ + {"path": "./src"}, + {"path": "./tests"} + ] +} diff --git a/fixtures/tsconfck/parse/valid/bom/tsconfig.json b/fixtures/tsconfck/parse/valid/bom/tsconfig.json new file mode 100644 index 00000000..9248c71b --- /dev/null +++ b/fixtures/tsconfck/parse/valid/bom/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "strictNullChecks": true + } +} diff --git a/fixtures/tsconfck/parse/valid/comma/tsconfig.json b/fixtures/tsconfck/parse/valid/comma/tsconfig.json new file mode 100644 index 00000000..5c5febac --- /dev/null +++ b/fixtures/tsconfck/parse/valid/comma/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "types": ["foo", ] , + } , +} diff --git a/fixtures/tsconfck/parse/valid/comments/tsconfig.json b/fixtures/tsconfck/parse/valid/comments/tsconfig.json new file mode 100644 index 00000000..4768190f --- /dev/null +++ b/fixtures/tsconfck/parse/valid/comments/tsconfig.json @@ -0,0 +1,15 @@ +/* +multi +line +*/ +{ + "compilerOptions": { //trailing-single-line-comment + "types": /* inline comment */ [ + "//keep \"this", + "/*", + // extra line single comment + "*/", + "/* this too */" + ] + } +} diff --git a/fixtures/tsconfck/parse/valid/configDir/a/src/foo.ts b/fixtures/tsconfck/parse/valid/configDir/a/src/foo.ts new file mode 100644 index 00000000..b0711913 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/configDir/a/src/foo.ts @@ -0,0 +1,3 @@ +export function foo() { + return 'foo'; +} diff --git a/fixtures/tsconfck/parse/valid/configDir/a/tsconfig.json b/fixtures/tsconfck/parse/valid/configDir/a/tsconfig.json new file mode 100644 index 00000000..4d4c4a7d --- /dev/null +++ b/fixtures/tsconfck/parse/valid/configDir/a/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": ["../tsconfig.base.json"] +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/valid/configDir/b/src/foo.ts b/fixtures/tsconfck/parse/valid/configDir/b/src/foo.ts new file mode 100644 index 00000000..b0711913 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/configDir/b/src/foo.ts @@ -0,0 +1,3 @@ +export function foo() { + return 'foo'; +} diff --git a/fixtures/tsconfck/parse/valid/configDir/b/tsconfig.json b/fixtures/tsconfck/parse/valid/configDir/b/tsconfig.json new file mode 100644 index 00000000..4d4c4a7d --- /dev/null +++ b/fixtures/tsconfck/parse/valid/configDir/b/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": ["../tsconfig.base.json"] +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/valid/configDir/src/foo.ts b/fixtures/tsconfck/parse/valid/configDir/src/foo.ts new file mode 100644 index 00000000..b0711913 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/configDir/src/foo.ts @@ -0,0 +1,3 @@ +export function foo() { + return 'foo'; +} diff --git a/fixtures/tsconfck/parse/valid/configDir/tsconfig.base.json b/fixtures/tsconfck/parse/valid/configDir/tsconfig.base.json new file mode 100644 index 00000000..8d3596c1 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/configDir/tsconfig.base.json @@ -0,0 +1,11 @@ +{ + "include": ["${configDir}/**/*"], + "exclude": ["${configDir}/src/**/*.spec.ts"], + "compilerOptions": { + "paths": { + "$src": ["${configDir}/src/**/*"] + }, + "baseUrl": "${configDir}/src", + "outDir": "${configDir}/build" + } +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/valid/configDirNpm/tsconfig.json b/fixtures/tsconfck/parse/valid/configDirNpm/tsconfig.json new file mode 100644 index 00000000..30e75749 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/configDirNpm/tsconfig.json @@ -0,0 +1,9 @@ +// The configuration file for TypeScript. +{ + "$schema": "https://raw.githubusercontent.com/complete-ts/complete/main/packages/complete-tsconfig/schemas/tsconfig-strict-schema.json", + + "extends": [ + // https://github.com/IsaacScript/isaacscript/blob/main/packages/isaacscript-tsconfig/tsconfig.mod.json + "isaacscript-tsconfig/tsconfig.mod.json", + ], +} diff --git a/fixtures/tsconfck/parse/valid/empty/jsconfig.json b/fixtures/tsconfck/parse/valid/empty/jsconfig.json new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/parse/valid/empty/tsconfig.json b/fixtures/tsconfck/parse/valid/empty/tsconfig.json new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/parse/valid/lib/tsconfig.json b/fixtures/tsconfck/parse/valid/lib/tsconfig.json new file mode 100644 index 00000000..9342e928 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/lib/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "lib": [ + "ES2020", + "ES2021.Promise" + ] + } +} diff --git a/fixtures/tsconfck/parse/valid/mixed/tsconfig.json b/fixtures/tsconfck/parse/valid/mixed/tsconfig.json new file mode 100644 index 00000000..5fcb9eae --- /dev/null +++ b/fixtures/tsconfck/parse/valid/mixed/tsconfig.json @@ -0,0 +1,16 @@ +/* +multi +line +*/ +{ + "compilerOptions": { // trailing single line comment + "types": /* inline comment */ [ + "//keep this", + "/*", + // extra line single comment + "*/", + "/* this too */" , //<-dangling + ] /* dangling->*/, + // still dangling ^ + } +} diff --git a/fixtures/tsconfck/parse/valid/moduleResolution/bundler/tsconfig.json b/fixtures/tsconfck/parse/valid/moduleResolution/bundler/tsconfig.json new file mode 100644 index 00000000..9f07e578 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/moduleResolution/bundler/tsconfig.json @@ -0,0 +1,16 @@ +{ + "files": ["foo.ts"], + "compilerOptions": { + "types": ["foo"], + "importsNotUsedAsValues": "error", + "module": "node16", + "moduleResolution": "bundler", + "newLine": "lf", + "target": "esnext" + }, + "watchOptions": { + "watchFile": "useFsEvents", + "watchDirectory": "useFsEvents", + "fallbackPolling": "dynamicPriority" + } +} diff --git a/fixtures/tsconfck/parse/valid/moduleResolution/classic/tsconfig.json b/fixtures/tsconfck/parse/valid/moduleResolution/classic/tsconfig.json new file mode 100644 index 00000000..bbe04136 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/moduleResolution/classic/tsconfig.json @@ -0,0 +1,16 @@ +{ + "files": ["foo.ts"], + "compilerOptions": { + "types": ["foo"], + "importsNotUsedAsValues": "error", + "module": "node16", + "moduleResolution": "classic", + "newLine": "lf", + "target": "esnext" + }, + "watchOptions": { + "watchFile": "useFsEvents", + "watchDirectory": "useFsEvents", + "fallbackPolling": "dynamicPriority" + } +} diff --git a/fixtures/tsconfck/parse/valid/moduleResolution/node16/tsconfig.json b/fixtures/tsconfck/parse/valid/moduleResolution/node16/tsconfig.json new file mode 100644 index 00000000..0768c4e4 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/moduleResolution/node16/tsconfig.json @@ -0,0 +1,16 @@ +{ + "files": ["foo.ts"], + "compilerOptions": { + "types": ["foo"], + "importsNotUsedAsValues": "error", + "module": "node16", + "moduleResolution": "node16", + "newLine": "lf", + "target": "esnext" + }, + "watchOptions": { + "watchFile": "useFsEvents", + "watchDirectory": "useFsEvents", + "fallbackPolling": "dynamicPriority" + } +} diff --git a/fixtures/tsconfck/parse/valid/moduleResolution/nodenext/tsconfig.json b/fixtures/tsconfck/parse/valid/moduleResolution/nodenext/tsconfig.json new file mode 100644 index 00000000..f4bfb616 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/moduleResolution/nodenext/tsconfig.json @@ -0,0 +1,16 @@ +{ + "files": ["foo.ts"], + "compilerOptions": { + "types": ["foo"], + "importsNotUsedAsValues": "error", + "module": "nodenext", + "moduleResolution": "nodenext", + "newLine": "lf", + "target": "esnext" + }, + "watchOptions": { + "watchFile": "useFsEvents", + "watchDirectory": "useFsEvents", + "fallbackPolling": "dynamicPriority" + } +} diff --git a/fixtures/tsconfck/parse/valid/regular/tsconfig.json b/fixtures/tsconfck/parse/valid/regular/tsconfig.json new file mode 100644 index 00000000..b19e302c --- /dev/null +++ b/fixtures/tsconfck/parse/valid/regular/tsconfig.json @@ -0,0 +1,16 @@ +{ + "files": ["foo.ts"], + "compilerOptions": { + "types": ["foo"], + "importsNotUsedAsValues": "error", + "module": "es2020", + "moduleResolution": "node", + "newLine": "lf", + "target": "esnext" + }, + "watchOptions": { + "watchFile": "useFsEvents", + "watchDirectory": "useFsEvents", + "fallbackPolling": "dynamicPriority" + } +} diff --git a/fixtures/tsconfck/parse/valid/ts_node/tsconfig.json b/fixtures/tsconfck/parse/valid/ts_node/tsconfig.json new file mode 100644 index 00000000..311b63e3 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/ts_node/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "noLib": false + }, + "ts-node": { + "preferTsExts": true, + "compilerOptions": { + "noLib": true + } + }, + "something": "bla" +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/valid/with_extends/array/src/foo.ts b/fixtures/tsconfck/parse/valid/with_extends/array/src/foo.ts new file mode 100644 index 00000000..3329a7d9 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/array/src/foo.ts @@ -0,0 +1 @@ +export const foo = 'foo'; diff --git a/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.a.b.json b/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.a.b.json new file mode 100644 index 00000000..5396084d --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.a.b.json @@ -0,0 +1,6 @@ +{ + "extends": ["./tsconfig.c.json"], // extending c here works because it does not create a loop + "compilerOptions": { + "disableSizeLimit": true // this hasn't been defined before, so it is expected in the output + } +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.a.json b/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.a.json new file mode 100644 index 00000000..54dcf0fc --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.a.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.a.b.json", + "compilerOptions": { + "strictNullChecks": false, + "noImplicitAny": false + }, + "files": ["src/foo.ts"] // files is not extended so expected output still has src/** (b extends a) +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.b.json b/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.b.json new file mode 100644 index 00000000..b6cdd550 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.b.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.a.b.json", + "compilerOptions": { + "noImplicitAny": true + }, + "files": ["src/**"] +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.c.json b/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.c.json new file mode 100644 index 00000000..c7d18b06 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.c.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "strictNullChecks": true, + } +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.json b/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.json new file mode 100644 index 00000000..07b733cd --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/array/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": ["./tsconfig.a.json","./tsconfig.b.json","./tsconfig.c.json"] +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/valid/with_extends/dot/main.js b/fixtures/tsconfck/parse/valid/with_extends/dot/main.js new file mode 100644 index 00000000..824d1be7 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/dot/main.js @@ -0,0 +1,3 @@ +export default function(){ + return 'not a tsconfig' +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/dot/package.json b/fixtures/tsconfck/parse/valid/with_extends/dot/package.json new file mode 100644 index 00000000..fa5bb06f --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/dot/package.json @@ -0,0 +1,8 @@ +{ + "name": "dummy", + "private": true, + "version": "0.0.0", + "//": "main field is found by createRequire", + "main": "main.js" + +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/dot/src/foo.ts b/fixtures/tsconfck/parse/valid/with_extends/dot/src/foo.ts new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/parse/valid/with_extends/dot/tsconfig.eslint.json b/fixtures/tsconfck/parse/valid/with_extends/dot/tsconfig.eslint.json new file mode 100644 index 00000000..1cf42003 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/dot/tsconfig.eslint.json @@ -0,0 +1,3 @@ +{ + "extends": "." +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/dot/tsconfig.json b/fixtures/tsconfck/parse/valid/with_extends/dot/tsconfig.json new file mode 100644 index 00000000..698fb99a --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/dot/tsconfig.json @@ -0,0 +1,3 @@ +{ + "include": ["src/**/*"] +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/dotdot/main.js b/fixtures/tsconfck/parse/valid/with_extends/dotdot/main.js new file mode 100644 index 00000000..824d1be7 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/dotdot/main.js @@ -0,0 +1,3 @@ +export default function(){ + return 'not a tsconfig' +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/dotdot/package.json b/fixtures/tsconfck/parse/valid/with_extends/dotdot/package.json new file mode 100644 index 00000000..fa5bb06f --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/dotdot/package.json @@ -0,0 +1,8 @@ +{ + "name": "dummy", + "private": true, + "version": "0.0.0", + "//": "main field is found by createRequire", + "main": "main.js" + +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/dotdot/src/foo.ts b/fixtures/tsconfck/parse/valid/with_extends/dotdot/src/foo.ts new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/parse/valid/with_extends/dotdot/src/tsconfig.json b/fixtures/tsconfck/parse/valid/with_extends/dotdot/src/tsconfig.json new file mode 100644 index 00000000..2c409638 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/dotdot/src/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": ".." +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/dotdot/tsconfig.json b/fixtures/tsconfck/parse/valid/with_extends/dotdot/tsconfig.json new file mode 100644 index 00000000..0ac2bfe8 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/dotdot/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../tsconfig.parent.json", + "include": ["src/**/*"] +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/nested/src/foo.ts b/fixtures/tsconfck/parse/valid/with_extends/nested/src/foo.ts new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/parse/valid/with_extends/nested/src/nested/bar.ts b/fixtures/tsconfck/parse/valid/with_extends/nested/src/nested/bar.ts new file mode 100644 index 00000000..e69de29b diff --git a/fixtures/tsconfck/parse/valid/with_extends/nested/src/nested/tsconfig.json b/fixtures/tsconfck/parse/valid/with_extends/nested/src/nested/tsconfig.json new file mode 100644 index 00000000..ff14f5bf --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/nested/src/nested/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "strictNullChecks": true + } +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/nested/src/tsconfig.json b/fixtures/tsconfck/parse/valid/with_extends/nested/src/tsconfig.json new file mode 100644 index 00000000..3c43903c --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/nested/src/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../tsconfig.json" +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/nested/tsconfig.json b/fixtures/tsconfck/parse/valid/with_extends/nested/tsconfig.json new file mode 100644 index 00000000..0ac2bfe8 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/nested/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../tsconfig.parent.json", + "include": ["src/**/*"] +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/no_compileroptions/tsconfig.json b/fixtures/tsconfck/parse/valid/with_extends/no_compileroptions/tsconfig.json new file mode 100644 index 00000000..2bbd9c8e --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/no_compileroptions/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../tsconfig.parent.json", + "include": ["src/**/*", "foo.ts"] +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/node/tsconfig.json b/fixtures/tsconfck/parse/valid/with_extends/node/tsconfig.json new file mode 100644 index 00000000..7e6625d9 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/node/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@tsconfig/node18/tsconfig.json", + "compilerOptions": { + "types": ["foo"], + "strictNullChecks": true + }, + "include": ["src/**/*"] +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/node_fallback/tsconfig.json b/fixtures/tsconfck/parse/valid/with_extends/node_fallback/tsconfig.json new file mode 100644 index 00000000..e9460d90 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/node_fallback/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@tsconfig/node18", + "compilerOptions": { + "types": ["foo"], + "strictNullChecks": true + }, + "include": ["src/**/*"] +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/paths/lib/foo.ts b/fixtures/tsconfck/parse/valid/with_extends/paths/lib/foo.ts new file mode 100644 index 00000000..3329a7d9 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/paths/lib/foo.ts @@ -0,0 +1 @@ +export const foo = 'foo'; diff --git a/fixtures/tsconfck/parse/valid/with_extends/paths/src/import-foo.ts b/fixtures/tsconfck/parse/valid/with_extends/paths/src/import-foo.ts new file mode 100644 index 00000000..ca851b49 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/paths/src/import-foo.ts @@ -0,0 +1,2 @@ +import foo from '$lib/foo'; +export const foobar = foo + 'bar;'; diff --git a/fixtures/tsconfck/parse/valid/with_extends/paths/src/tsconfig.json b/fixtures/tsconfck/parse/valid/with_extends/paths/src/tsconfig.json new file mode 100644 index 00000000..a8bfd195 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/paths/src/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../tsconfig.base", + "compilerOptions": { + "types": ["foo"], + "strictNullChecks": true + } +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/valid/with_extends/paths/tsconfig.base.json b/fixtures/tsconfck/parse/valid/with_extends/paths/tsconfig.base.json new file mode 100644 index 00000000..51a784d6 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/paths/tsconfig.base.json @@ -0,0 +1,11 @@ +{ + "extends": "../tsconfig.parent.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "$lib": ["*","./lib"], + "$src": ["./src"] + } + }, + "include": ["src/**/*","lib/**/*"] +} \ No newline at end of file diff --git a/fixtures/tsconfck/parse/valid/with_extends/simple/tsconfig.json b/fixtures/tsconfck/parse/valid/with_extends/simple/tsconfig.json new file mode 100644 index 00000000..0903c05b --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/simple/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.parent.json", + "compilerOptions": { + "types": ["foo"], + "strictNullChecks": true + }, + "include": ["src/**/*", "foo.ts"] +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/tsconfig.parent.json b/fixtures/tsconfck/parse/valid/with_extends/tsconfig.parent.json new file mode 100644 index 00000000..bf6ecee3 --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/tsconfig.parent.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "types": ["bar"], + "strictNullChecks": false, + "noImplicitAny": true + }, + "watchOptions": { + "watchFile": "useFsEvents", + "watchDirectory": "useFsEvents", + "fallbackPolling": "dynamicPriority" + }, + "exclude": ["**/foo/*"], + // the following keys should not be inherited by extending + "something": "bla", + "ts-node": { + "skipIgnore": true + } +} diff --git a/fixtures/tsconfck/parse/valid/with_extends/without_json_extension/tsconfig.json b/fixtures/tsconfck/parse/valid/with_extends/without_json_extension/tsconfig.json new file mode 100644 index 00000000..537eba7a --- /dev/null +++ b/fixtures/tsconfck/parse/valid/with_extends/without_json_extension/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.parent", + "compilerOptions": { + "types": ["foo"], + "strictNullChecks": true + }, + "include": ["src/**/*", "foo.ts"] +} diff --git a/package.json b/package.json index e3e36cc8..36428262 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@napi-rs/wasm-runtime": "^1.0.7", "@types/node": "^24.9.1", "emnapi": "^1.6.0", + "tsconfck": "^3.1.6", "typescript": "^5.9.3", "vitest": "^4.0.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index de302896..04faceae 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,9 @@ importers: emnapi: specifier: ^1.6.0 version: 1.7.0 + tsconfck: + specifier: ^3.1.6 + version: 3.1.6(typescript@5.9.3) typescript: specifier: ^5.9.3 version: 5.9.3 @@ -75,6 +78,15 @@ importers: specifier: ^19.1.0 version: 19.2.0 + fixtures/tsconfck: + devDependencies: + '@tsconfig/node18': + specifier: ^18.2.4 + version: 18.2.6 + isaacscript-tsconfig: + specifier: ^7.0.1 + version: 7.0.1 + packages: '@babel/runtime@7.28.4': @@ -893,6 +905,15 @@ packages: '@standard-schema/spec@1.0.0': resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} + '@tsconfig/node-lts@20.1.3': + resolution: {integrity: sha512-m3b7EP2U+h5tNSpaBMfcTuHmHn04wrgRPQQrfKt75YIPq6kPs2153/KfPHdqkEWGx5pEBvS6rnvToT+yTtC1iw==} + + '@tsconfig/node18@18.2.6': + resolution: {integrity: sha512-eAWQzAjPj18tKnDzmWstz4OyWewLUNBm9tdoN9LayzoboRktYx3Enk1ZXPmThj55L7c4VWYq/Bzq0A51znZfhw==} + + '@tsconfig/strictest@2.0.8': + resolution: {integrity: sha512-XnQ7vNz5HRN0r88GYf1J9JJjqtZPiHt2woGJOo2dYqyHGGcd6OLGqSlBB6p1j9mpzja6Oe5BoPqWmeDx6X9rLw==} + '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} @@ -1167,6 +1188,9 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + isaacscript-tsconfig@7.0.1: + resolution: {integrity: sha512-E0K3g+31vjy0nDNc8G7xNKY48xw/vOXPBOvQ1f6pumA0PzPkMm8QU2Z1VJKbxOKyNI/VUS3Ml9ElRdNlYgzkBg==} + javascript-natural-sort@0.7.1: resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} @@ -1325,6 +1349,16 @@ packages: resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} engines: {node: '>=14.0.0'} + tsconfck@3.1.6: + resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==} + engines: {node: ^18 || >=20} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} @@ -2042,6 +2076,12 @@ snapshots: '@standard-schema/spec@1.0.0': {} + '@tsconfig/node-lts@20.1.3': {} + + '@tsconfig/node18@18.2.6': {} + + '@tsconfig/strictest@2.0.8': {} + '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 @@ -2311,6 +2351,11 @@ snapshots: is-fullwidth-code-point@3.0.0: {} + isaacscript-tsconfig@7.0.1: + dependencies: + '@tsconfig/node-lts': 20.1.3 + '@tsconfig/strictest': 2.0.8 + javascript-natural-sort@0.7.1: {} js-yaml@4.1.0: @@ -2475,6 +2520,10 @@ snapshots: tinyrainbow@3.0.3: {} + tsconfck@3.1.6(typescript@5.9.3): + optionalDependencies: + typescript: 5.9.3 + tslib@2.6.2: {} tslib@2.8.1: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 8fa98621..ba16a0a7 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,6 +2,7 @@ packages: - npm - napi - fixtures/pnpm + - fixtures/tsconfck - fixtures/pnpm-workspace/** ignoredBuiltDependencies: diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 68054156..258a506a 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -24,6 +24,7 @@ mod roots; mod scoped_packages; mod simple; mod symlink; +mod tsconfck; mod tsconfig_discovery; mod tsconfig_extends; mod tsconfig_paths; diff --git a/src/tests/tsconfck.rs b/src/tests/tsconfck.rs new file mode 100644 index 00000000..44c41045 --- /dev/null +++ b/src/tests/tsconfck.rs @@ -0,0 +1,108 @@ +use std::path::PathBuf; + +use walkdir::WalkDir; + +use crate::Resolver; + +fn walk(dir: &PathBuf) -> Vec { + WalkDir::new(dir) + .into_iter() + .filter_map(Result::ok) + .map(|entry| entry.path().to_path_buf()) + .collect() +} + +// https://github.com/dominikg/tsconfck/blob/main/packages/tsconfck/tests/parse.js +#[test] +fn parse_valid() { + let dir = super::fixture_root().join("tsconfck").join("parse").join("valid"); + let resolver = Resolver::default(); + for path in walk(&dir).into_iter().filter(|path| path.file_name().unwrap() == "tsconfig.json") { + let tsconfig = resolver.resolve_tsconfig(&path); + assert_eq!(tsconfig.map(|t| t.path().to_path_buf()), Ok(path)); + } +} + +#[test] +fn parse_invalid() { + let dir = super::fixture_root().join("tsconfck").join("parse").join("invalid"); + let resolver = Resolver::default(); + for path in walk(&dir).into_iter().filter(|path| path.file_name().unwrap() == "tsconfig.json") { + let tsconfig = resolver.resolve_tsconfig(&path); + assert!(tsconfig.is_err(), "{} {tsconfig:?}", path.display()); + } +} + +#[test] +fn config_dir() { + let dir = super::fixture_root().join("tsconfck").join("parse").join("valid").join("configDir"); + let resolver = Resolver::default(); + for path in walk(&dir).into_iter().filter(|path| path.file_name().unwrap() == "tsconfig.json") { + let tsconfig = resolver.resolve_tsconfig(&path).unwrap(); + let base_url = tsconfig.compiler_options.base_url.clone(); + assert_eq!(base_url, Some(path.parent().unwrap().join("src"))); + } +} + +#[test] +fn solution() { + let dir = super::fixture_root().join("tsconfck").join("parse").join("solution"); + let resolver = Resolver::default(); + for path in walk(&dir).into_iter().filter(|path| path.file_name().unwrap() == "tsconfig.json") { + let tsconfig = resolver.resolve_tsconfig(&path); + assert_eq!(tsconfig.map(|t| t.path().to_path_buf()), Ok(path)); + } +} + +#[test] +fn part_of_solution() { + let root = super::fixture_root().join("tsconfck").join("parse").join("solution"); + + let pass = [ + ("simple", "src/foo.ts", "src/tsconfig.json"), + ("simple", "tests/foo.ts", "tests/tsconfig.json"), + ("mixed", "src/bar.mts", "tsconfig.src.json"), + ("mixed", "src/baz.cts", "tsconfig.src.json"), + ("mixed", "src/foo.ts", "tsconfig.src.json"), + ("mixed", "src/foo.spec.ts", "tsconfig.test.json"), + ("referenced-extends-original", "src/foo.ts", "tsconfig.json"), + ("referenced-extends-original", "tests/foo.test.ts", "tsconfig.json"), + ("referenced-with-configDir", "src/foo.ts", "tsconfig.src.json"), + ( + "referenced-with-configDir-and-extends", + "packages/foo/src/foo.ts", + "packages/foo/tsconfig.foo.json", + ), + ("referenced-with-implicit-globs", "src/foo.ts", "tsconfig.src.json"), + ("referenced-with-implicit-globs", "tests/foo.test.ts", "tsconfig.test.json"), + // not part of tsconfck + ("referenced-files", "src/foo.ts", "tsconfig.foo.json"), + ("referenced-files", "src/bar.ts", "tsconfig.json"), + ("referenced-include", "src/foo.ts", "tsconfig.foo.json"), + ("referenced-include", "src/bar.ts", "tsconfig.bar.json"), + ("referenced-exclude", "src/foo.ts", "tsconfig.foo.json"), + ("referenced-exclude", "src/bar.ts", "tsconfig.bar.json"), + ]; + + let resolver = Resolver::default(); + for (dir, specifier, expected) in pass { + let dir = root.join(dir); + let tsconfig = resolver.find_tsconfig(dir.join(specifier)).unwrap().unwrap(); + assert_eq!(tsconfig.path.clone(), dir.join(expected), "{dir:?} {specifier}"); + } +} + +// https://github.com/dominikg/tsconfck/blob/main/packages/tsconfck/tests/find.js +#[test] +fn find() { + let dir = super::fixture_root().join("tsconfck").join("find").join("a"); + let resolver = Resolver::default(); + + let result = resolver.find_tsconfig(dir.join("foo.ts")); + let path = result.map(|tsconfig| tsconfig.unwrap().path().to_path_buf()); + assert_eq!(path, Ok(dir.join("tsconfig.json"))); + + let result = resolver.find_tsconfig(dir.join("b").join("foo.ts")); + let path = result.map(|tsconfig| tsconfig.unwrap().path().to_path_buf()); + assert_eq!(path, Ok(dir.join("tsconfig.json"))); +} diff --git a/src/tests/tsconfig_extends.rs b/src/tests/tsconfig_extends.rs index f12ede69..acd9902a 100644 --- a/src/tests/tsconfig_extends.rs +++ b/src/tests/tsconfig_extends.rs @@ -24,9 +24,9 @@ fn test_extend_tsconfig() { let resolution = resolver.resolve_tsconfig(&f).expect("resolved"); // Should inherit tsconfig from parent - assert_eq!(resolution.files, Some(vec!["files".to_string()])); - assert_eq!(resolution.include, Some(vec!["include".to_string()])); - assert_eq!(resolution.exclude, Some(vec!["exclude".to_string()])); + assert_eq!(resolution.files, Some(vec![f.join("files")])); + assert_eq!(resolution.include, Some(vec![f.join("include")])); + assert_eq!(resolution.exclude, Some(vec![f.join("exclude")])); let compiler_options = &resolution.compiler_options; assert_eq!(compiler_options.base_url, Some(f.join("src"))); diff --git a/src/tsconfig.rs b/src/tsconfig.rs index da449283..e80d3bf5 100644 --- a/src/tsconfig.rs +++ b/src/tsconfig.rs @@ -1,4 +1,5 @@ use std::{ + borrow::Cow, fmt::Debug, hash::BuildHasherDefault, path::{Path, PathBuf}, @@ -11,8 +12,18 @@ use serde::Deserialize; use crate::{TsconfigReferences, path::PathUtil, replace_bom_with_whitespace}; +/// Template variable `${configDir}` for substitution of config files +/// directory path. +/// +/// NOTE: All tests cases are just a head replacement of `${configDir}`, so +/// we are constrained as such. +/// +/// See . +/// Allow list: const TEMPLATE_VARIABLE: &str = "${configDir}"; +const GLOB_ALL_PATTERN: &str = "**/*"; + pub type CompilerOptionsPathsMap = IndexMap, BuildHasherDefault>; /// Project Reference @@ -36,13 +47,13 @@ pub struct TsConfig { pub path: PathBuf, #[serde(default)] - pub files: Option>, + pub files: Option>, #[serde(default)] - pub include: Option>, + pub include: Option>, #[serde(default)] - pub exclude: Option>, + pub exclude: Option>, #[serde(default)] pub extends: Option, @@ -57,7 +68,7 @@ pub struct TsConfig { /// /// Corresponds to each item in [TsConfig::references]. #[serde(skip)] - pub references_resolved: Vec>, + pub references_resolved: Vec>, } impl TsConfig { @@ -301,12 +312,23 @@ impl TsConfig { let config_dir = self.directory().to_path_buf(); + // Substitute template variable in `tsconfig.files`. + if let Some(files) = self.files.take() { + self.files = Some(files.into_iter().map(|p| self.adjust_path(p)).collect()); + } + + // Substitute template variable in `tsconfig.include`. + if let Some(includes) = self.include.take() { + self.include = Some(includes.into_iter().map(|p| self.adjust_path(p)).collect()); + } + + // Substitute template variable in `tsconfig.exclude`. + if let Some(excludes) = self.exclude.take() { + self.exclude = Some(excludes.into_iter().map(|p| self.adjust_path(p)).collect()); + } + if let Some(base_url) = &self.compiler_options.base_url { - // Substitute template variable in `tsconfig.compilerOptions.baseUrl`. - let base_url = base_url.to_string_lossy().strip_prefix(TEMPLATE_VARIABLE).map_or_else( - || config_dir.normalize_with(base_url), - |stripped_path| config_dir.join(stripped_path.trim_start_matches('/')), - ); + let base_url = self.adjust_path(base_url.clone()); self.compiler_options.base_url = Some(base_url); } @@ -324,7 +346,12 @@ impl TsConfig { // Substitute template variable in `tsconfig.compilerOptions.paths`. for paths in self.compiler_options.paths.as_mut().unwrap().values_mut() { for path in paths { - Self::substitute_template_variable(&config_dir, path); + if let Some(stripped_path) = path.strip_prefix(TEMPLATE_VARIABLE) { + *path = config_dir + .join(stripped_path.trim_start_matches('/')) + .to_string_lossy() + .to_string(); + } } } } @@ -332,17 +359,12 @@ impl TsConfig { self } - /// Template variable `${configDir}` for substitution of config files - /// directory path. - /// - /// NOTE: All tests cases are just a head replacement of `${configDir}`, so - /// we are constrained as such. - /// - /// See . - pub(crate) fn substitute_template_variable(directory: &Path, path: &mut String) { - if let Some(stripped_path) = path.strip_prefix(TEMPLATE_VARIABLE) { - *path = - directory.join(stripped_path.trim_start_matches('/')).to_string_lossy().to_string(); + #[expect(clippy::option_if_let_else)] + fn adjust_path(&self, path: PathBuf) -> PathBuf { + if let Some(stripped) = path.to_string_lossy().strip_prefix(TEMPLATE_VARIABLE) { + self.directory().join(stripped.trim_start_matches('/')) + } else { + self.directory().normalize_with(path) } } @@ -492,3 +514,101 @@ pub enum ExtendsField { Single(String), Multiple(Vec), } + +#[derive(Clone, Copy)] +enum GlobPattern<'a> { + Pattern(&'a [PathBuf]), + All, +} + +/// Tsconfig resolver +impl TsConfig { + pub(crate) fn resolve_tsconfig_solution(tsconfig: Arc, path: &Path) -> Arc { + if !tsconfig.references_resolved.is_empty() + && tsconfig.is_file_extension_allowed_in_tsconfig(path) + && !tsconfig.is_file_included_in_tsconfig(path) + && let Some(solution_tsconfig) = tsconfig + .references_resolved + .iter() + .find(|referenced| referenced.is_file_included_in_tsconfig(path)) + .map(Arc::clone) + { + return solution_tsconfig; + } + tsconfig + } + + fn is_file_included_in_tsconfig(&self, path: &Path) -> bool { + // 1. Check files array (highest priority - overrides exclude) + if self.files.as_ref().is_some_and(|files| files.iter().any(|file| Path::new(file) == path)) + { + return true; + } + // 2. Check include patterns + let is_included = self.include.as_ref().map_or_else( + || { + if self.files.is_some() { + false + } else { + self.is_glob_matches(path, GlobPattern::All) + } + }, + |include_patterns| self.is_glob_matches(path, GlobPattern::Pattern(include_patterns)), + ); + // 3. Check exclude patterns + if is_included { + return self.exclude.as_ref().is_none_or(|exclude_patterns| { + !self.is_glob_matches(path, GlobPattern::Pattern(exclude_patterns)) + }); + } + false + } + + fn is_glob_matches(&self, path: &Path, pattern: GlobPattern) -> bool { + let path_str = path.to_string_lossy().replace('\\', "/"); + match pattern { + GlobPattern::All => self.is_glob_match(GLOB_ALL_PATTERN, path, &path_str), + GlobPattern::Pattern(patterns) => patterns.iter().any(|pattern| { + let pattern = pattern.to_string_lossy().replace('\\', "/"); + self.is_glob_match(pattern.as_ref(), path, &path_str) + }), + } + } + + fn is_glob_match(&self, pattern: &str, path: &Path, path_str: &str) -> bool { + if pattern == path_str { + return true; + } + // Special case: **/* matches everything + if pattern == GLOB_ALL_PATTERN { + return true; + } + // Normalize pattern: add implicit /**/* for directory patterns + // Find the part after the last '/' to check if it looks like a directory + let after_last_slash = pattern.rsplit('/').next().unwrap_or(pattern); + let needs_implicit_glob = !after_last_slash.contains(['.', '*', '?']); + let pattern = if needs_implicit_glob { + Cow::Owned(format!( + "{pattern}{}", + if pattern.ends_with('/') { "**/*" } else { "/**/*" } + )) + } else { + Cow::Borrowed(pattern) + }; + // Fast check: if pattern ends with *, filename must have valid extension + if pattern.ends_with('*') && !self.is_file_extension_allowed_in_tsconfig(path) { + return false; + } + fast_glob::glob_match(pattern.as_ref(), path_str) + } + + fn is_file_extension_allowed_in_tsconfig(&self, path: &Path) -> bool { + const TS_EXTENSIONS: [&str; 4] = ["ts", "tsx", "mts", "cts"]; + const JS_EXTENSIONS: [&str; 4] = ["js", "jsx", "mjs", "cjs"]; + let allow_js = self.compiler_options.allow_js.is_some_and(|b| b); + path.extension().and_then(|ext| ext.to_str()).is_some_and(|ext| { + TS_EXTENSIONS.contains(&ext) + || if allow_js { JS_EXTENSIONS.contains(&ext) } else { false } + }) + } +} diff --git a/src/tsconfig_resolver.rs b/src/tsconfig_resolver.rs index b51b31c3..f28326ef 100644 --- a/src/tsconfig_resolver.rs +++ b/src/tsconfig_resolver.rs @@ -34,6 +34,76 @@ impl TsconfigResolveContext { } impl ResolverGeneric { + /// Finds the `tsconfig` to which this `path` belongs. + /// + /// Algorithm: + /// + /// 1. Search for `tsconfig.json` in ancestor directories. + /// 2. If the path is not included in this `tsconfig.json` through the `files`, `include`, or `exclude` fields: + /// 2.1. Search through project references until a referenced `tsconfig` includes this file. + /// 2.2. If none of the references include this path, return the `tsconfig.json` found in step 1. + /// + /// # Errors + /// + /// * Returns an error if the tsconfig is invalid, including any extended or referenced tsconfigs. + pub fn find_tsconfig>( + &self, + path: P, + ) -> Result>, ResolveError> { + let path = path.as_ref(); + self.find_tsconfig_tracing(path) + } + + fn find_tsconfig_tracing(&self, path: &Path) -> Result>, ResolveError> { + let span = tracing::debug_span!("find_tsconfig", path = ?path); + let _enter = span.enter(); + let cached_path = self.cache.value(path); + self.find_tsconfig_impl(&cached_path, &mut Ctx::default()).map(|option_tsconfig| { + option_tsconfig.map(|tsconfig| { + let r = TsConfig::resolve_tsconfig_solution(tsconfig, path); + tracing::debug!(path = ?path, ret = ?r); + r + }) + }) + } + + /// Find tsconfig.json of a path by traversing parent directories. + /// + /// # Errors + /// + /// * [ResolveError::Json] + pub(crate) fn find_tsconfig_impl( + &self, + cached_path: &CachedPath, + ctx: &mut Ctx, + ) -> Result>, ResolveError> { + // Don't discover tsconfig for paths inside node_modules + if cached_path.inside_node_modules() { + return Ok(None); + } + // Skip non-absolute paths (e.g. virtual modules) + if !cached_path.path.is_absolute() { + return Ok(None); + } + + let mut cache_value = Some(cached_path.clone()); + while let Some(cv) = cache_value { + if let Some(tsconfig) = cv.tsconfig.get_or_try_init(|| { + let tsconfig_path = cv.path.join("tsconfig.json"); + let tsconfig_path = self.cache.value(&tsconfig_path); + if self.cache.is_file(&tsconfig_path, ctx) { + self.resolve_tsconfig(tsconfig_path.path()).map(Some) + } else { + Ok(None) + } + })? { + return Ok(Some(Arc::clone(tsconfig))); + } + cache_value = cv.parent(); + } + Ok(None) + } + /// Resolve `tsconfig`. /// /// The path can be: @@ -167,7 +237,7 @@ impl ResolverGeneric { tsconfig } Some(TsconfigDiscovery::Auto) => { - let Some(tsconfig) = self.find_tsconfig(cached_path, ctx)? else { + let Some(tsconfig) = self.find_tsconfig_impl(cached_path, ctx)? else { return Ok(None); }; tsconfig @@ -185,44 +255,6 @@ impl ResolverGeneric { } Ok(None) } - - /// Find tsconfig.json of a path by traversing parent directories. - /// - /// # Errors - /// - /// * [ResolveError::Json] - pub(crate) fn find_tsconfig( - &self, - cached_path: &CachedPath, - ctx: &mut Ctx, - ) -> Result>, ResolveError> { - // Don't discover tsconfig for paths inside node_modules - if cached_path.inside_node_modules() { - return Ok(None); - } - // Skip non-absolute paths (e.g. virtual modules) - if !cached_path.path.is_absolute() { - return Ok(None); - } - - let mut cache_value = Some(cached_path.clone()); - while let Some(cv) = cache_value { - if let Some(tsconfig) = cv.tsconfig.get_or_try_init(|| { - let tsconfig_path = cv.path.join("tsconfig.json"); - let tsconfig_path = self.cache.value(&tsconfig_path); - if self.cache.is_file(&tsconfig_path, ctx) { - self.resolve_tsconfig(tsconfig_path.path()).map(Some) - } else { - Ok(None) - } - })? { - return Ok(Some(Arc::clone(tsconfig))); - } - cache_value = cv.parent(); - } - Ok(None) - } - fn get_extended_tsconfig_path( &self, directory: &CachedPath, From 62c44972f3dff94b4dec70190077b525b24c546c Mon Sep 17 00:00:00 2001 From: Boshen Date: Sat, 22 Nov 2025 16:38:48 +0800 Subject: [PATCH 2/2] add cache --- src/cache/cached_path.rs | 4 ++++ src/tsconfig_resolver.rs | 31 ++++++++++++++++++++----------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/cache/cached_path.rs b/src/cache/cached_path.rs index 2d0971a9..79f2ccd6 100644 --- a/src/cache/cached_path.rs +++ b/src/cache/cached_path.rs @@ -28,7 +28,10 @@ pub struct CachedPathImpl { pub canonicalized: OnceLock>, pub node_modules: OnceLock>>, pub package_json: OnceLock>, + /// `tsconfig.json` found at path. pub tsconfig: OnceLock>>, + /// `tsconfig.json` after resolving `references`, `files`, `include` and `extend`. + pub resolved_tsconfig: OnceLock>>, } impl CachedPathImpl { @@ -50,6 +53,7 @@ impl CachedPathImpl { node_modules: OnceLock::new(), package_json: OnceLock::new(), tsconfig: OnceLock::new(), + resolved_tsconfig: OnceLock::new(), } } } diff --git a/src/tsconfig_resolver.rs b/src/tsconfig_resolver.rs index f28326ef..f2fb7e01 100644 --- a/src/tsconfig_resolver.rs +++ b/src/tsconfig_resolver.rs @@ -51,20 +51,29 @@ impl ResolverGeneric { path: P, ) -> Result>, ResolveError> { let path = path.as_ref(); - self.find_tsconfig_tracing(path) + let cached_path = self.cache.value(path); + self.find_tsconfig_tracing(&cached_path, &mut Ctx::default()) } - fn find_tsconfig_tracing(&self, path: &Path) -> Result>, ResolveError> { - let span = tracing::debug_span!("find_tsconfig", path = ?path); + fn find_tsconfig_tracing( + &self, + cached_path: &CachedPath, + ctx: &mut Ctx, + ) -> Result>, ResolveError> { + let span = tracing::debug_span!("find_tsconfig", path = %cached_path); let _enter = span.enter(); - let cached_path = self.cache.value(path); - self.find_tsconfig_impl(&cached_path, &mut Ctx::default()).map(|option_tsconfig| { - option_tsconfig.map(|tsconfig| { - let r = TsConfig::resolve_tsconfig_solution(tsconfig, path); - tracing::debug!(path = ?path, ret = ?r); - r + cached_path + .resolved_tsconfig + .get_or_try_init(|| { + self.find_tsconfig_impl(cached_path, ctx).map(|option_tsconfig| { + option_tsconfig.map(|tsconfig| { + let r = TsConfig::resolve_tsconfig_solution(tsconfig, cached_path.path()); + tracing::debug!(path = %cached_path, ret = ?r); + r + }) + }) }) - }) + .cloned() } /// Find tsconfig.json of a path by traversing parent directories. @@ -237,7 +246,7 @@ impl ResolverGeneric { tsconfig } Some(TsconfigDiscovery::Auto) => { - let Some(tsconfig) = self.find_tsconfig_impl(cached_path, ctx)? else { + let Some(tsconfig) = self.find_tsconfig_tracing(cached_path, ctx)? else { return Ok(None); }; tsconfig