@@ -587,16 +587,21 @@ func (handler *InoHandler) transformClangdResult(method string, uri lsp.Document
587
587
handler .cpp2inoTextEdit (& (* r )[index ], uri )
588
588
}
589
589
case "textDocument/documentSymbol" :
590
- r := result .(* []* documentSymbolOrSymbolInformation )
590
+ r , ok := result .(* []* documentSymbolOrSymbolInformation )
591
+ if ! ok || len (* r ) == 0 {
592
+ return result
593
+ }
594
+
591
595
slice := * r
592
- if len ( slice ) > 0 && slice [0 ].DocumentSymbol != nil {
596
+ if slice [0 ].DocumentSymbol != nil {
593
597
// Treat the input as []DocumentSymbol
594
598
symbols := make ([]DocumentSymbol , len (slice ))
595
599
for index := range slice {
596
600
symbols [index ] = * slice [index ].DocumentSymbol
597
601
}
598
- result = handler .cpp2inoDocumentSymbols (symbols , uri )
599
- } else if len (slice ) > 0 && slice [0 ].SymbolInformation != nil {
602
+ return handler .cpp2inoDocumentSymbols (symbols , uri )
603
+ }
604
+ if slice [0 ].SymbolInformation != nil {
600
605
// Treat the input as []SymbolInformation
601
606
symbols := make ([]lsp.SymbolInformation , len (slice ))
602
607
for index := range slice {
@@ -605,11 +610,11 @@ func (handler *InoHandler) transformClangdResult(method string, uri lsp.Document
605
610
for index := range symbols {
606
611
handler .cpp2inoLocation (& symbols [index ].Location )
607
612
}
608
- result = symbols
613
+ return symbols
609
614
}
610
615
case "textDocument/rename" :
611
616
r := result .(* lsp.WorkspaceEdit )
612
- result = handler .cpp2inoWorkspaceEdit (r )
617
+ return handler .cpp2inoWorkspaceEdit (r )
613
618
case "workspace/symbol" :
614
619
r := result .(* []lsp.SymbolInformation )
615
620
for index := range * r {
@@ -711,29 +716,37 @@ func (handler *InoHandler) cpp2inoDocumentSymbols(origSymbols []DocumentSymbol,
711
716
if ! ok || len (origSymbols ) == 0 {
712
717
return origSymbols
713
718
}
714
- newSymbols := make ([] DocumentSymbol , len ( origSymbols ))
715
- j := 0
719
+
720
+ symbolIdx := make ( map [ string ] * DocumentSymbol )
716
721
for i := 0 ; i < len (origSymbols ); i ++ {
717
722
symbol := & origSymbols [i ]
718
723
symbol .Range .Start .Line = data .sourceLineMap [symbol .Range .Start .Line ]
719
724
symbol .Range .End .Line = data .sourceLineMap [symbol .Range .End .Line ]
720
725
721
726
duplicate := false
722
- for k := 0 ; k < j ; k ++ {
723
- if symbol .Name == newSymbols [k ].Name && symbol .Range .Start .Line == newSymbols [k ].Range .Start .Line {
724
- duplicate = true
725
- break
727
+ other , duplicate := symbolIdx [symbol .Name ]
728
+ if duplicate {
729
+ // we prefer symbols later in the file due to the function header generation. E.g. if one has a function `void foo() {}` somehwre in the code
730
+ // the code generation will add a `void foo();` header at the beginning of the cpp file. We care about the function body later in the file, not
731
+ // the header early on.
732
+ if symbol .Range .Start .Line < other .Range .Start .Line {
733
+ continue
726
734
}
727
735
}
728
- if ! duplicate {
729
- symbol .SelectionRange .Start .Line = data .sourceLineMap [symbol .SelectionRange .Start .Line ]
730
- symbol .SelectionRange .End .Line = data .sourceLineMap [symbol .SelectionRange .End .Line ]
731
- symbol .Children = handler .cpp2inoDocumentSymbols (symbol .Children , uri )
732
- newSymbols [j ] = * symbol
733
- j ++
734
- }
736
+
737
+ symbol .SelectionRange .Start .Line = data .sourceLineMap [symbol .SelectionRange .Start .Line ]
738
+ symbol .SelectionRange .End .Line = data .sourceLineMap [symbol .SelectionRange .End .Line ]
739
+ symbol .Children = handler .cpp2inoDocumentSymbols (symbol .Children , uri )
740
+ symbolIdx [symbol .Name ] = symbol
741
+ }
742
+
743
+ newSymbols := make ([]DocumentSymbol , len (symbolIdx ))
744
+ j := 0
745
+ for _ , s := range symbolIdx {
746
+ newSymbols [j ] = * s
747
+ j ++
735
748
}
736
- return newSymbols [: j ]
749
+ return newSymbols
737
750
}
738
751
739
752
// FromClangd handles a message received from clangd.
0 commit comments