diff --git a/go.mod b/go.mod index 6d95b22..08474f3 100644 --- a/go.mod +++ b/go.mod @@ -9,3 +9,6 @@ require ( github.com/google/go-cmp v0.3.0 github.com/sourcegraph/jsonrpc2 v0.2.0 ) + +// TODO: merge github.com/fhs/go-lsp-internal PR, update dependency and delete next line +replace github.com/fhs/go-lsp-internal => github.com/cloudspinner/go-lsp-internal v0.0.0-20240109201957-d9537c30fb78 diff --git a/go.sum b/go.sum index 180cdf4..32b81b4 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,12 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/cloudspinner/go-lsp-internal v0.0.0-20240109201957-d9537c30fb78 h1:W/QXjKTNneGNXhD+wDd0DBso2NDjl4cAakUa9+8cf2w= +github.com/cloudspinner/go-lsp-internal v0.0.0-20240109201957-d9537c30fb78/go.mod h1:GF34TbXJNatquGdvhieClRATyP8RFzX+l+rNYqfdTow= github.com/fhs/9fans-go v0.0.0-fhs.20200606 h1:kwqns/76paQLNLDx9I5UFkFG1z1tSqHq8a3j/I0kLr4= github.com/fhs/9fans-go v0.0.0-fhs.20200606/go.mod h1:9PelHyep+qBAEyYdGnqAa66ZGjWE0L8EJP+GIDz8p7M= -github.com/fhs/go-lsp-internal v0.0.0-20230610234852-c5f2102def33 h1:IOmTt60Dzfdp4NYvkrOB9AotLk7mBYtd+PBsU5jAQeg= -github.com/fhs/go-lsp-internal v0.0.0-20230610234852-c5f2102def33/go.mod h1:GF34TbXJNatquGdvhieClRATyP8RFzX+l+rNYqfdTow= -github.com/fhs/go-lsp-internal v0.0.0-20230617125605-15c355072be4 h1:3viom14iPcmgEM8hyWJEc7gHAW3HCNUO38bgHYsFaqE= -github.com/fhs/go-lsp-internal v0.0.0-20230617125605-15c355072be4/go.mod h1:GF34TbXJNatquGdvhieClRATyP8RFzX+l+rNYqfdTow= -github.com/fhs/go-lsp-internal v0.0.0-20230617170009-e3a916438ee1 h1:jeF/D2AKXTooLP6m1DP9Qd9dSRmUt2h5VN+3qyyMlII= -github.com/fhs/go-lsp-internal v0.0.0-20230617170009-e3a916438ee1/go.mod h1:GF34TbXJNatquGdvhieClRATyP8RFzX+l+rNYqfdTow= -github.com/fhs/go-lsp-internal v0.0.0-20230619000151-7826e273203a h1:4qLe7eMLgsA82mUUBVmSyOrCE0UV989Oxsqgd+PQcOk= -github.com/fhs/go-lsp-internal v0.0.0-20230619000151-7826e273203a/go.mod h1:GF34TbXJNatquGdvhieClRATyP8RFzX+l+rNYqfdTow= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/sourcegraph/jsonrpc2 v0.2.0 h1:KjN/dC4fP6aN9030MZCJs9WQbTOjWHhrtKVpzzSrr/U= github.com/sourcegraph/jsonrpc2 v0.2.0/go.mod h1:ZafdZgk/axhT1cvZAPOhw+95nz2I/Ra5qMlU4gTRwIo= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/lsp/acmelsp/acmelsp.go b/internal/lsp/acmelsp/acmelsp.go index 539c41b..7bc7543 100644 --- a/internal/lsp/acmelsp/acmelsp.go +++ b/internal/lsp/acmelsp/acmelsp.go @@ -219,6 +219,32 @@ func CodeActionAndFormat(ctx context.Context, server FormatServer, doc *protocol return nil } +func orsToEdits(ors []protocol.Or_TextDocumentEdit_edits_Elem) []protocol.TextEdit { + edits := make([]protocol.TextEdit, len(ors)) + for i, or := range ors { + switch or.Value.(type) { + case protocol.AnnotatedTextEdit: + edits[i] = or.Value.(protocol.AnnotatedTextEdit).TextEdit + case protocol.TextEdit: + edits[i] = or.Value.(protocol.TextEdit) + case nil: + edits[i] = protocol.TextEdit{} + } + } + return edits +} + +func executeCommand(ctx context.Context, server FormatServer, doc *protocol.TextDocumentIdentifier, c *protocol.Command) error { + _, err := server.ExecuteCommandOnDocument(ctx, &proxy.ExecuteCommandOnDocumentParams{ + TextDocument: *doc, + ExecuteCommandParams: protocol.ExecuteCommandParams{ + Command: c.Command, + Arguments: c.Arguments, + }, + }) + return err +} + func editWorkspace(we *protocol.WorkspaceEdit) error { if we == nil { return nil // no changes to apply @@ -230,7 +256,7 @@ func editWorkspace(we *protocol.WorkspaceEdit) error { changes := make(map[protocol.DocumentURI][]protocol.TextEdit) for _, dc := range we.DocumentChanges { if tde := dc.TextDocumentEdit; tde != nil { - changes[tde.TextDocument.TextDocumentIdentifier.URI] = tde.Edits + changes[tde.TextDocument.TextDocumentIdentifier.URI] = orsToEdits(tde.Edits) } } we.Changes = changes diff --git a/internal/lsp/acmelsp/client.go b/internal/lsp/acmelsp/client.go index b94b721..c304028 100644 --- a/internal/lsp/acmelsp/client.go +++ b/internal/lsp/acmelsp/client.go @@ -155,8 +155,8 @@ func (c *Client) init(conn net.Conn, cfg *ClientConfig) error { Capabilities: protocol.ClientCapabilities{ TextDocument: protocol.TextDocumentClientCapabilities{ CodeAction: protocol.CodeActionClientCapabilities{ - CodeActionLiteralSupport: protocol.PCodeActionLiteralSupportPCodeAction{ - CodeActionKind: protocol.FCodeActionKindPCodeActionLiteralSupport{ + CodeActionLiteralSupport: protocol.ClientCodeActionLiteralOptions{ + CodeActionKind: protocol.ClientCodeActionKindOptions{ ValueSet: []protocol.CodeActionKind{ protocol.SourceOrganizeImports, }, @@ -167,8 +167,8 @@ func (c *Client) init(conn net.Conn, cfg *ClientConfig) error { HierarchicalDocumentSymbolSupport: true, }, Completion: protocol.CompletionClientCapabilities{ - CompletionItem: protocol.PCompletionItemPCompletion{ - TagSupport: protocol.FTagSupportPCompletionItem{ + CompletionItem: protocol.ClientCompletionItemOptions{ + TagSupport: &protocol.CompletionItemTagOptions{ ValueSet: []protocol.CompletionItemTag{}, }, }, diff --git a/internal/lsp/acmelsp/client_test.go b/internal/lsp/acmelsp/client_test.go index a563581..b1f1ad4 100644 --- a/internal/lsp/acmelsp/client_test.go +++ b/internal/lsp/acmelsp/client_test.go @@ -191,17 +191,21 @@ func main() { if err != nil { t.Fatalf("Definition failed: %v", err) } - want := []protocol.Location{ - { - URI: uri, - Range: protocol.Range{ - Start: protocol.Position{ - Line: 4, - Character: 5, - }, - End: protocol.Position{ - Line: 4, - Character: 10, + want := &protocol.Or_Result_textDocument_definition{ + Value: protocol.Definition{ + Value: []protocol.Location{ + { + URI: uri, + Range: protocol.Range{ + Start: protocol.Position{ + Line: 4, + Character: 5, + }, + End: protocol.Position{ + Line: 4, + Character: 10, + }, + }, }, }, }, diff --git a/internal/lsp/acmelsp/proxy.go b/internal/lsp/acmelsp/proxy.go index 40eab15..7afee93 100644 --- a/internal/lsp/acmelsp/proxy.go +++ b/internal/lsp/acmelsp/proxy.go @@ -48,7 +48,7 @@ func (s *proxyServer) DidChangeWorkspaceFolders(ctx context.Context, params *pro return s.ss.DidChangeWorkspaceFolders(ctx, params.Event.Added, params.Event.Removed) } -func (s *proxyServer) Completion(ctx context.Context, params *protocol.CompletionParams) (*protocol.CompletionList, error) { +func (s *proxyServer) Completion(ctx context.Context, params *protocol.CompletionParams) (*protocol.Or_Result_textDocument_completion, error) { srv, err := serverForURI(s.ss, params.TextDocumentPositionParams.TextDocument.URI) if err != nil { return nil, fmt.Errorf("Completion: %v", err) @@ -56,7 +56,7 @@ func (s *proxyServer) Completion(ctx context.Context, params *protocol.Completio return srv.Client.Completion(ctx, params) } -func (s *proxyServer) Definition(ctx context.Context, params *protocol.DefinitionParams) ([]protocol.Location, error) { +func (s *proxyServer) Definition(ctx context.Context, params *protocol.DefinitionParams) (*protocol.Or_Result_textDocument_definition, error) { srv, err := serverForURI(s.ss, params.TextDocumentPositionParams.TextDocument.URI) if err != nil { return nil, fmt.Errorf("Definition: %v", err) diff --git a/internal/lsp/acmelsp/remote.go b/internal/lsp/acmelsp/remote.go index b81456b..5ff6253 100644 --- a/internal/lsp/acmelsp/remote.go +++ b/internal/lsp/acmelsp/remote.go @@ -99,8 +99,18 @@ func (rc *RemoteCmd) Completion(ctx context.Context, kind CompletionKind) error return err } - if (kind == CompleteInsertFirstMatch && len(result.Items) >= 1) || (kind == CompleteInsertOnlyMatch && len(result.Items) == 1) { - textEdit := result.Items[0].TextEdit + var items []protocol.CompletionItem + switch val := result.Value; val.(type) { + case protocol.CompletionList: + items = val.(protocol.CompletionList).Items + case []protocol.CompletionItem: + items = val.([]protocol.CompletionItem) + default: + return fmt.Errorf("unknown Completion result type: %T", val) + } + + if (kind == CompleteInsertFirstMatch && len(items) >= 1) || (kind == CompleteInsertOnlyMatch && len(items) == 1) { + textEdit := items[0].TextEdit if textEdit == nil { // TODO(fhs): Use insertText or label instead. return fmt.Errorf("nil TextEdit in completion item") @@ -109,18 +119,18 @@ func (rc *RemoteCmd) Completion(ctx context.Context, kind CompletionKind) error return fmt.Errorf("failed to apply completion edit: %v", err) } - if len(result.Items) == 1 { + if len(items) == 1 { return nil } } var sb strings.Builder - if len(result.Items) == 0 { + if len(items) == 0 { fmt.Fprintf(&sb, "no completion\n") } - for _, item := range result.Items { + for _, item := range items { fmt.Fprintf(&sb, "%v\t%v\n", item.Label, item.Detail) } @@ -151,12 +161,33 @@ func (rc *RemoteCmd) Definition(ctx context.Context, print bool) error { if err != nil { return fmt.Errorf("failed to get position: %v", err) } - locations, err := rc.server.Definition(ctx, &protocol.DefinitionParams{ + orResultDef, err := rc.server.Definition(ctx, &protocol.DefinitionParams{ TextDocumentPositionParams: *pos, }) if err != nil { return fmt.Errorf("bad server response: %v", err) } + var locations []protocol.Location + switch val := orResultDef.Value; val.(type) { + case protocol.Definition: + switch orDefVal := val.(protocol.Definition).Value; orDefVal.(type) { + case protocol.Location: + locations = []protocol.Location{orDefVal.(protocol.Location)} + case []protocol.Location: + locations = orDefVal.([]protocol.Location) + default: + return fmt.Errorf("unknown Definition location type: %T", orDefVal) + } + case []protocol.DefinitionLink: + links := val.([]protocol.DefinitionLink) + locs := make([]protocol.Location, len(links)) + for i, link := range links { + locs[i] = protocol.Location{link.TargetURI, link.TargetSelectionRange} + } + locations = locs + default: + return fmt.Errorf("unknown Definition result type: %T", val) + } if print { return PrintLocations(rc.Stdout, locations) } diff --git a/internal/lsp/proxy/client.go b/internal/lsp/proxy/client.go index d82f923..81fabf4 100644 --- a/internal/lsp/proxy/client.go +++ b/internal/lsp/proxy/client.go @@ -99,6 +99,11 @@ func (c *NotImplementedClient) DiagnosticRefresh(context.Context) error { return fmt.Errorf("workspace/diagnostic/refresh not implemented") } +// workspace/foldingRange/refresh +func (c *NotImplementedClient) FoldingRangeRefresh(context.Context) error { + return fmt.Errorf("workspace/foldingRange/refresh not implemented") +} + // workspace/inlayHint/refresh func (c *NotImplementedClient) InlayHintRefresh(context.Context) error { return fmt.Errorf("workspace/inlayHint/refresh not implemented") diff --git a/internal/lsp/proxy/server.go b/internal/lsp/proxy/server.go index b63f249..eb1ef78 100644 --- a/internal/lsp/proxy/server.go +++ b/internal/lsp/proxy/server.go @@ -182,13 +182,13 @@ func (s *NotImplementedServer) CodeLens(context.Context, *protocol.CodeLensParam func (s *NotImplementedServer) ColorPresentation(context.Context, *protocol.ColorPresentationParams) ([]protocol.ColorPresentation, error) { return nil, fmt.Errorf("not implemented") } -func (s *NotImplementedServer) Completion(context.Context, *protocol.CompletionParams) (*protocol.CompletionList, error) { +func (s *NotImplementedServer) Completion(context.Context, *protocol.CompletionParams) (*protocol.Or_Result_textDocument_completion, error) { return nil, fmt.Errorf("not implemented") } func (s *NotImplementedServer) Declaration(context.Context, *protocol.DeclarationParams) (*protocol.Or_textDocument_declaration, error) { return nil, fmt.Errorf("not implemented") } -func (s *NotImplementedServer) Definition(context.Context, *protocol.DefinitionParams) ([]protocol.Location, error) { +func (s *NotImplementedServer) Definition(context.Context, *protocol.DefinitionParams) (*protocol.Or_Result_textDocument_definition, error) { return nil, fmt.Errorf("not implemented") } func (s *NotImplementedServer) Diagnostic(context.Context, *string) (*string, error) { @@ -233,6 +233,9 @@ func (s *NotImplementedServer) Implementation(context.Context, *protocol.Impleme func (s *NotImplementedServer) InlayHint(context.Context, *protocol.InlayHintParams) ([]protocol.InlayHint, error) { return nil, fmt.Errorf("not implemented") } +func (s *NotImplementedServer) InlineCompletion(context.Context, *protocol.InlineCompletionParams) (*protocol.Or_Result_textDocument_inlineCompletion, error) { + return nil, fmt.Errorf("not implemented") +} func (s *NotImplementedServer) InlineValue(context.Context, *protocol.InlineValueParams) ([]protocol.InlineValue, error) { return nil, fmt.Errorf("not implemented") } @@ -248,7 +251,7 @@ func (s *NotImplementedServer) OnTypeFormatting(context.Context, *protocol.Docum func (s *NotImplementedServer) PrepareCallHierarchy(context.Context, *protocol.CallHierarchyPrepareParams) ([]protocol.CallHierarchyItem, error) { return nil, fmt.Errorf("not implemented") } -func (s *NotImplementedServer) PrepareRename(context.Context, *protocol.PrepareRenameParams) (*protocol.PrepareRename2Gn, error) { +func (s *NotImplementedServer) PrepareRename(context.Context, *protocol.PrepareRenameParams) (*protocol.PrepareRenameResult, error) { return nil, fmt.Errorf("not implemented") } func (s *NotImplementedServer) PrepareTypeHierarchy(context.Context, *protocol.TypeHierarchyPrepareParams) ([]protocol.TypeHierarchyItem, error) { @@ -257,6 +260,9 @@ func (s *NotImplementedServer) PrepareTypeHierarchy(context.Context, *protocol.T func (s *NotImplementedServer) RangeFormatting(context.Context, *protocol.DocumentRangeFormattingParams) ([]protocol.TextEdit, error) { return nil, fmt.Errorf("not implemented") } +func (s *NotImplementedServer) RangesFormatting(context.Context, *protocol.DocumentRangesFormattingParams) ([]protocol.TextEdit, error) { + return nil, fmt.Errorf("not implemented") +} func (s *NotImplementedServer) References(context.Context, *protocol.ReferenceParams) ([]protocol.Location, error) { return nil, fmt.Errorf("not implemented") }