1
+ use globset:: Candidate ;
1
2
use ruff_linter:: {
2
3
display_settings, fs:: normalize_path_to, settings:: types:: FilePattern ,
3
4
settings:: types:: PreviewMode ,
4
5
} ;
6
+ use ruff_workspace:: resolver:: match_candidate_exclusion;
5
7
use ruff_workspace:: {
6
8
configuration:: { Configuration , FormatConfiguration , LintConfiguration , RuleSelection } ,
7
9
pyproject:: { find_user_settings_toml, settings_toml} ,
@@ -12,12 +14,13 @@ use std::{
12
14
path:: { Path , PathBuf } ,
13
15
sync:: Arc ,
14
16
} ;
15
- use walkdir:: { DirEntry , WalkDir } ;
17
+ use walkdir:: WalkDir ;
16
18
17
19
use crate :: session:: settings:: { ConfigurationPreference , ResolvedEditorSettings } ;
18
20
19
- #[ derive( Default ) ]
20
21
pub ( crate ) struct RuffSettings {
22
+ /// Settings used to manage file inclusion and exclusion.
23
+ file_resolver : ruff_workspace:: FileResolverSettings ,
21
24
/// Settings to pass into the Ruff linter.
22
25
linter : ruff_linter:: settings:: LinterSettings ,
23
26
/// Settings to pass into the Ruff formatter.
@@ -54,7 +57,7 @@ impl RuffSettings {
54
57
. ok ( )
55
58
} )
56
59
. unwrap_or_else ( || {
57
- let default_configuration = ruff_workspace :: configuration :: Configuration :: default ( ) ;
60
+ let default_configuration = Configuration :: default ( ) ;
58
61
EditorConfigurationTransformer ( editor_settings, root)
59
62
. transform ( default_configuration)
60
63
. into_settings ( root)
@@ -64,6 +67,7 @@ impl RuffSettings {
64
67
} ) ;
65
68
66
69
RuffSettings {
70
+ file_resolver : fallback. file_resolver ,
67
71
formatter : fallback. formatter ,
68
72
linter : fallback. linter ,
69
73
}
@@ -85,20 +89,18 @@ impl RuffSettingsIndex {
85
89
// Add any settings from above the workspace root.
86
90
for directory in root. ancestors ( ) {
87
91
if let Some ( pyproject) = settings_toml ( directory) . ok ( ) . flatten ( ) {
88
- if index. contains_key ( & pyproject) {
89
- continue ;
90
- }
91
-
92
92
let Ok ( settings) = ruff_workspace:: resolver:: resolve_root_settings (
93
93
& pyproject,
94
94
Relativity :: Parent ,
95
95
& EditorConfigurationTransformer ( editor_settings, root) ,
96
96
) else {
97
97
continue ;
98
98
} ;
99
+
99
100
index. insert (
100
101
directory. to_path_buf ( ) ,
101
102
Arc :: new ( RuffSettings {
103
+ file_resolver : settings. file_resolver ,
102
104
linter : settings. linter ,
103
105
formatter : settings. formatter ,
104
106
} ) ,
@@ -107,18 +109,55 @@ impl RuffSettingsIndex {
107
109
}
108
110
}
109
111
110
- // Add any settings within the workspace itself.
111
- for directory in WalkDir :: new ( root)
112
- . into_iter ( )
113
- . filter_map ( Result :: ok)
114
- . filter ( |entry| entry. file_type ( ) . is_dir ( ) )
115
- . map ( DirEntry :: into_path)
116
- {
117
- if let Some ( pyproject) = settings_toml ( & directory) . ok ( ) . flatten ( ) {
118
- if index. contains_key ( & pyproject) {
119
- continue ;
112
+ // Add any settings within the workspace itself
113
+ let mut walker = WalkDir :: new ( root) . into_iter ( ) ;
114
+
115
+ while let Some ( entry) = walker. next ( ) {
116
+ let Ok ( entry) = entry else {
117
+ continue ;
118
+ } ;
119
+
120
+ // Skip non-directories.
121
+ if !entry. file_type ( ) . is_dir ( ) {
122
+ continue ;
123
+ }
124
+
125
+ let directory = entry. into_path ( ) ;
126
+
127
+ // If the directory is excluded from the workspace, skip it.
128
+ if let Some ( file_name) = directory. file_name ( ) {
129
+ if let Some ( ( _, settings) ) = index
130
+ . range ( ..directory. clone ( ) )
131
+ . rfind ( |( path, _) | directory. starts_with ( path) )
132
+ {
133
+ let candidate = Candidate :: new ( & directory) ;
134
+ let basename = Candidate :: new ( file_name) ;
135
+ if match_candidate_exclusion (
136
+ & candidate,
137
+ & basename,
138
+ & settings. file_resolver . exclude ,
139
+ ) {
140
+ tracing:: debug!( "Ignored path via `exclude`: {}" , directory. display( ) ) ;
141
+
142
+ walker. skip_current_dir ( ) ;
143
+ continue ;
144
+ } else if match_candidate_exclusion (
145
+ & candidate,
146
+ & basename,
147
+ & settings. file_resolver . extend_exclude ,
148
+ ) {
149
+ tracing:: debug!(
150
+ "Ignored path via `extend-exclude`: {}" ,
151
+ directory. display( )
152
+ ) ;
153
+
154
+ walker. skip_current_dir ( ) ;
155
+ continue ;
156
+ }
120
157
}
158
+ }
121
159
160
+ if let Some ( pyproject) = settings_toml ( & directory) . ok ( ) . flatten ( ) {
122
161
let Ok ( settings) = ruff_workspace:: resolver:: resolve_root_settings (
123
162
& pyproject,
124
163
Relativity :: Parent ,
@@ -129,6 +168,7 @@ impl RuffSettingsIndex {
129
168
index. insert (
130
169
directory,
131
170
Arc :: new ( RuffSettings {
171
+ file_resolver : settings. file_resolver ,
132
172
linter : settings. linter ,
133
173
formatter : settings. formatter ,
134
174
} ) ,
@@ -145,8 +185,7 @@ impl RuffSettingsIndex {
145
185
if let Some ( ( _, settings) ) = self
146
186
. index
147
187
. range ( ..document_path. to_path_buf ( ) )
148
- . rev ( )
149
- . find ( |( path, _) | document_path. starts_with ( path) )
188
+ . rfind ( |( path, _) | document_path. starts_with ( path) )
150
189
{
151
190
return settings. clone ( ) ;
152
191
}
0 commit comments