@@ -22,39 +22,62 @@ pub struct FoundConfig {
2222 pub project_options : ProjectOptions ,
2323 pub diagnostic_config : DiagnosticConfig ,
2424 pub config_path : Option < Arc < AbsPath > > ,
25+ pub most_probable_base : Arc < AbsPath > ,
2526}
2627
2728pub fn find_workspace_config (
2829 vfs : & dyn VfsHandler ,
29- workspace_dir : & AbsPath ,
30+ workspace_dir : Arc < AbsPath > ,
3031 on_check_path : impl FnMut ( & AbsPath ) ,
3132) -> anyhow:: Result < ProjectOptions > {
32- Ok ( find_mypy_config_file_in_dir ( vfs, workspace_dir, None , on_check_path) ?. project_options )
33+ let config = find_mypy_config_file_in_dir ( vfs, workspace_dir, None , on_check_path) ?;
34+
35+ Ok ( match config {
36+ Some ( config) => config. project_options ,
37+ None => {
38+ tracing:: info!( "No relevant config found" ) ;
39+ ProjectOptions :: default_for_mode ( Mode :: Default )
40+ }
41+ } )
3342}
3443
3544pub fn find_cli_config (
3645 vfs : & dyn VfsHandler ,
37- current_dir : & AbsPath ,
46+ current_dir : Arc < AbsPath > ,
3847 config_file : Option < & Path > ,
3948 mode : Option < Mode > ,
4049) -> anyhow:: Result < FoundConfig > {
4150 if let Some ( config_file) = config_file. as_ref ( ) {
4251 let Some ( config_path) = config_file. as_os_str ( ) . to_str ( ) else {
4352 anyhow:: bail!( "Expected a valid UTF-8 encoded config path" )
4453 } ;
45- let config_path = vfs. absolute_path ( current_dir, config_path) ;
54+ let config_path = vfs. absolute_path ( & current_dir, config_path) ;
4655 let s = std:: fs:: read_to_string ( config_path. as_ref ( ) )
4756 . map_err ( |err| anyhow:: anyhow!( "Issue while reading {config_path}: {err}" ) ) ?;
4857
49- let result = initialize_config ( vfs, current_dir, config_path, s, mode) ?;
58+ let most_probable_base = Arc :: from ( vfs. parent_of_absolute_path ( & config_path) . unwrap ( ) ) ;
59+ let result = initialize_config ( vfs, & current_dir, config_path, s, mode) ?;
5060 let project_options = result. 0 . unwrap_or_else ( ProjectOptions :: mypy_default) ;
5161 Ok ( FoundConfig {
5262 project_options,
5363 diagnostic_config : result. 1 ,
5464 config_path : Some ( result. 2 ) ,
65+ most_probable_base,
5566 } )
5667 } else {
57- find_mypy_config_file_in_dir ( vfs, current_dir, mode, |_| ( ) )
68+ let mut current = current_dir. clone ( ) ;
69+ loop {
70+ if let Some ( found) = find_mypy_config_file_in_dir ( vfs, current. clone ( ) , mode, |_| ( ) ) ? {
71+ return Ok ( found) ;
72+ }
73+ if let Some ( outer) = vfs. parent_of_absolute_path ( & current) {
74+ current = Arc :: from ( outer) ;
75+ } else {
76+ break ;
77+ }
78+ }
79+ tracing:: info!( "No relevant config found" ) ;
80+ Ok ( default_config ( mode, None , current_dir) )
5881 }
5982}
6083
@@ -90,28 +113,28 @@ fn initialize_config(
90113
91114fn find_mypy_config_file_in_dir (
92115 vfs : & dyn VfsHandler ,
93- dir : & AbsPath ,
116+ dir : Arc < AbsPath > ,
94117 mode : Option < Mode > ,
95118 mut on_check_path : impl FnMut ( & AbsPath ) ,
96- ) -> anyhow:: Result < FoundConfig > {
119+ ) -> anyhow:: Result < Option < FoundConfig > > {
97120 let mut end_result = None ;
98121 let mut pyproject_toml: Option < DocumentMut > = None ;
99122 for config_name in CONFIG_PATHS . iter ( ) {
100- let path = vfs. join ( dir, config_name) ;
123+ let path = vfs. join ( & dir, config_name) ;
101124 on_check_path ( & path) ;
102125 if let Ok ( mut file) = std:: fs:: File :: open ( path. as_ref ( ) ) {
103126 let mut content = String :: new ( ) ;
104127 if let Err ( err) = file. read_to_string ( & mut content) {
105128 anyhow:: bail!( "Issue while reading {path}: {err}" ) ;
106129 }
107- let config_path = vfs. absolute_path ( dir, config_name) ;
130+ let config_path = vfs. absolute_path ( & dir, config_name) ;
108131 tracing:: info!( "Potential config found: {config_path}" ) ;
109132 if * config_name == PYPROJECT_TOML_NAME {
110133 let mut diagnostic_config = DiagnosticConfig :: default ( ) ;
111134 pyproject_toml = Some ( content. parse ( ) ?) ;
112135 let project_options = ProjectOptions :: apply_pyproject_toml_mypy_part (
113136 vfs,
114- dir,
137+ & dir,
115138 & config_path,
116139 pyproject_toml. as_ref ( ) . unwrap ( ) ,
117140 & mut diagnostic_config,
@@ -122,11 +145,12 @@ fn find_mypy_config_file_in_dir(
122145 project_options,
123146 diagnostic_config,
124147 config_path : Some ( config_path) ,
148+ most_probable_base : dir. clone ( ) ,
125149 } ) ;
126150 break ;
127151 }
128152 } else {
129- let result = initialize_config ( vfs, dir, config_path, content, mode) ?;
153+ let result = initialize_config ( vfs, & dir, config_path, content, mode) ?;
130154 if let Some ( project_options) = result. 0 . or_else ( || {
131155 [ "mypy.ini" , ".mypy.ini" ] . contains ( config_name) . then ( || {
132156 // Both mypy.ini and .mypy.ini always take precedent, even if there is no [mypy]
@@ -138,39 +162,47 @@ fn find_mypy_config_file_in_dir(
138162 project_options,
139163 diagnostic_config : result. 1 ,
140164 config_path : Some ( result. 2 ) ,
165+ most_probable_base : dir. clone ( ) ,
141166 } ) ;
142167 break ;
143168 }
144169 } ;
145170 }
146171 }
147- let default_config = |config_path| FoundConfig {
148- project_options : ProjectOptions :: default_for_mode ( mode. unwrap_or ( Mode :: Default ) ) ,
149- diagnostic_config : DiagnosticConfig :: default ( ) ,
150- config_path,
151- } ;
152172 if let Some ( pyproject_toml) = pyproject_toml
153173 && let Some ( config) = pyproject_toml
154174 . get ( "tool" )
155175 . and_then ( |item| item. get ( "zuban" ) )
156176 {
157177 if end_result. is_none ( ) {
158- end_result = Some ( default_config ( Some (
159- vfs. absolute_path ( dir, PYPROJECT_TOML_NAME ) ,
160- ) ) ) ;
178+ end_result = Some ( default_config (
179+ mode,
180+ Some ( vfs. absolute_path ( & dir, PYPROJECT_TOML_NAME ) ) ,
181+ dir. clone ( ) ,
182+ ) ) ;
161183 }
162184 let found = end_result. as_mut ( ) . unwrap ( ) ;
163185 found. project_options . apply_pyproject_table (
164186 vfs,
165- dir,
187+ & dir,
166188 found. config_path . as_ref ( ) . unwrap ( ) ,
167189 & mut found. diagnostic_config ,
168190 config,
169191 true ,
170192 ) ?
171193 }
172- Ok ( end_result. unwrap_or_else ( || {
173- tracing:: info!( "No relevant config found" ) ;
174- default_config ( None )
175- } ) )
194+ Ok ( end_result)
195+ }
196+
197+ fn default_config (
198+ mode : Option < Mode > ,
199+ config_path : Option < Arc < AbsPath > > ,
200+ current_dir : Arc < AbsPath > ,
201+ ) -> FoundConfig {
202+ FoundConfig {
203+ project_options : ProjectOptions :: default_for_mode ( mode. unwrap_or ( Mode :: Default ) ) ,
204+ diagnostic_config : DiagnosticConfig :: default ( ) ,
205+ config_path,
206+ most_probable_base : current_dir,
207+ }
176208}
0 commit comments