@@ -192,17 +192,12 @@ fn resolve_module_with_package_json(
192192
193193 // Initialise `type_roots` from the `tsconfig.json` if we have one.
194194 let initialise_type_roots = options. resolve_types && options. type_roots . is_auto ( ) ;
195- let type_roots: Option < Vec < & str > > = match initialise_type_roots {
196- true => tsconfig
197- . as_ref ( )
198- . ok ( )
199- . and_then ( |tsconfig| tsconfig. compiler_options . type_roots . as_ref ( ) )
200- . map ( |type_roots| type_roots. iter ( ) . map ( String :: as_str) . collect ( ) ) ,
201- false => None ,
202- } ;
203195 let options = match initialise_type_roots {
204196 true => & options. with_type_roots_and_without_manifests ( TypeRoots :: from_optional_slice (
205- type_roots. as_deref ( ) ,
197+ tsconfig
198+ . as_ref ( )
199+ . ok ( )
200+ . and_then ( |tsconfig| tsconfig. compiler_options . type_roots . as_deref ( ) ) ,
206201 ) ) ,
207202 false => options,
208203 } ;
@@ -460,35 +455,32 @@ fn resolve_dependency(
460455) -> Result < Utf8PathBuf , ResolveError > {
461456 let ( package_name, subpath) = parse_package_specifier ( specifier) ?;
462457
463- if let TypeRoots :: Explicit ( type_roots) = options. type_roots {
464- for type_root in type_roots {
465- let package_path = base_dir. join ( type_root) . join ( package_name) ;
466- match resolve_package_path ( & package_path, subpath, fs, options) {
467- Ok ( path) => return Ok ( path) ,
468- Err ( ResolveError :: NotFound ) => { /* continue */ }
469- Err ( error) => return Err ( error) ,
470- }
458+ for type_root in options. type_roots . explicit_roots ( ) {
459+ let package_path = base_dir. join ( type_root) . join ( package_name) ;
460+ match resolve_package_path ( & package_path, subpath, fs, options) {
461+ Ok ( path) => return Ok ( path) ,
462+ Err ( ResolveError :: NotFound ) => { /* continue */ }
463+ Err ( error) => return Err ( error) ,
464+ }
471465
472- // FIXME: This is an incomplete approximation of how resolving
473- // inside custom `typeRoots` should work. Besides packages,
474- // type roots may contain individual `d.ts` files. Such files
475- // don't even need to match the name of the package, because
476- // they can do things such as
477- // `declare module "whatever_package_name"`. But to get these
478- // things to work reliably, we need to track **global** type
479- // definitions first, so for now we'll assume a correlation
480- // between package name and module name.
481- for extension in options. extensions {
482- if let Some ( extension) = definition_extension_for_js_extension ( extension) {
483- let path = package_path. with_extension ( extension) ;
484- match fs. path_info ( & path) {
485- Ok ( PathInfo :: File ) => return Ok ( normalize_path ( & path) ) ,
486- Ok ( PathInfo :: Symlink {
487- canonicalized_target,
488- } ) => return Ok ( canonicalized_target) ,
489- _ => { /* continue */ }
490- } ;
491- }
466+ // FIXME: This is an incomplete approximation of how resolving inside
467+ // custom `typeRoots` should work. Besides packages, type roots
468+ // may contain individual `d.ts` files. Such files don't even
469+ // need to match the name of the package, because they can do
470+ // things such as `declare module "whatever_package_name"`. But
471+ // to get these things to work reliably, we need to track
472+ // **global** type definitions first, so for now we'll assume a
473+ // correlation between package name and module name.
474+ for extension in options. extensions {
475+ if let Some ( extension) = definition_extension_for_js_extension ( extension) {
476+ let path = package_path. with_extension ( extension) ;
477+ match fs. path_info ( & path) {
478+ Ok ( PathInfo :: File ) => return Ok ( normalize_path ( & path) ) ,
479+ Ok ( PathInfo :: Symlink {
480+ canonicalized_target,
481+ } ) => return Ok ( canonicalized_target) ,
482+ _ => { /* continue */ }
483+ } ;
492484 }
493485 }
494486 }
@@ -935,6 +927,12 @@ pub enum TypeRoots<'a> {
935927 /// Relative paths are resolved from the package path.
936928 Explicit ( & ' a [ & ' a str ] ) ,
937929
930+ /// Explicit list of directories to search.
931+ ///
932+ /// Same as [`TypeRoots::Explicit`] except it references a slice of owned
933+ /// strings.
934+ ExplicitOwned ( & ' a [ String ] ) ,
935+
938936 /// The default value to use if no `compilerOptions.typeRoots` field can be
939937 /// found in the `tsconfig.json`.
940938 ///
@@ -944,18 +942,49 @@ pub enum TypeRoots<'a> {
944942}
945943
946944impl < ' a > TypeRoots < ' a > {
947- const fn from_optional_slice ( type_roots : Option < & ' a [ & ' a str ] > ) -> Self {
945+ const fn from_optional_slice ( type_roots : Option < & ' a [ String ] > ) -> Self {
948946 match type_roots {
949- Some ( type_roots) => Self :: Explicit ( type_roots) ,
947+ Some ( type_roots) => Self :: ExplicitOwned ( type_roots) ,
950948 None => Self :: TypesInNodeModules ,
951949 }
952950 }
953951
952+ fn explicit_roots ( & self ) -> impl Iterator < Item = & str > {
953+ ExplicitTypeRootIterator {
954+ type_roots : self ,
955+ index : 0 ,
956+ }
957+ }
958+
954959 const fn is_auto ( self ) -> bool {
955960 matches ! ( self , Self :: Auto )
956961 }
957962}
958963
964+ struct ExplicitTypeRootIterator < ' a > {
965+ type_roots : & ' a TypeRoots < ' a > ,
966+ index : usize ,
967+ }
968+
969+ impl < ' a > Iterator for ExplicitTypeRootIterator < ' a > {
970+ type Item = & ' a str ;
971+
972+ fn next ( & mut self ) -> Option < Self :: Item > {
973+ match self . type_roots {
974+ TypeRoots :: Auto => None ,
975+ TypeRoots :: Explicit ( items) => items. get ( self . index ) . map ( |root| {
976+ self . index += 1 ;
977+ * root
978+ } ) ,
979+ TypeRoots :: ExplicitOwned ( items) => items. get ( self . index ) . map ( |root| {
980+ self . index += 1 ;
981+ root. as_str ( )
982+ } ) ,
983+ TypeRoots :: TypesInNodeModules => None ,
984+ }
985+ }
986+ }
987+
959988/// Reference-counted resolved path wrapped in a [Result] that may contain an
960989/// error if the resolution failed.
961990#[ derive( Clone , Debug , Eq , Hash , Ord , PartialEq , PartialOrd ) ]
0 commit comments