Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
1 change: 1 addition & 0 deletions fixtures/tsconfig/cases/root-dirs/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import {} from './foo'
5 changes: 5 additions & 0 deletions fixtures/tsconfig/cases/root-dirs/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"compilerOptions": {
"rootDirs": ["./generated"]
},
}
5 changes: 2 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ impl<Fs: FileSystem> ResolverGeneric<Fs> {
ctx: &mut Ctx,
) -> Result<CachedPath, ResolveError> {
// tsconfig-paths
if let Some(path) = self.load_tsconfig_paths(cached_path, specifier, tsconfig)? {
if let Some(path) = self.load_tsconfig_paths(cached_path, specifier, tsconfig, ctx)? {
return Ok(path);
}

Expand Down Expand Up @@ -488,11 +488,10 @@ impl<Fs: FileSystem> ResolverGeneric<Fs> {
c,
Component::CurDir | Component::ParentDir | Component::Normal(_)
)));
let cached_path = cached_path.normalize_with(specifier, self.cache.as_ref());
// a. LOAD_AS_FILE(Y + X)
// b. LOAD_AS_DIRECTORY(Y + X)
if let Some(path) = self.load_as_file_or_directory(
&cached_path,
&cached_path.normalize_with(specifier, self.cache.as_ref()),
// ensure resolve directory only when specifier is `.`
if specifier == "." { "./" } else { specifier },
tsconfig,
Expand Down
1 change: 1 addition & 0 deletions src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ mod tsconfig_discovery;
mod tsconfig_extends;
mod tsconfig_paths;
mod tsconfig_project_references;
mod tsconfig_root_dirs;
#[cfg(target_os = "windows")]
mod windows;

Expand Down
10 changes: 10 additions & 0 deletions src/tests/tsconfig_root_dirs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//! Tests for tsconfig root_dirs
use crate::{
ResolveError, ResolveOptions, Resolver, TsconfigDiscovery, TsconfigOptions, TsconfigReferences,
};

#[test]
fn test() {
let f = super::fixture_root().join("tsconfig/cases/root-dirs");
}
15 changes: 15 additions & 0 deletions src/tsconfig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,12 @@ impl TsConfig {
{
compiler_options.allow_js = Some(*allow_js);
}

if compiler_options.root_dirs.is_none()
&& let Some(root_dirs) = &tsconfig.compiler_options.root_dirs
{
compiler_options.root_dirs = Some(root_dirs.clone());
}
}
/// "Build" the root tsconfig, resolve:
///
Expand Down Expand Up @@ -326,6 +332,12 @@ impl TsConfig {
config_dir.join(stripped_path.trim_start_matches('/'));
}

if let Some(root_dirs) = &mut self.compiler_options.root_dirs {
for root_dir in root_dirs.iter_mut() {
*root_dir = config_dir.normalize_with(&root_dir);
}
}

if self.compiler_options.paths.is_some() {
// Substitute template variable in `tsconfig.compilerOptions.paths`.
for paths in self.compiler_options.paths.as_mut().unwrap().values_mut() {
Expand Down Expand Up @@ -483,6 +495,9 @@ pub struct CompilerOptions {

/// <https://www.typescriptlang.org/tsconfig/#allowJs>
pub allow_js: Option<bool>,

/// <https://www.typescriptlang.org/tsconfig/#rootDirs>
pub root_dirs: Option<Vec<PathBuf>>,
}

/// Value for the "extends" field.
Expand Down
84 changes: 83 additions & 1 deletion src/tsconfig_resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
use crate::{
CachedPath, Ctx, FileSystem, ResolveError, ResolveOptions, ResolveResult, ResolverGeneric,
SpecifierError, TsConfig, TsconfigDiscovery, TsconfigOptions, TsconfigReferences,
path::PathUtil,
path::PathUtil, specifier,
};

#[derive(Default)]
Expand Down Expand Up @@ -260,6 +260,7 @@ impl<Fs: FileSystem> ResolverGeneric<Fs> {
cached_path: &CachedPath,
specifier: &str,
tsconfig: Option<&TsConfig>,
ctx: &mut Ctx,
) -> ResolveResult {
if cached_path.inside_node_modules() {
return Ok(None);
Expand Down Expand Up @@ -296,8 +297,89 @@ impl<Fs: FileSystem> ResolverGeneric<Fs> {
return Ok(Some(resolution));
}
}
if specifier.starts_with(".")
&& let Some(path) =
self.load_tsconfig_root_dirs(&cached_path, specifier, tsconfig, ctx)?
{
return Ok(Some(path));
}
Ok(None)
}

pub(crate) fn load_tsconfig_root_dirs(
&self,
cached_path: &CachedPath,
specifier: &str,
tsconfig: &TsConfig,
ctx: &mut Ctx,
) -> ResolveResult {
debug_assert!(specifier.starts_with("."));
debug_assert!(!cached_path.inside_node_modules());
let Some(root_dirs) = &tsconfig.compiler_options.root_dirs else { return Ok(None) };

let candidate = cached_path.normalize_with(specifier, &self.cache);
let mut matched_normalized_prefix: Option<PathBuf> = None;
let mut matched_root_dir: Option<PathBuf> = None;
for root_dir in root_dirs {
let is_longest_matching_prefix = candidate.path().starts_with(root_dir)
&& matched_normalized_prefix
.as_ref()
.is_none_or(|prefix| prefix.as_os_str().len() < root_dir.as_os_str().len());
if is_longest_matching_prefix {
matched_normalized_prefix.replace(root_dir.clone());
matched_root_dir.replace(root_dir.clone());
}
}
let Some(matched_normalized_prefix) = matched_normalized_prefix else {
return Ok(None);
};
let Some(matched_root_dir) = matched_root_dir else {
return Ok(None);
};
if let Some(p) = self.load_as_file_or_directory(&candidate, ".", Some(tsconfig), ctx)? {
return Ok(Some(p));
};
let Ok(suffix) = candidate.path().strip_prefix(&matched_root_dir) else {
return Ok(None);
};
dbg!(&matched_normalized_prefix);
dbg!(&matched_root_dir);
dbg!(&candidate);
dbg!(&suffix);
for root_dir in root_dirs {
if *root_dir == matched_root_dir {
continue;
}
let candidate = root_dir.normalize_with(suffix);
}
Ok(None)
// let specifier =
// dbg!(
// cached_path
// .normalize_with(specifier, &self.cache)
// .path()
// .strip_prefix(tsconfig.directory())
// );
// if let Some(root_dirs) = &tsconfig.compiler_options.root_dirs {
// if let Ok(subpath) = cached_path
// .normalize_with(specifier, &self.cache)
// .path()
// .strip_prefix(tsconfig.directory())
// {
// dbg!(subpath);
// for root_dir in root_dirs {
// let target = tsconfig.directory().normalize_with(root_dir).join(subpath);
// let cp = self.cache.value(&target);
// if let Some(resolution) =
// self.load_as_file_or_directory(&cp, ".", Some(tsconfig), ctx)?
// {
// return Ok(Some(resolution));
// }
// }
// }
// }
}

fn get_extended_tsconfig_path(
&self,
directory: &CachedPath,
Expand Down
Loading