@@ -212,16 +212,9 @@ pub(crate) enum GotoTarget<'a> {
212212
213213/// The resolved definitions for a `GotoTarget`
214214#[ derive( Debug , Clone ) ]
215- pub ( crate ) enum DefinitionsOrTargets < ' db > {
216- /// We computed actual Definitions we can do followup queries on.
217- Definitions ( Vec < ResolvedDefinition < ' db > > ) ,
218- /// We directly computed a navigation.
219- ///
220- /// We can't get docs or usefully compute goto-definition for this.
221- Targets ( crate :: NavigationTargets ) ,
222- }
215+ pub ( crate ) struct Definitions < ' db > ( pub Vec < ResolvedDefinition < ' db > > ) ;
223216
224- impl < ' db > DefinitionsOrTargets < ' db > {
217+ impl < ' db > Definitions < ' db > {
225218 pub ( crate ) fn from_ty ( db : & ' db dyn crate :: Db , ty : Type < ' db > ) -> Option < Self > {
226219 let ty_def = ty. definition ( db) ?;
227220 let resolved = match ty_def {
@@ -237,7 +230,7 @@ impl<'db> DefinitionsOrTargets<'db> {
237230 ResolvedDefinition :: Definition ( definition)
238231 }
239232 } ;
240- Some ( DefinitionsOrTargets :: Definitions ( vec ! [ resolved] ) )
233+ Some ( Definitions ( vec ! [ resolved] ) )
241234 }
242235
243236 /// Get the "goto-declaration" interpretation of this definition
@@ -247,12 +240,7 @@ impl<'db> DefinitionsOrTargets<'db> {
247240 self ,
248241 db : & ' db dyn ty_python_semantic:: Db ,
249242 ) -> Option < crate :: NavigationTargets > {
250- match self {
251- DefinitionsOrTargets :: Definitions ( definitions) => {
252- definitions_to_navigation_targets ( db, None , definitions)
253- }
254- DefinitionsOrTargets :: Targets ( targets) => Some ( targets) ,
255- }
243+ definitions_to_navigation_targets ( db, None , self . 0 )
256244 }
257245
258246 /// Get the "goto-definition" interpretation of this definition
@@ -263,12 +251,7 @@ impl<'db> DefinitionsOrTargets<'db> {
263251 self ,
264252 db : & ' db dyn ty_python_semantic:: Db ,
265253 ) -> Option < crate :: NavigationTargets > {
266- match self {
267- DefinitionsOrTargets :: Definitions ( definitions) => {
268- definitions_to_navigation_targets ( db, Some ( & StubMapper :: new ( db) ) , definitions)
269- }
270- DefinitionsOrTargets :: Targets ( targets) => Some ( targets) ,
271- }
254+ definitions_to_navigation_targets ( db, Some ( & StubMapper :: new ( db) ) , self . 0 )
272255 }
273256
274257 /// Get the docstring for this definition
@@ -277,13 +260,7 @@ impl<'db> DefinitionsOrTargets<'db> {
277260 /// so this will check both the goto-declarations and goto-definitions (in that order)
278261 /// and return the first one found.
279262 pub ( crate ) fn docstring ( self , db : & ' db dyn crate :: Db ) -> Option < Docstring > {
280- let definitions = match self {
281- DefinitionsOrTargets :: Definitions ( definitions) => definitions,
282- // Can't find docs for these
283- // (make more cases DefinitionOrTargets::Definitions to get more docs!)
284- DefinitionsOrTargets :: Targets ( _) => return None ,
285- } ;
286- for definition in & definitions {
263+ for definition in & self . 0 {
287264 // If we got a docstring from the original definition, use it
288265 if let Some ( docstring) = definition. docstring ( db) {
289266 return Some ( Docstring :: new ( docstring) ) ;
@@ -296,7 +273,7 @@ impl<'db> DefinitionsOrTargets<'db> {
296273 let stub_mapper = StubMapper :: new ( db) ;
297274
298275 // Try to find the corresponding implementation definition
299- for definition in stub_mapper. map_definitions ( definitions ) {
276+ for definition in stub_mapper. map_definitions ( self . 0 ) {
300277 if let Some ( docstring) = definition. docstring ( db) {
301278 return Some ( Docstring :: new ( docstring) ) ;
302279 }
@@ -399,36 +376,32 @@ impl GotoTarget<'_> {
399376 & self ,
400377 model : & SemanticModel < ' db > ,
401378 alias_resolution : ImportAliasResolution ,
402- ) -> Option < DefinitionsOrTargets < ' db > > {
403- use crate :: NavigationTarget ;
404- match self {
405- GotoTarget :: Expression ( expression) => definitions_for_expression ( model, * expression)
406- . map ( DefinitionsOrTargets :: Definitions ) ,
379+ ) -> Option < Definitions < ' db > > {
380+ let definitions = match self {
381+ GotoTarget :: Expression ( expression) => definitions_for_expression ( model, * expression) ,
407382 // For already-defined symbols, they are their own definitions
408- GotoTarget :: FunctionDef ( function) => Some ( DefinitionsOrTargets :: Definitions ( vec ! [
409- ResolvedDefinition :: Definition ( function. definition( model) ) ,
410- ] ) ) ,
383+ GotoTarget :: FunctionDef ( function) => Some ( vec ! [ ResolvedDefinition :: Definition (
384+ function. definition( model) ,
385+ ) ] ) ,
411386
412- GotoTarget :: ClassDef ( class) => Some ( DefinitionsOrTargets :: Definitions ( vec ! [
413- ResolvedDefinition :: Definition ( class. definition( model) ) ,
414- ] ) ) ,
387+ GotoTarget :: ClassDef ( class) => Some ( vec ! [ ResolvedDefinition :: Definition (
388+ class. definition( model) ,
389+ ) ] ) ,
415390
416- GotoTarget :: Parameter ( parameter) => Some ( DefinitionsOrTargets :: Definitions ( vec ! [
417- ResolvedDefinition :: Definition ( parameter. definition( model) ) ,
418- ] ) ) ,
391+ GotoTarget :: Parameter ( parameter) => Some ( vec ! [ ResolvedDefinition :: Definition (
392+ parameter. definition( model) ,
393+ ) ] ) ,
419394
420395 // For import aliases (offset within 'y' or 'z' in "from x import y as z")
421396 GotoTarget :: ImportSymbolAlias {
422397 alias, import_from, ..
423398 } => {
424399 let symbol_name = alias. name . as_str ( ) ;
425- Some ( DefinitionsOrTargets :: Definitions (
426- definitions_for_imported_symbol (
427- model,
428- import_from,
429- symbol_name,
430- alias_resolution,
431- ) ,
400+ Some ( definitions_for_imported_symbol (
401+ model,
402+ import_from,
403+ symbol_name,
404+ alias_resolution,
432405 ) )
433406 }
434407
@@ -448,60 +421,54 @@ impl GotoTarget<'_> {
448421 if alias_resolution == ImportAliasResolution :: ResolveAliases {
449422 definitions_for_module ( model, Some ( alias. name . as_str ( ) ) , 0 )
450423 } else {
451- let alias_range = alias. asname . as_ref ( ) . unwrap ( ) . range ;
452- Some ( DefinitionsOrTargets :: Targets (
453- crate :: NavigationTargets :: single ( NavigationTarget {
454- file : model. file ( ) ,
455- focus_range : alias_range,
456- full_range : alias. range ( ) ,
457- } ) ,
458- ) )
424+ alias. asname . as_ref ( ) . map ( |name| {
425+ definitions_for_name ( model, name. as_str ( ) , AnyNodeRef :: Identifier ( name) )
426+ } )
459427 }
460428 }
461429
462430 // Handle keyword arguments in call expressions
463431 GotoTarget :: KeywordArgument {
464432 keyword,
465433 call_expression,
466- } => Some ( DefinitionsOrTargets :: Definitions (
467- definitions_for_keyword_argument ( model, keyword, call_expression) ,
434+ } => Some ( definitions_for_keyword_argument (
435+ model,
436+ keyword,
437+ call_expression,
468438 ) ) ,
469439
470440 // For exception variables, they are their own definitions (like parameters)
471441 GotoTarget :: ExceptVariable ( except_handler) => {
472- Some ( DefinitionsOrTargets :: Definitions ( vec ! [
473- ResolvedDefinition :: Definition ( except_handler. definition( model) ) ,
474- ] ) )
442+ Some ( vec ! [ ResolvedDefinition :: Definition (
443+ except_handler. definition( model) ,
444+ ) ] )
475445 }
476446
477- // For pattern match rest variables, they are their own definitions
447+ // Patterns are glorified assignments but we have to look them up by ident
448+ // because they're not expressions
478449 GotoTarget :: PatternMatchRest ( pattern_mapping) => {
479- if let Some ( rest_name) = & pattern_mapping. rest {
480- let range = rest_name. range ;
481- Some ( DefinitionsOrTargets :: Targets (
482- crate :: NavigationTargets :: single ( NavigationTarget :: new (
483- model. file ( ) ,
484- range,
485- ) ) ,
486- ) )
487- } else {
488- None
489- }
450+ pattern_mapping. rest . as_ref ( ) . map ( |name| {
451+ definitions_for_name ( model, name. as_str ( ) , AnyNodeRef :: Identifier ( name) )
452+ } )
490453 }
491454
492- // For pattern match as names, they are their own definitions
493- GotoTarget :: PatternMatchAsName ( pattern_as) => {
494- if let Some ( name) = & pattern_as. name {
495- let range = name. range ;
496- Some ( DefinitionsOrTargets :: Targets (
497- crate :: NavigationTargets :: single ( NavigationTarget :: new (
498- model. file ( ) ,
499- range,
500- ) ) ,
501- ) )
502- } else {
503- None
504- }
455+ GotoTarget :: PatternMatchAsName ( pattern_as) => pattern_as. name . as_ref ( ) . map ( |name| {
456+ definitions_for_name ( model, name. as_str ( ) , AnyNodeRef :: Identifier ( name) )
457+ } ) ,
458+
459+ GotoTarget :: PatternKeywordArgument ( pattern_keyword) => {
460+ let name = & pattern_keyword. attr ;
461+ Some ( definitions_for_name (
462+ model,
463+ name. as_str ( ) ,
464+ AnyNodeRef :: Identifier ( name) ,
465+ ) )
466+ }
467+
468+ GotoTarget :: PatternMatchStarName ( pattern_star) => {
469+ pattern_star. name . as_ref ( ) . map ( |name| {
470+ definitions_for_name ( model, name. as_str ( ) , AnyNodeRef :: Identifier ( name) )
471+ } )
505472 }
506473
507474 // For callables, both the definition of the callable and the actual function impl are relevant.
@@ -516,22 +483,22 @@ impl GotoTarget<'_> {
516483 if definitions. is_empty ( ) {
517484 None
518485 } else {
519- Some ( DefinitionsOrTargets :: Definitions ( definitions) )
486+ Some ( definitions)
520487 }
521488 }
522489
523490 GotoTarget :: BinOp { expression, .. } => {
524491 let ( definitions, _) =
525492 ty_python_semantic:: definitions_for_bin_op ( model, expression) ?;
526493
527- Some ( DefinitionsOrTargets :: Definitions ( definitions) )
494+ Some ( definitions)
528495 }
529496
530497 GotoTarget :: UnaryOp { expression, .. } => {
531498 let ( definitions, _) =
532499 ty_python_semantic:: definitions_for_unary_op ( model, expression) ?;
533500
534- Some ( DefinitionsOrTargets :: Definitions ( definitions) )
501+ Some ( definitions)
535502 }
536503
537504 // String annotations sub-expressions require us to recurse into the sub-AST
@@ -545,23 +512,47 @@ impl GotoTarget<'_> {
545512 . node ( )
546513 . as_expr_ref ( ) ?;
547514 definitions_for_expression ( & submodel, subexpr)
548- . map ( DefinitionsOrTargets :: Definitions )
549515 }
516+
517+ // nonlocal and global are essentially loads, but again they're statements,
518+ // so we need to look them up by ident
550519 GotoTarget :: NonLocal { identifier } | GotoTarget :: Globals { identifier } => {
551- Some ( DefinitionsOrTargets :: Definitions ( definitions_for_name (
520+ Some ( definitions_for_name (
552521 model,
553522 identifier. as_str ( ) ,
554523 AnyNodeRef :: Identifier ( identifier) ,
555- ) ) )
524+ ) )
556525 }
557526
558- // TODO: implement these
559- GotoTarget :: PatternKeywordArgument ( ..)
560- | GotoTarget :: PatternMatchStarName ( ..)
561- | GotoTarget :: TypeParamTypeVarName ( ..)
562- | GotoTarget :: TypeParamParamSpecName ( ..)
563- | GotoTarget :: TypeParamTypeVarTupleName ( ..) => None ,
564- }
527+ // These are declarations of sorts, but they're stmts and not exprs, so look up by ident.
528+ GotoTarget :: TypeParamTypeVarName ( type_var) => {
529+ let name = & type_var. name ;
530+ Some ( definitions_for_name (
531+ model,
532+ name. as_str ( ) ,
533+ AnyNodeRef :: Identifier ( name) ,
534+ ) )
535+ }
536+
537+ GotoTarget :: TypeParamParamSpecName ( name) => {
538+ let name = & name. name ;
539+ Some ( definitions_for_name (
540+ model,
541+ name. as_str ( ) ,
542+ AnyNodeRef :: Identifier ( name) ,
543+ ) )
544+ }
545+
546+ GotoTarget :: TypeParamTypeVarTupleName ( name) => {
547+ let name = & name. name ;
548+ Some ( definitions_for_name (
549+ model,
550+ name. as_str ( ) ,
551+ AnyNodeRef :: Identifier ( name) ,
552+ ) )
553+ }
554+ } ;
555+ definitions. map ( Definitions )
565556 }
566557
567558 /// Returns the text representation of this goto target.
@@ -1050,12 +1041,10 @@ fn definitions_for_module<'db>(
10501041 model : & SemanticModel < ' db > ,
10511042 module : Option < & str > ,
10521043 level : u32 ,
1053- ) -> Option < DefinitionsOrTargets < ' db > > {
1044+ ) -> Option < Vec < ResolvedDefinition < ' db > > > {
10541045 let module = model. resolve_module ( module, level) ?;
10551046 let file = module. file ( model. db ( ) ) ?;
1056- Some ( DefinitionsOrTargets :: Definitions ( vec ! [
1057- ResolvedDefinition :: Module ( file) ,
1058- ] ) )
1047+ Some ( vec ! [ ResolvedDefinition :: Module ( file) ] )
10591048}
10601049
10611050/// Helper function to extract module component information from a dotted module name
0 commit comments