@@ -76,84 +76,147 @@ pub struct Scopes {
7676 stack : Vec < Scope > ,
7777}
7878
79+ pub enum ExportFunctionDecorators {
80+ InDecoratedFunction ,
81+ InParentScope ,
82+ InDecoratedTarget ,
83+ Ignore ,
84+ }
85+
86+ pub enum ExportClassDecorators {
87+ InDecoratedClassTopLevel ,
88+ InParentScope ,
89+ Ignore ,
90+ }
91+
92+ pub enum ExportDefaultArguments {
93+ InFunction ,
94+ InParentScope ,
95+ Ignore ,
96+ }
97+
98+ pub struct ScopeExportedFunctionFlags {
99+ pub include_top_level : bool ,
100+ pub include_class_top_level : bool ,
101+ pub include_function_decorators : ExportFunctionDecorators ,
102+ pub include_class_decorators : ExportClassDecorators ,
103+ pub include_default_arguments : ExportDefaultArguments ,
104+ }
105+
79106impl Scopes {
80107 pub fn current_exported_function (
81108 & self ,
82109 module_id : ModuleId ,
83110 module_name : ModuleName ,
84- include_top_level : bool ,
85- include_class_top_level : bool ,
86- include_decorators_in_decorated_definition : bool ,
87- include_default_arguments_in_function : bool ,
111+ flags : ScopeExportedFunctionFlags ,
88112 ) -> Option < FunctionRef > {
89- let mut iterator = self . stack . iter ( ) . rev ( ) ;
90- loop {
91- match iterator. next ( ) . unwrap ( ) {
92- Scope :: TopLevel => {
93- if include_top_level {
94- return Some ( FunctionRef {
95- module_id,
96- module_name,
97- function_id : FunctionId :: ModuleTopLevel ,
98- function_name : Name :: from ( "$toplevel" ) ,
99- } ) ;
100- } else {
101- return None ;
102- }
113+ Self :: current_exported_function_impl ( self . stack . iter ( ) . rev ( ) , module_id, module_name, flags)
114+ }
115+
116+ fn current_exported_function_impl < ' a > (
117+ mut iterator : impl Iterator < Item = & ' a Scope > ,
118+ module_id : ModuleId ,
119+ module_name : ModuleName ,
120+ flags : ScopeExportedFunctionFlags ,
121+ ) -> Option < FunctionRef > {
122+ match iterator. next ( ) . unwrap ( ) {
123+ Scope :: TopLevel => {
124+ if flags. include_top_level {
125+ Some ( FunctionRef {
126+ module_id,
127+ module_name,
128+ function_id : FunctionId :: ModuleTopLevel ,
129+ function_name : Name :: from ( "$toplevel" ) ,
130+ } )
131+ } else {
132+ None
103133 }
104- Scope :: ExportedFunction {
105- function_id,
106- function_name,
107- ..
108- } => {
109- return Some ( FunctionRef {
134+ }
135+ Scope :: ExportedFunction {
136+ function_id,
137+ function_name,
138+ ..
139+ } => Some ( FunctionRef {
140+ module_id,
141+ module_name,
142+ function_id : function_id. clone ( ) ,
143+ function_name : function_name. clone ( ) ,
144+ } ) ,
145+ Scope :: NonExportedFunction { .. } => None ,
146+ Scope :: ExportedClass { class_id, .. } => {
147+ if flags. include_class_top_level {
148+ Some ( FunctionRef {
110149 module_id,
111150 module_name,
112- function_id : function_id. clone ( ) ,
113- function_name : function_name. clone ( ) ,
114- } ) ;
151+ function_id : FunctionId :: ClassTopLevel {
152+ class_id : * class_id,
153+ } ,
154+ function_name : Name :: from ( "$class_toplevel" ) ,
155+ } )
156+ } else {
157+ None
115158 }
116- Scope :: NonExportedFunction { .. } => {
117- return None ;
159+ }
160+ Scope :: NonExportedClass { .. } => None ,
161+ Scope :: FunctionParameters => match flags. include_default_arguments {
162+ ExportDefaultArguments :: InFunction => {
163+ Self :: current_exported_function_impl ( iterator, module_id, module_name, flags)
118164 }
119- Scope :: ExportedClass { class_id, .. } => {
120- if include_class_top_level {
121- return Some ( FunctionRef {
122- module_id,
123- module_name,
124- function_id : FunctionId :: ClassTopLevel {
125- class_id : * class_id,
126- } ,
127- function_name : Name :: from ( "$class_toplevel" ) ,
128- } ) ;
129- } else {
130- return None ;
131- }
165+ ExportDefaultArguments :: InParentScope => {
166+ iterator. next ( ) . unwrap ( ) ;
167+ Self :: current_exported_function_impl ( iterator, module_id, module_name, flags)
132168 }
133- Scope :: NonExportedClass { .. } => {
134- return None ;
169+ ExportDefaultArguments :: Ignore => None ,
170+ } ,
171+ Scope :: FunctionTypeParams
172+ | Scope :: FunctionReturnAnnotation
173+ | Scope :: ClassTypeParams
174+ | Scope :: ClassArguments => {
175+ // These are not true "semantic" scopes.
176+ // We need to skip the parent scope, which is the wrapping function/class scope.
177+ iterator. next ( ) . unwrap ( ) ;
178+ Self :: current_exported_function_impl ( iterator, module_id, module_name, flags)
179+ }
180+ Scope :: ClassDecorators => match flags. include_class_decorators {
181+ ExportClassDecorators :: InDecoratedClassTopLevel => {
182+ Self :: current_exported_function_impl ( iterator, module_id, module_name, flags)
135183 }
136- Scope :: FunctionParameters => {
137- if !include_default_arguments_in_function {
138- // This not a true "semantic" scope.
139- // We need to skip the parent scope, which is the wrapping function/class scope.
140- iterator. next ( ) . unwrap ( ) ;
141- }
184+ ExportClassDecorators :: InParentScope => {
185+ iterator. next ( ) . unwrap ( ) ;
186+ Self :: current_exported_function_impl ( iterator, module_id, module_name, flags)
142187 }
143- Scope :: FunctionTypeParams
144- | Scope :: FunctionReturnAnnotation
145- | Scope :: ClassTypeParams
146- | Scope :: ClassArguments => {
147- // These are not true "semantic" scopes.
148- // We need to skip the parent scope, which is the wrapping function/class scope.
188+ ExportClassDecorators :: Ignore => None ,
189+ } ,
190+ Scope :: FunctionDecorators => match flags. include_function_decorators {
191+ ExportFunctionDecorators :: InDecoratedFunction => {
192+ Self :: current_exported_function_impl ( iterator, module_id, module_name, flags)
193+ }
194+ ExportFunctionDecorators :: InParentScope => {
149195 iterator. next ( ) . unwrap ( ) ;
196+ Self :: current_exported_function_impl ( iterator, module_id, module_name, flags)
150197 }
151- Scope :: FunctionDecorators | Scope :: ClassDecorators => {
152- if !include_decorators_in_decorated_definition {
153- iterator. next ( ) . unwrap ( ) ;
198+ ExportFunctionDecorators :: InDecoratedTarget => {
199+ match Self :: current_exported_function_impl (
200+ iterator,
201+ module_id,
202+ module_name,
203+ flags,
204+ ) {
205+ Some ( FunctionRef {
206+ function_id : FunctionId :: Function { location } ,
207+ function_name,
208+ ..
209+ } ) => Some ( FunctionRef {
210+ module_id,
211+ module_name,
212+ function_id : FunctionId :: FunctionDecoratedTarget { location } ,
213+ function_name,
214+ } ) ,
215+ _ => None ,
154216 }
155217 }
156- }
218+ ExportFunctionDecorators :: Ignore => None ,
219+ } ,
157220 }
158221 }
159222}
@@ -192,33 +255,58 @@ impl ScopeId {
192255}
193256
194257pub trait AstScopedVisitor {
195- fn visit_statement ( & mut self , _stmt : & Stmt , _scopes : & Scopes ) { }
258+ fn visit_statement ( & mut self , stmt : & Stmt , scopes : & Scopes ) {
259+ let _ = stmt;
260+ let _ = scopes;
261+ }
196262 fn visit_expression (
197263 & mut self ,
198- _expr : & Expr ,
199- _scopes : & Scopes ,
200- _parent_expression : Option < & Expr > ,
264+ expr : & Expr ,
265+ scopes : & Scopes ,
266+ parent_expression : Option < & Expr > ,
201267 // If the current expression is in an assignment, this is the left side of the assignment
202- _assignment_targets : Option < & Vec < & Expr > > ,
268+ assignment_targets : Option < & Vec < & Expr > > ,
203269 ) {
270+ let _ = expr;
271+ let _ = scopes;
272+ let _ = parent_expression;
273+ let _ = assignment_targets;
204274 }
205275 fn enter_function_scope (
206276 & mut self ,
207- _function_def : & StmtFunctionDef ,
208- _scopes_in_function : & Scopes ,
277+ function_def : & StmtFunctionDef ,
278+ scopes_in_function : & Scopes ,
209279 ) {
280+ let _ = function_def;
281+ let _ = scopes_in_function;
210282 }
211283 fn exit_function_scope (
212284 & mut self ,
213- _function_def : & StmtFunctionDef ,
214- _scopes_outside_function : & Scopes ,
285+ function_def : & StmtFunctionDef ,
286+ scopes_outside_function : & Scopes ,
215287 ) {
288+ let _ = function_def;
289+ let _ = scopes_outside_function;
290+ }
291+ fn enter_class_scope ( & mut self , class_def : & StmtClassDef , scopes_in_class : & Scopes ) {
292+ let _ = class_def;
293+ let _ = scopes_in_class;
294+ }
295+ fn exit_class_scope ( & mut self , function_def : & StmtClassDef , scopes_outside_class : & Scopes ) {
296+ let _ = function_def;
297+ let _ = scopes_outside_class;
298+ }
299+ fn enter_toplevel_scope ( & mut self , ast : & ModModule , scopes_in_toplevel : & Scopes ) {
300+ let _ = ast;
301+ let _ = scopes_in_toplevel;
302+ }
303+ fn exit_toplevel_scope ( & mut self , ast : & ModModule , scopes_in_toplevel : & Scopes ) {
304+ let _ = ast;
305+ let _ = scopes_in_toplevel;
306+ }
307+ fn on_scope_update ( & mut self , scopes : & Scopes ) {
308+ let _ = scopes;
216309 }
217- fn enter_class_scope ( & mut self , _class_def : & StmtClassDef , _scopes_in_class : & Scopes ) { }
218- fn exit_class_scope ( & mut self , _function_def : & StmtClassDef , _scopes_outside_class : & Scopes ) { }
219- fn enter_toplevel_scope ( & mut self , _ast : & ModModule , _scopes_in_toplevel : & Scopes ) { }
220- fn exit_toplevel_scope ( & mut self , _ast : & ModModule , _scopes_in_toplevel : & Scopes ) { }
221- fn on_scope_update ( & mut self , _scopes : & Scopes ) { }
222310 fn visit_type_annotations ( ) -> bool ;
223311}
224312
@@ -305,26 +393,28 @@ fn visit_statement<V: AstScopedVisitor>(
305393 visitor. enter_function_scope ( function_def, scopes) ;
306394 visitor. on_scope_update ( scopes) ;
307395
308- scopes. stack . push ( Scope :: FunctionDecorators ) ;
309- visitor. on_scope_update ( scopes) ;
310- function_def. decorator_list . iter ( ) . for_each ( & mut |e| {
311- ruff_python_ast:: visitor:: source_order:: SourceOrderVisitor :: visit_decorator (
312- & mut CustomSourceOrderVisitor {
313- visitor,
314- scopes,
315- module_context,
316- parent_expression : None ,
317- assignment_targets : None ,
318- } ,
319- e,
320- )
321- } ) ;
322- scopes. stack . pop ( ) ;
323- visitor. on_scope_update ( scopes) ;
396+ if !function_def. decorator_list . is_empty ( ) {
397+ scopes. stack . push ( Scope :: FunctionDecorators ) ;
398+ visitor. on_scope_update ( scopes) ;
399+ function_def. decorator_list . iter ( ) . for_each ( & mut |e| {
400+ ruff_python_ast:: visitor:: source_order:: SourceOrderVisitor :: visit_decorator (
401+ & mut CustomSourceOrderVisitor {
402+ visitor,
403+ scopes,
404+ module_context,
405+ parent_expression : None ,
406+ assignment_targets : None ,
407+ } ,
408+ e,
409+ )
410+ } ) ;
411+ scopes. stack . pop ( ) ;
412+ visitor. on_scope_update ( scopes) ;
413+ }
324414
325- scopes. stack . push ( Scope :: FunctionTypeParams ) ;
326- visitor. on_scope_update ( scopes) ;
327415 if let Some ( type_params) = & function_def. type_params {
416+ scopes. stack . push ( Scope :: FunctionTypeParams ) ;
417+ visitor. on_scope_update ( scopes) ;
328418 ruff_python_ast:: visitor:: source_order:: SourceOrderVisitor :: visit_type_params (
329419 & mut CustomSourceOrderVisitor {
330420 visitor,
@@ -335,9 +425,9 @@ fn visit_statement<V: AstScopedVisitor>(
335425 } ,
336426 type_params,
337427 ) ;
428+ scopes. stack . pop ( ) ;
429+ visitor. on_scope_update ( scopes) ;
338430 }
339- scopes. stack . pop ( ) ;
340- visitor. on_scope_update ( scopes) ;
341431
342432 scopes. stack . push ( Scope :: FunctionParameters ) ;
343433 visitor. on_scope_update ( scopes) ;
@@ -354,22 +444,24 @@ fn visit_statement<V: AstScopedVisitor>(
354444 scopes. stack . pop ( ) ;
355445 visitor. on_scope_update ( scopes) ;
356446
357- scopes. stack . push ( Scope :: FunctionReturnAnnotation ) ;
358- visitor. on_scope_update ( scopes) ;
359- function_def. returns . iter ( ) . for_each ( |return_annotation| {
360- ruff_python_ast:: visitor:: source_order:: SourceOrderVisitor :: visit_annotation (
361- & mut CustomSourceOrderVisitor {
362- visitor,
363- scopes,
364- module_context,
365- parent_expression : None ,
366- assignment_targets : None ,
367- } ,
368- return_annotation,
369- ) ;
370- } ) ;
371- scopes. stack . pop ( ) ;
372- visitor. on_scope_update ( scopes) ;
447+ if function_def. returns . is_some ( ) {
448+ scopes. stack . push ( Scope :: FunctionReturnAnnotation ) ;
449+ visitor. on_scope_update ( scopes) ;
450+ function_def. returns . iter ( ) . for_each ( |return_annotation| {
451+ ruff_python_ast:: visitor:: source_order:: SourceOrderVisitor :: visit_annotation (
452+ & mut CustomSourceOrderVisitor {
453+ visitor,
454+ scopes,
455+ module_context,
456+ parent_expression : None ,
457+ assignment_targets : None ,
458+ } ,
459+ return_annotation,
460+ ) ;
461+ } ) ;
462+ scopes. stack . pop ( ) ;
463+ visitor. on_scope_update ( scopes) ;
464+ }
373465
374466 for stmt in & function_def. body {
375467 visit_statement ( stmt, visitor, scopes, module_context) ;
0 commit comments