Skip to content

Commit 91241a3

Browse files
committed
Implemented textDocument/documentSymbol
1 parent 57a46b3 commit 91241a3

File tree

3 files changed

+91
-81
lines changed

3 files changed

+91
-81
lines changed

Diff for: handler/handler.go

+57-60
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,14 @@ func (handler *InoHandler) HandleMessageFromIDE(ctx context.Context, conn *jsonr
206206
err = handler.ino2cppTextDocumentPositionParams(doc)
207207
log.Printf(" --> hover(%s:%d:%d)\n", doc.TextDocument.URI, doc.Position.Line, doc.Position.Character)
208208

209+
case *lsp.DocumentSymbolParams:
210+
// method "textDocument/documentSymbol"
211+
uri = p.TextDocument.URI
212+
log.Printf("--> documentSymbol(%s)", p.TextDocument.URI)
213+
214+
err = handler.sketchToBuildPathTextDocumentIdentifier(&p.TextDocument)
215+
log.Printf(" --> documentSymbol(%s)", p.TextDocument.URI)
216+
209217
case *lsp.DidSaveTextDocumentParams: // "textDocument/didSave":
210218
log.Printf("--X " + req.Method)
211219
return nil, nil
@@ -250,11 +258,6 @@ func (handler *InoHandler) HandleMessageFromIDE(ctx context.Context, conn *jsonr
250258
return nil, nil
251259
uri = p.TextDocument.URI
252260
err = handler.ino2cppDocumentOnTypeFormattingParams(p)
253-
case *lsp.DocumentSymbolParams: // "textDocument/documentSymbol":
254-
log.Printf("--X " + req.Method)
255-
return nil, nil
256-
uri = p.TextDocument.URI
257-
err = handler.sketchToBuildPathTextDocumentIdentifier(&p.TextDocument)
258261
case *lsp.RenameParams: // "textDocument/rename":
259262
log.Printf("--X " + req.Method)
260263
return nil, nil
@@ -725,6 +728,19 @@ func (handler *InoHandler) transformClangdResult(method string, uri lsp.Document
725728
log.Printf("<-- completion(%d items)", len(r.Items))
726729
return r
727730

731+
case *lsp.DocumentSymbolArrayOrSymbolInformationArray:
732+
// method "textDocument/documentSymbol"
733+
734+
if r.DocumentSymbolArray != nil {
735+
// Treat the input as []DocumentSymbol
736+
return handler.cpp2inoDocumentSymbols(*r.DocumentSymbolArray, uri)
737+
} else if r.SymbolInformationArray != nil {
738+
// Treat the input as []SymbolInformation
739+
return handler.cpp2inoSymbolInformation(*r.SymbolInformationArray)
740+
} else {
741+
// Treat the input as null
742+
}
743+
728744
case *[]*lsp.CommandOrCodeAction:
729745
// method "textDocument/codeAction"
730746
// TODO: implement response
@@ -764,28 +780,6 @@ func (handler *InoHandler) transformClangdResult(method string, uri lsp.Document
764780
for index := range *r {
765781
handler.cpp2inoTextEdit(&(*r)[index], uri)
766782
}
767-
case *[]*lsp.DocumentSymbolOrSymbolInformation: // "textDocument/documentSymbol":
768-
if len(*r) == 0 {
769-
return result
770-
}
771-
772-
slice := *r
773-
if slice[0].DocumentSymbol != nil {
774-
// Treat the input as []DocumentSymbol
775-
symbols := make([]lsp.DocumentSymbol, len(slice))
776-
for index := range slice {
777-
symbols[index] = *slice[index].DocumentSymbol
778-
}
779-
return handler.cpp2inoDocumentSymbols(symbols, uri)
780-
}
781-
if slice[0].SymbolInformation != nil {
782-
// Treat the input as []SymbolInformation
783-
symbols := make([]*lsp.SymbolInformation, len(slice))
784-
for i, s := range slice {
785-
symbols[i] = s.SymbolInformation
786-
}
787-
return handler.cpp2inoSymbolInformation(symbols)
788-
}
789783
case *lsp.WorkspaceEdit: // "textDocument/rename":
790784
return handler.cpp2inoWorkspaceEdit(r)
791785
case *[]lsp.SymbolInformation: // "workspace/symbol":
@@ -859,44 +853,47 @@ func (handler *InoHandler) cpp2inoTextEdit(edit *lsp.TextEdit, uri lsp.DocumentU
859853
// }
860854
}
861855

862-
func (handler *InoHandler) cpp2inoDocumentSymbols(origSymbols []lsp.DocumentSymbol, uri lsp.DocumentURI) []lsp.DocumentSymbol {
863-
panic("not implemented")
864-
// data, ok := handler.data[uri]
865-
// if !ok || len(origSymbols) == 0 {
866-
// return origSymbols
867-
// }
856+
func (handler *InoHandler) cpp2inoDocumentSymbols(origSymbols []lsp.DocumentSymbol, origURI lsp.DocumentURI) []lsp.DocumentSymbol {
857+
if origURI.AsPath().Ext() != ".ino" || len(origSymbols) == 0 {
858+
return origSymbols
859+
}
868860

869-
// symbolIdx := make(map[string]*lsp.DocumentSymbol)
870-
// for i := 0; i < len(origSymbols); i++ {
871-
// symbol := &origSymbols[i]
872-
// _, symbol.Range = data.sourceMap.CppToInoRange(symbol.Range)
873-
874-
// duplicate := false
875-
// other, duplicate := symbolIdx[symbol.Name]
876-
// if duplicate {
877-
// // 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
878-
// // 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
879-
// // the header early on.
880-
// if other.Range.Start.Line < symbol.Range.Start.Line {
881-
// continue
882-
// }
883-
// }
861+
inoSymbols := []lsp.DocumentSymbol{}
862+
for _, symbol := range origSymbols {
863+
if handler.sketchMapper.IsPreprocessedCppLine(symbol.Range.Start.Line) {
864+
continue
865+
}
884866

885-
// _, symbol.SelectionRange = data.sourceMap.CppToInoRange(symbol.SelectionRange)
886-
// symbol.Children = handler.cpp2inoDocumentSymbols(symbol.Children, uri)
887-
// symbolIdx[symbol.Name] = symbol
888-
// }
867+
inoFile, inoRange := handler.sketchMapper.CppToInoRange(symbol.Range)
868+
inoSelectionURI, inoSelectionRange := handler.sketchMapper.CppToInoRange(symbol.SelectionRange)
889869

890-
// newSymbols := make([]lsp.DocumentSymbol, len(symbolIdx))
891-
// j := 0
892-
// for _, s := range symbolIdx {
893-
// newSymbols[j] = *s
894-
// j++
895-
// }
896-
// return newSymbols
870+
if inoFile != inoSelectionURI {
871+
log.Printf(" ERROR: symbol range and selection belongs to different URI!")
872+
log.Printf(" > %s != %s", symbol.Range, symbol.SelectionRange)
873+
log.Printf(" > %s:%s != %s:%s", inoFile, inoRange, inoSelectionURI, inoSelectionRange)
874+
continue
875+
}
876+
877+
if inoFile != origURI.Unbox() {
878+
//log.Printf(" skipping symbol related to %s", inoFile)
879+
continue
880+
}
881+
882+
inoSymbols = append(inoSymbols, lsp.DocumentSymbol{
883+
Name: symbol.Name,
884+
Detail: symbol.Detail,
885+
Deprecated: symbol.Deprecated,
886+
Kind: symbol.Kind,
887+
Range: inoRange,
888+
SelectionRange: inoSelectionRange,
889+
Children: handler.cpp2inoDocumentSymbols(symbol.Children, origURI),
890+
})
891+
}
892+
893+
return inoSymbols
897894
}
898895

899-
func (handler *InoHandler) cpp2inoSymbolInformation(syms []*lsp.SymbolInformation) []lsp.SymbolInformation {
896+
func (handler *InoHandler) cpp2inoSymbolInformation(syms []lsp.SymbolInformation) []lsp.SymbolInformation {
900897
panic("not implemented")
901898
// // Much like in cpp2inoDocumentSymbols we de-duplicate symbols based on file in-file location.
902899
// idx := make(map[string]*lsp.SymbolInformation)

Diff for: handler/sourcemapper/ino.go

+8
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@ func (s *InoMapper) CppToInoLineOk(targetLine int) (string, int, bool) {
9999
return res.File, res.Line, ok
100100
}
101101

102+
// IsPreprocessedCppLine returns true if the give .cpp line is part of the
103+
// section added by the arduino preprocessor.
104+
func (s *InoMapper) IsPreprocessedCppLine(cppLine int) bool {
105+
_, preprocessed := s.cppPreprocessed[cppLine]
106+
_, mapsToIno := s.toIno[cppLine]
107+
return preprocessed || !mapsToIno
108+
}
109+
102110
// CreateInoMapper create a InoMapper from the given target file
103111
func CreateInoMapper(targetFile []byte) *InoMapper {
104112
mapper := &InoMapper{

Diff for: lsp/protocol.go

+26-21
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ func SendRequest(ctx context.Context, conn *jsonrpc2.Conn, method string, params
154154
err := conn.Call(ctx, method, params, result)
155155
return result, err
156156
case "textDocument/documentSymbol":
157-
result := new([]*DocumentSymbolOrSymbolInformation)
157+
result := new(DocumentSymbolArrayOrSymbolInformationArray)
158158
err := conn.Call(ctx, method, params, result)
159159
return result, err
160160
case "textDocument/rename":
@@ -252,35 +252,40 @@ type DocumentSymbol struct {
252252
Children []DocumentSymbol `json:"children,omitempty"`
253253
}
254254

255-
type DocumentSymbolOrSymbolInformation struct {
256-
DocumentSymbol *DocumentSymbol
257-
SymbolInformation *SymbolInformation
255+
type DocumentSymbolArrayOrSymbolInformationArray struct {
256+
DocumentSymbolArray *[]DocumentSymbol
257+
SymbolInformationArray *[]SymbolInformation
258258
}
259259

260-
type documentSymbolOrSymbolInformationDiscriminator struct {
261-
Range *Range `json:"range,omitempty"`
262-
Location *Location `json:"location,omitempty"`
263-
}
264-
265-
func (entry *DocumentSymbolOrSymbolInformation) UnmarshalJSON(raw []byte) error {
266-
discriminator := new(documentSymbolOrSymbolInformationDiscriminator)
267-
err := json.Unmarshal(raw, discriminator)
268-
if err != nil {
260+
func (entry *DocumentSymbolArrayOrSymbolInformationArray) UnmarshalJSON(raw []byte) error {
261+
intermediate := []json.RawMessage{}
262+
if err := json.Unmarshal(raw, &intermediate); err != nil {
263+
return err
264+
}
265+
discriminator := struct {
266+
Range *Range `json:"range,omitempty"`
267+
Location *Location `json:"location,omitempty"`
268+
}{}
269+
if err := json.Unmarshal(intermediate[0], &discriminator); err != nil {
269270
return err
270271
}
271272
if discriminator.Range != nil {
272-
entry.DocumentSymbol = new(DocumentSymbol)
273-
err = json.Unmarshal(raw, entry.DocumentSymbol)
274-
if err != nil {
275-
return err
273+
res := make([]DocumentSymbol, len(intermediate))
274+
for i, item := range intermediate {
275+
if err := json.Unmarshal(item, &res[i]); err != nil {
276+
return err
277+
}
276278
}
279+
entry.DocumentSymbolArray = &res
277280
}
278281
if discriminator.Location != nil {
279-
entry.SymbolInformation = new(SymbolInformation)
280-
err = json.Unmarshal(raw, entry.SymbolInformation)
281-
if err != nil {
282-
return err
282+
res := make([]SymbolInformation, len(intermediate))
283+
for i, item := range intermediate {
284+
if err := json.Unmarshal(item, &res[i]); err != nil {
285+
return err
286+
}
283287
}
288+
entry.SymbolInformationArray = &res
284289
}
285290
return nil
286291
}

0 commit comments

Comments
 (0)