Repository: oxc-project/oxc-resolver
Pull request #91 (2024-02-19 08:21:16)

fix: extending tsconfig paths with baseUrl in original tsconfig file
relates https://github.com/web-infra-dev/rspack/issues/5671

Boshen: Current dependencies on/for this PR:
* `main`
  * **PR #91** <a href="https://app.graphite.dev/github/pr/oxc-project/oxc-resolver/91?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a>  👈

This [stack of pull requests](https://stacking.dev/?utm_source=stack-comment) is managed by [Graphite](https://app.graphite.dev/github/pr/oxc-project/oxc-resolver/91?utm_source=stack-comment).
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/oxc-project/oxc-resolver/pull/91?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=oxc-project) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Comparison is base [(`1f58113`)](https://app.codecov.io/gh/oxc-project/oxc-resolver/commit/1f581132b864f0ab3860bf0c38ac3be57c2765c9?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=oxc-project) 93.50% compared to head [(`586b3d6`)](https://app.codecov.io/gh/oxc-project/oxc-resolver/pull/91?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=oxc-project) 93.51%.
> Report is 4 commits behind head on main.


<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main      #91   +/-   ##
=======================================
  Coverage   93.50%   93.51%           
=======================================
  Files          11       11           
  Lines        2170     2173    +3     
=======================================
+ Hits         2029     2032    +3     
  Misses        141      141           
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/oxc-project/oxc-resolver/pull/91?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=oxc-project).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=oxc-project).


Patch:
diff --git a/fixtures/parcel/tsconfig/extends-paths/src/index.js b/fixtures/parcel/tsconfig/extends-paths/src/index.js
new file mode 100644
index 0000000..e69de29
diff --git a/fixtures/parcel/tsconfig/extends-paths/tsconfig.base.json b/fixtures/parcel/tsconfig/extends-paths/tsconfig.base.json
new file mode 100644
index 0000000..5c64b06
--- /dev/null
+++ b/fixtures/parcel/tsconfig/extends-paths/tsconfig.base.json
@@ -0,0 +1,7 @@
+{
+	"compilerOptions": {
+		"paths": {
+			"@/*": ["./*"]
+		}
+	}
+}
diff --git a/fixtures/parcel/tsconfig/extends-paths/tsconfig.json b/fixtures/parcel/tsconfig/extends-paths/tsconfig.json
new file mode 100644
index 0000000..5108601
--- /dev/null
+++ b/fixtures/parcel/tsconfig/extends-paths/tsconfig.json
@@ -0,0 +1,6 @@
+{
+  "extends":	"./tsconfig.base.json",
+  "compilerOptions": {
+    "baseUrl": "src",
+  },
+}
diff --git a/src/tsconfig.rs b/src/tsconfig.rs
index 9f12c33..166136a 100644
--- a/src/tsconfig.rs
+++ b/src/tsconfig.rs
@@ -87,13 +87,16 @@ impl TsConfig {
 
     pub fn extend_tsconfig(&mut self, tsconfig: &Self) {
         let compiler_options = &mut self.compiler_options;
-        if compiler_options.base_url.is_none() {
-            compiler_options.base_url = tsconfig.compiler_options.base_url.clone();
-        }
         if compiler_options.paths.is_none() {
-            compiler_options.paths_base = tsconfig.compiler_options.paths_base.clone();
+            compiler_options.paths_base = compiler_options
+                .base_url
+                .as_ref()
+                .map_or_else(|| tsconfig.compiler_options.paths_base.clone(), Clone::clone);
             compiler_options.paths = tsconfig.compiler_options.paths.clone();
         }
+        if compiler_options.base_url.is_none() {
+            compiler_options.base_url = tsconfig.compiler_options.base_url.clone();
+        }
     }
 
     pub fn resolve(&self, path: &Path, specifier: &str) -> Vec<PathBuf> {


Test patch:
diff --git a/src/tests/tsconfig_paths.rs b/src/tests/tsconfig_paths.rs
index 66c52c6..02510e5 100644
--- a/src/tests/tsconfig_paths.rs
+++ b/src/tests/tsconfig_paths.rs
@@ -18,24 +18,26 @@ fn tsconfig() {
 
     #[rustfmt::skip]
     let pass = [
-        (f.clone(), "ts-path", f.join("foo.js")),
-        (f.join("nested"), "ts-path", f.join("nested/test.js")),
-        (f.join("tsconfig/index"), "foo", f.join("node_modules/tsconfig-index/foo.js")),
+        (f.clone(), None, "ts-path", f.join("foo.js")),
+        (f.join("nested"), None, "ts-path", f.join("nested/test.js")),
+        (f.join("tsconfig/index"), None, "foo", f.join("node_modules/tsconfig-index/foo.js")),
         // This requires reading package.json.tsconfig field
         // (f.join("tsconfig/field"), "foo", f.join("node_modules/tsconfig-field/foo.js"))
-        (f.join("tsconfig/exports"), "foo", f.join("node_modules/tsconfig-exports/foo.js")),
-        (f.join("tsconfig/extends-extension"), "foo", f.join("tsconfig/extends-extension/foo.js")),
-        (f.join("tsconfig/extends-extensionless"), "foo", f.join("node_modules/tsconfig-field/foo.js"))
+        (f.join("tsconfig/exports"), None, "foo", f.join("node_modules/tsconfig-exports/foo.js")),
+        (f.join("tsconfig/extends-extension"), None, "foo", f.join("tsconfig/extends-extension/foo.js")),
+        (f.join("tsconfig/extends-extensionless"), None, "foo", f.join("node_modules/tsconfig-field/foo.js")),
+        (f.join("tsconfig/extends-paths"), Some("src"), "@/index", f.join("tsconfig/extends-paths/src/index.js")),
     ];
 
-    for (path, request, expected) in pass {
+    for (dir, subdir, request, expected) in pass {
         let resolver = Resolver::new(ResolveOptions {
             tsconfig: Some(TsconfigOptions {
-                config_file: path.join("tsconfig.json"),
+                config_file: dir.join("tsconfig.json"),
                 references: TsconfigReferences::Auto,
             }),
             ..ResolveOptions::default()
         });
+        let path = subdir.map_or(dir.clone(), |subdir| dir.join(subdir));
         let resolved_path = resolver.resolve(&path, request).map(|f| f.full_path());
         assert_eq!(resolved_path, Ok(expected), "{request} {path:?}");
     }