@@ -5,11 +5,12 @@ use crate::rust_analyzer::FileSemanticInformation;
55use crate :: trap:: { DiagnosticSeverity , TrapFile , TrapId } ;
66use crate :: trap:: { Label , TrapClass } ;
77use codeql_extractor:: trap:: { self } ;
8+ use itertools:: Either ;
89use log:: Level ;
910use ra_ap_base_db:: salsa:: InternKey ;
1011use ra_ap_base_db:: CrateOrigin ;
1112use ra_ap_hir:: db:: ExpandDatabase ;
12- use ra_ap_hir:: { Adt , ItemContainer , Module , Semantics , Type } ;
13+ use ra_ap_hir:: { Adt , Crate , ItemContainer , Module , ModuleDef , PathResolution , Semantics , Type } ;
1314use ra_ap_hir_def:: type_ref:: Mutability ;
1415use ra_ap_hir_def:: ModuleId ;
1516use ra_ap_hir_expand:: ExpandTo ;
@@ -47,6 +48,12 @@ macro_rules! emit_detached {
4748 $self. extract_canonical_origin( & $node, $label. into( ) ) ;
4849 } ;
4950 // TODO canonical origin of other items
51+ ( Path , $self: ident, $node: ident, $label: ident) => {
52+ $self. extract_canonical_destination( & $node, $label) ;
53+ } ;
54+ ( MethodCallExpr , $self: ident, $node: ident, $label: ident) => {
55+ $self. extract_method_canonical_destination( & $node, $label) ;
56+ } ;
5057 ( $( $_: tt) * ) => { } ;
5158}
5259
@@ -276,13 +283,13 @@ impl<'a> Translator<'a> {
276283 } else {
277284 let range = self . text_range_for_node ( mcall) ;
278285 self . emit_parse_error ( mcall, & SyntaxError :: new (
279- format ! (
280- "macro expansion failed: the macro '{}' expands to {:?} but a {:?} was expected" ,
281- mcall. path( ) . map( |p| p. to_string( ) ) . unwrap_or_default( ) ,
282- kind, expand_to
283- ) ,
284- range. unwrap_or_else ( || TextRange :: empty ( TextSize :: from ( 0 ) ) ) ,
285- ) ) ;
286+ format ! (
287+ "macro expansion failed: the macro '{}' expands to {:?} but a {:?} was expected" ,
288+ mcall. path( ) . map( |p| p. to_string( ) ) . unwrap_or_default( ) ,
289+ kind, expand_to
290+ ) ,
291+ range. unwrap_or_else ( || TextRange :: empty ( TextSize :: from ( 0 ) ) ) ,
292+ ) ) ;
286293 }
287294 } else if self . semantics . is_some ( ) {
288295 // let's not spam warnings if we don't have semantics, we already emitted one
@@ -381,10 +388,34 @@ impl<'a> Translator<'a> {
381388 Some ( format ! ( "{prefix}::{name}" ) )
382389 }
383390
391+ fn canonical_path_from_module_def ( & self , item : ModuleDef ) -> Option < String > {
392+ match item {
393+ ModuleDef :: Module ( it) => self . canonical_path_from_hir ( it) ,
394+ ModuleDef :: Function ( it) => self . canonical_path_from_hir ( it) ,
395+ ModuleDef :: Adt ( Adt :: Enum ( it) ) => self . canonical_path_from_hir ( it) ,
396+ ModuleDef :: Adt ( Adt :: Struct ( it) ) => self . canonical_path_from_hir ( it) ,
397+ ModuleDef :: Adt ( Adt :: Union ( it) ) => self . canonical_path_from_hir ( it) ,
398+ ModuleDef :: Trait ( it) => self . canonical_path_from_hir ( it) ,
399+ ModuleDef :: Static ( _) => None ,
400+ ModuleDef :: TraitAlias ( _) => None ,
401+ ModuleDef :: TypeAlias ( _) => None ,
402+ ModuleDef :: BuiltinType ( _) => None ,
403+ ModuleDef :: Macro ( _) => None ,
404+ ModuleDef :: Variant ( _) => None ,
405+ ModuleDef :: Const ( _) => None ,
406+ }
407+ }
408+
384409 fn origin_from_hir < T : AstNode > ( & self , item : impl AddressableHir < T > ) -> String {
385410 // if we have a Hir entity, it means we have semantics
386411 let sema = self . semantics . as_ref ( ) . unwrap ( ) ;
387- match item. module ( sema) . krate ( ) . origin ( sema. db ) {
412+ self . origin_from_crate ( item. module ( sema) . krate ( ) )
413+ }
414+
415+ fn origin_from_crate ( & self , item : Crate ) -> String {
416+ // if we have a Hir entity, it means we have semantics
417+ let sema = self . semantics . as_ref ( ) . unwrap ( ) ;
418+ match item. origin ( sema. db ) {
388419 CrateOrigin :: Rustc { name } => format ! ( "rustc:{}" , name) ,
389420 CrateOrigin :: Local { repo, name } => format ! (
390421 "repo:{}:{}" ,
@@ -398,6 +429,24 @@ impl<'a> Translator<'a> {
398429 }
399430 }
400431
432+ fn origin_from_module_def ( & self , item : ModuleDef ) -> Option < String > {
433+ match item {
434+ ModuleDef :: Module ( it) => Some ( self . origin_from_hir ( it) ) ,
435+ ModuleDef :: Function ( it) => Some ( self . origin_from_hir ( it) ) ,
436+ ModuleDef :: Adt ( Adt :: Enum ( it) ) => Some ( self . origin_from_hir ( it) ) ,
437+ ModuleDef :: Adt ( Adt :: Struct ( it) ) => Some ( self . origin_from_hir ( it) ) ,
438+ ModuleDef :: Adt ( Adt :: Union ( it) ) => Some ( self . origin_from_hir ( it) ) ,
439+ ModuleDef :: Trait ( it) => Some ( self . origin_from_hir ( it) ) ,
440+ ModuleDef :: Static ( _) => None ,
441+ ModuleDef :: TraitAlias ( _) => None ,
442+ ModuleDef :: TypeAlias ( _) => None ,
443+ ModuleDef :: BuiltinType ( _) => None ,
444+ ModuleDef :: Macro ( _) => None ,
445+ ModuleDef :: Variant ( _) => None ,
446+ ModuleDef :: Const ( _) => None ,
447+ }
448+ }
449+
401450 pub ( crate ) fn extract_canonical_origin < T : AddressableAst + HasName > (
402451 & mut self ,
403452 item : & T ,
@@ -413,4 +462,50 @@ impl<'a> Translator<'a> {
413462 Some ( ( ) )
414463 } ) ( ) ;
415464 }
465+
466+ pub ( crate ) fn extract_canonical_destination (
467+ & mut self ,
468+ item : & ast:: Path ,
469+ label : Label < generated:: Path > ,
470+ ) {
471+ ( || {
472+ let sema = self . semantics . as_ref ( ) ?;
473+ let resolution = sema. resolve_path ( item) ?;
474+ let PathResolution :: Def ( def) = resolution else {
475+ return None ;
476+ } ;
477+ let origin = self . origin_from_module_def ( def) ?;
478+ let path = self . canonical_path_from_module_def ( def) ?;
479+ generated:: Resolvable :: emit_resolved_crate_origin (
480+ label. into ( ) ,
481+ origin,
482+ & mut self . trap . writer ,
483+ ) ;
484+ generated:: Resolvable :: emit_resolved_path ( label. into ( ) , path, & mut self . trap . writer ) ;
485+ Some ( ( ) )
486+ } ) ( ) ;
487+ }
488+
489+ pub ( crate ) fn extract_method_canonical_destination (
490+ & mut self ,
491+ item : & ast:: MethodCallExpr ,
492+ label : Label < generated:: MethodCallExpr > ,
493+ ) {
494+ ( || {
495+ let sema = self . semantics . as_ref ( ) ?;
496+ let resolved = sema. resolve_method_call_fallback ( item) ?;
497+ let Either :: Left ( function) = resolved else {
498+ return None ;
499+ } ;
500+ let origin = self . origin_from_hir ( function) ;
501+ let path = self . canonical_path_from_hir ( function) ?;
502+ generated:: Resolvable :: emit_resolved_crate_origin (
503+ label. into ( ) ,
504+ origin,
505+ & mut self . trap . writer ,
506+ ) ;
507+ generated:: Resolvable :: emit_resolved_path ( label. into ( ) , path, & mut self . trap . writer ) ;
508+ Some ( ( ) )
509+ } ) ( ) ;
510+ }
416511}
0 commit comments