@@ -20,15 +20,17 @@ use lsp_types::{
20
20
CallHierarchyIncomingCall , CallHierarchyIncomingCallsParams , CallHierarchyItem ,
21
21
CallHierarchyOutgoingCall , CallHierarchyOutgoingCallsParams , CallHierarchyPrepareParams ,
22
22
CodeLens , CompletionItem , Diagnostic , DiagnosticTag , DocumentFormattingParams , FoldingRange ,
23
- FoldingRangeParams , HoverContents , Location , NumberOrString , Position , PrepareRenameResponse ,
24
- Range , RenameParams , SemanticTokensDeltaParams , SemanticTokensFullDeltaResult ,
25
- SemanticTokensParams , SemanticTokensRangeParams , SemanticTokensRangeResult ,
26
- SemanticTokensResult , SymbolInformation , SymbolTag , TextDocumentIdentifier , Url , WorkspaceEdit ,
23
+ FoldingRangeParams , HoverContents , Location , LocationLink , NumberOrString , Position ,
24
+ PrepareRenameResponse , Range , RenameParams , SemanticTokensDeltaParams ,
25
+ SemanticTokensFullDeltaResult , SemanticTokensParams , SemanticTokensRangeParams ,
26
+ SemanticTokensRangeResult , SemanticTokensResult , SymbolInformation , SymbolTag ,
27
+ TextDocumentIdentifier , Url , WorkspaceEdit ,
27
28
} ;
28
- use project_model:: TargetKind ;
29
+ use project_model:: { ProjectWorkspace , TargetKind } ;
29
30
use serde_json:: json;
30
31
use stdx:: { format_to, never} ;
31
32
use syntax:: { algo, ast, AstNode , TextRange , TextSize , T } ;
33
+ use vfs:: AbsPath ;
32
34
33
35
use crate :: {
34
36
cargo_target_spec:: CargoTargetSpec ,
@@ -603,6 +605,74 @@ pub(crate) fn handle_parent_module(
603
605
params : lsp_types:: TextDocumentPositionParams ,
604
606
) -> Result < Option < lsp_types:: GotoDefinitionResponse > > {
605
607
let _p = profile:: span ( "handle_parent_module" ) ;
608
+ if let Ok ( file_path) = & params. text_document . uri . to_file_path ( ) {
609
+ if file_path. file_name ( ) . unwrap_or_default ( ) == "Cargo.toml" {
610
+ // search parent workspace and collect a list of `LocationLink`path,
611
+ // since cargo.toml doesn't have file_id
612
+ let links: Vec < LocationLink > = snap
613
+ . workspaces
614
+ . iter ( )
615
+ . filter_map ( |ws| match ws {
616
+ ProjectWorkspace :: Cargo { cargo, .. } => cargo
617
+ . packages ( )
618
+ . find ( |& pkg| {
619
+ cargo[ pkg]
620
+ . targets
621
+ . iter ( )
622
+ . find_map ( |& it| {
623
+ let pkg_parent_path = cargo[ it] . root . parent ( ) ?;
624
+ let file_parent_path = AbsPath :: assert ( file_path. parent ( ) ?) ;
625
+ if pkg_parent_path == file_parent_path {
626
+ Some ( ( ) )
627
+ } else {
628
+ None
629
+ }
630
+ } )
631
+ . is_some ( )
632
+ } )
633
+ . and_then ( |_| Some ( cargo) ) ,
634
+ _ => None ,
635
+ } )
636
+ . map ( |ws| {
637
+ let target_cargo_toml_path = ws. workspace_root ( ) . join ( "Cargo.toml" ) ;
638
+ let target_cargo_toml_url =
639
+ to_proto:: url_from_abs_path ( & target_cargo_toml_path) ;
640
+ LocationLink {
641
+ origin_selection_range : None ,
642
+ target_uri : target_cargo_toml_url,
643
+ target_range : Range :: default ( ) ,
644
+ target_selection_range : Range :: default ( ) ,
645
+ }
646
+ } )
647
+ . collect :: < _ > ( ) ;
648
+ return Ok ( Some ( links. into ( ) ) ) ;
649
+ }
650
+
651
+ // check if invoked at the crate root
652
+ let file_id = from_proto:: file_id ( & snap, & params. text_document . uri ) ?;
653
+ let crate_id = match snap. analysis . crate_for ( file_id) ?. first ( ) {
654
+ Some ( & crate_id) => crate_id,
655
+ None => return Ok ( None ) ,
656
+ } ;
657
+ let cargo_spec = match CargoTargetSpec :: for_file ( & snap, file_id) ? {
658
+ Some ( it) => it,
659
+ None => return Ok ( None ) ,
660
+ } ;
661
+
662
+ if snap. analysis . crate_root ( crate_id) ? == file_id {
663
+ let cargo_toml_url = to_proto:: url_from_abs_path ( & cargo_spec. cargo_toml ) ;
664
+ let res = vec ! [ LocationLink {
665
+ origin_selection_range: None ,
666
+ target_uri: cargo_toml_url,
667
+ target_range: Range :: default ( ) ,
668
+ target_selection_range: Range :: default ( ) ,
669
+ } ]
670
+ . into ( ) ;
671
+ return Ok ( Some ( res) ) ;
672
+ }
673
+ }
674
+
675
+ // locate parent module by semantics
606
676
let position = from_proto:: file_position ( & snap, params) ?;
607
677
let navs = snap. analysis . parent_module ( position) ?;
608
678
let res = to_proto:: goto_definition_response ( & snap, None , navs) ?;
0 commit comments