@@ -23,6 +23,12 @@ pub struct ResolveSettings {
2323 /// Maximum number of results from `global_name` before discarding
2424 /// as too ambiguous. Prevents fan-out on common names.
2525 pub global_name_max_results : usize ,
26+ /// When set, restrict the qualified-name fast path (resolver.rs) to
27+ /// definitions in the SAME DIRECTORY as the referencing file. For
28+ /// languages whose module scope is a directory (Terraform/HCL), this
29+ /// stops a `local.x` / `type.name` reference from resolving to a
30+ /// same-named definition in an unrelated module directory.
31+ pub same_directory_scope : bool ,
2632}
2733
2834impl Default for ResolveSettings {
@@ -34,10 +40,20 @@ impl Default for ResolveSettings {
3440 compound_key_recovery : true ,
3541 implicit_scope_on_base : true ,
3642 global_name_max_results : 5 ,
43+ same_directory_scope : false ,
3744 }
3845 }
3946}
4047
48+ /// The directory portion of a file path (everything before the last `/`),
49+ /// or `""` for a repo-root file. Used for directory-scoped resolution.
50+ pub ( crate ) fn dir_of ( path : & str ) -> & str {
51+ match path. rfind ( '/' ) {
52+ Some ( i) => & path[ ..i] ,
53+ None => "" ,
54+ }
55+ }
56+
4157// ── ImportResolver ──────────────────────────────────────────────
4258
4359/// Per-file import resolver. Holds shared state so individual
@@ -381,3 +397,28 @@ impl<'a> ImportResolver<'a> {
381397 . collect ( )
382398 }
383399}
400+
401+ #[ cfg( test) ]
402+ mod tests {
403+ use super :: dir_of;
404+
405+ #[ test]
406+ fn dir_of_nested_path ( ) {
407+ assert_eq ! ( dir_of( "modules/vpc/main.tf" ) , "modules/vpc" ) ;
408+ }
409+
410+ #[ test]
411+ fn dir_of_root_file ( ) {
412+ assert_eq ! ( dir_of( "main.tf" ) , "" ) ;
413+ }
414+
415+ #[ test]
416+ fn dir_of_empty ( ) {
417+ assert_eq ! ( dir_of( "" ) , "" ) ;
418+ }
419+
420+ #[ test]
421+ fn dir_of_trailing_slash ( ) {
422+ assert_eq ! ( dir_of( "a/b/" ) , "a/b" ) ;
423+ }
424+ }
0 commit comments