Skip to content

Commit

Permalink
internal/lsp: reorganize the generated Go code for the lsp protocol
Browse files Browse the repository at this point in the history
Code generation has been unified, so that tsprotocol.go and tsserver.go
are produced by the same program. tsprotocol.go is about 900 lines shorter,
partly from removing boilerplate comments that golint no longer requires.
(And partly by generating fewer unneeded types.)

The choice made for a union type is commented with the set of types. There
is no Go equivalent for union types, but making themn all interface{}
would replace type checking at unmarshalling with checking runtime
conversions.

Intersection types (A&B) are sometimes embedded (struct{A;B;}, and
sometimes expanded, as they have to be if A and B have fields with the
same names.

There are fewer embedded structs, which had been verbose and confusing to
initialize. They have been replaced by types whose names end in Gn.

Essentially all the generated *structs have been removed. This makes
no difference in what the client sends, and the server may send a {}
where it previously might have sent nothing. The benefit is that some
nil tests can be removed. Thus 'omitempty' in json tags is just
documentation that the element is optional in the protocol.

The files that generate this code will be submitted later, but soon.

Change-Id: I52b997d9c58de3d733fc8c6ce061e47ce2bdb100
Reviewed-on: https://go-review.googlesource.com/c/tools/+/207598
Run-TryBot: Peter Weinberger <pjw@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
  • Loading branch information
pjweinbgo committed Nov 18, 2019
1 parent 5a76f03 commit 5091d64
Show file tree
Hide file tree
Showing 18 changed files with 1,349 additions and 2,227 deletions.
6 changes: 3 additions & 3 deletions internal/lsp/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,10 @@ func (app *Application) connect(ctx context.Context) (*connection, error) {
}

func (c *connection) initialize(ctx context.Context) error {
params := &protocol.ParamInitia{}
params := &protocol.ParamInitialize{}
params.RootURI = string(span.FileURI(c.Client.app.wd))
params.Capabilities.Workspace.Configuration = true
params.Capabilities.TextDocument.Hover = &protocol.HoverClientCapabilities{
params.Capabilities.TextDocument.Hover = protocol.HoverClientCapabilities{
ContentFormat: []protocol.MarkupKind{protocol.PlainText},
}
if _, err := c.Server.Initialize(ctx, params); err != nil {
Expand Down Expand Up @@ -295,7 +295,7 @@ func (c *cmdClient) WorkspaceFolders(ctx context.Context) ([]protocol.WorkspaceF
return nil, nil
}

func (c *cmdClient) Configuration(ctx context.Context, p *protocol.ParamConfig) ([]interface{}, error) {
func (c *cmdClient) Configuration(ctx context.Context, p *protocol.ParamConfiguration) ([]interface{}, error) {
results := make([]interface{}, len(p.Items))
for i, item := range p.Items {
if item.Section != "gopls" {
Expand Down
6 changes: 5 additions & 1 deletion internal/lsp/cmd/imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ func (t *imports) Run(ctx context.Context, args ...string) error {
return errors.Errorf("%v: %v", from, err)
}
var edits []protocol.TextEdit
for _, a := range actions {
v, ok := actions.([]protocol.CodeAction)
if !ok {
return errors.Errorf("expected CodeAction, got %T", actions)
}
for _, a := range v {
if a.Title != "Organize Imports" {
continue
}
Expand Down
6 changes: 5 additions & 1 deletion internal/lsp/cmd/suggested_fix.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ func (s *suggestedfix) Run(ctx context.Context, args ...string) error {
return errors.Errorf("%v: %v", from, err)
}
var edits []protocol.TextEdit
for _, a := range actions {
v, ok := actions.([]protocol.CodeAction)
if !ok {
return errors.Errorf("expected CodeAction, got %T", actions)
}
for _, a := range v {
if !a.IsPreferred && !s.All {
continue
}
Expand Down
1 change: 0 additions & 1 deletion internal/lsp/cmd/symbols.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ func (r *symbols) Run(ctx context.Context, args ...string) error {
if err != nil {
return err
}

for _, s := range symbols {
fmt.Println(symbolToString(s))
// Sort children for consistency
Expand Down
8 changes: 4 additions & 4 deletions internal/lsp/code_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionPara
codeActions = append(codeActions, protocol.CodeAction{
Title: "Tidy",
Kind: protocol.SourceOrganizeImports,
Command: &protocol.Command{
Command: protocol.Command{
Title: "Tidy",
Command: "tidy",
Arguments: []interface{}{
Expand Down Expand Up @@ -94,7 +94,7 @@ func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionPara
codeActions = append(codeActions, protocol.CodeAction{
Title: importFixTitle(importFix.Fix),
Kind: protocol.QuickFix,
Edit: &protocol.WorkspaceEdit{
Edit: protocol.WorkspaceEdit{
DocumentChanges: documentChanges(fh, importFix.Edits),
},
Diagnostics: fixDiagnostics,
Expand All @@ -107,7 +107,7 @@ func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionPara
codeActions = append(codeActions, protocol.CodeAction{
Title: "Organize Imports",
Kind: protocol.SourceOrganizeImports,
Edit: &protocol.WorkspaceEdit{
Edit: protocol.WorkspaceEdit{
DocumentChanges: documentChanges(fh, edits),
},
})
Expand Down Expand Up @@ -226,7 +226,7 @@ func quickFixes(ctx context.Context, s source.Snapshot, f source.File, diagnosti
Title: fix.Title,
Kind: protocol.QuickFix,
Diagnostics: []protocol.Diagnostic{diag},
Edit: &protocol.WorkspaceEdit{},
Edit: protocol.WorkspaceEdit{},
}
for uri, edits := range fix.Edits {
f, err := s.View().GetFile(ctx, uri)
Expand Down
4 changes: 2 additions & 2 deletions internal/lsp/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func toProtocolCompletionItems(candidates []source.CompletionItem, rng protocol.
Label: candidate.Label,
Detail: candidate.Detail,
Kind: candidate.Kind,
TextEdit: &protocol.TextEdit{
TextEdit: protocol.TextEdit{
NewText: insertText,
Range: rng,
},
Expand All @@ -123,7 +123,7 @@ func toProtocolCompletionItems(candidates []source.CompletionItem, rng protocol.
// since we show return types as well.
switch item.Kind {
case protocol.FunctionCompletion, protocol.MethodCompletion:
item.Command = &protocol.Command{
item.Command = protocol.Command{
Command: "editor.action.triggerParameterHints",
}
}
Expand Down
41 changes: 15 additions & 26 deletions internal/lsp/general.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
errors "golang.org/x/xerrors"
)

func (s *Server) initialize(ctx context.Context, params *protocol.ParamInitia) (*protocol.InitializeResult, error) {
func (s *Server) initialize(ctx context.Context, params *protocol.ParamInitialize) (*protocol.InitializeResult, error) {
s.stateMu.Lock()
state := s.state
s.stateMu.Unlock()
Expand Down Expand Up @@ -53,8 +53,7 @@ func (s *Server) initialize(ctx context.Context, params *protocol.ParamInitia) (
}

var codeActionProvider interface{}
if ca := params.Capabilities.TextDocument.CodeAction; ca != nil && ca.CodeActionLiteralSupport != nil &&
len(ca.CodeActionLiteralSupport.CodeActionKind.ValueSet) > 0 {
if ca := params.Capabilities.TextDocument.CodeAction; len(ca.CodeActionLiteralSupport.CodeActionKind.ValueSet) > 0 {
// If the client has specified CodeActionLiteralSupport,
// send the code actions we support.
//
Expand All @@ -65,54 +64,44 @@ func (s *Server) initialize(ctx context.Context, params *protocol.ParamInitia) (
} else {
codeActionProvider = true
}
var renameOpts interface{}
if r := params.Capabilities.TextDocument.Rename; r != nil {
renameOpts = &protocol.RenameOptions{
PrepareProvider: r.PrepareSupport,
}
} else {
renameOpts = true
// This used to be interface{}, when r could be nil
var renameOpts protocol.RenameOptions
r := params.Capabilities.TextDocument.Rename
renameOpts = protocol.RenameOptions{
PrepareProvider: r.PrepareSupport,
}
return &protocol.InitializeResult{
Capabilities: protocol.ServerCapabilities{
CodeActionProvider: codeActionProvider,
CompletionProvider: &protocol.CompletionOptions{
CompletionProvider: protocol.CompletionOptions{
TriggerCharacters: []string{"."},
},
DefinitionProvider: true,
TypeDefinitionProvider: true,
ImplementationProvider: true,
DocumentFormattingProvider: true,
DocumentSymbolProvider: true,
ExecuteCommandProvider: &protocol.ExecuteCommandOptions{
ExecuteCommandProvider: protocol.ExecuteCommandOptions{
Commands: options.SupportedCommands,
},
FoldingRangeProvider: true,
HoverProvider: true,
DocumentHighlightProvider: true,
DocumentLinkProvider: &protocol.DocumentLinkOptions{},
DocumentLinkProvider: protocol.DocumentLinkOptions{},
ReferencesProvider: true,
RenameProvider: renameOpts,
SignatureHelpProvider: &protocol.SignatureHelpOptions{
SignatureHelpProvider: protocol.SignatureHelpOptions{
TriggerCharacters: []string{"(", ","},
},
TextDocumentSync: &protocol.TextDocumentSyncOptions{
Change: options.TextDocumentSyncKind,
OpenClose: true,
Save: &protocol.SaveOptions{
Save: protocol.SaveOptions{
IncludeText: false,
},
},
Workspace: &struct {
WorkspaceFolders *struct {
Supported bool "json:\"supported,omitempty\""
ChangeNotifications string "json:\"changeNotifications,omitempty\""
} "json:\"workspaceFolders,omitempty\""
}{
WorkspaceFolders: &struct {
Supported bool "json:\"supported,omitempty\""
ChangeNotifications string "json:\"changeNotifications,omitempty\""
}{
Workspace: protocol.WorkspaceGn{
protocol.WorkspaceFoldersGn{
Supported: true,
ChangeNotifications: "workspace/didChangeWorkspaceFolders",
},
Expand Down Expand Up @@ -192,7 +181,7 @@ func (s *Server) fetchConfig(ctx context.Context, name string, folder span.URI,
if !s.session.Options().ConfigurationSupported {
return nil
}
v := protocol.ParamConfig{
v := protocol.ParamConfiguration{
ConfigurationParams: protocol.ConfigurationParams{
Items: []protocol.ConfigurationItem{{
ScopeURI: protocol.NewURI(folder),
Expand Down
2 changes: 1 addition & 1 deletion internal/lsp/highlight.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func toProtocolHighlight(rngs []protocol.Range) []protocol.DocumentHighlight {
kind := protocol.Text
for _, rng := range rngs {
result = append(result, protocol.DocumentHighlight{
Kind: &kind,
Kind: kind,
Range: rng,
})
}
Expand Down
2 changes: 1 addition & 1 deletion internal/lsp/hover.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (s *Server) hover(ctx context.Context, params *protocol.HoverParams) (*prot
contents := s.toProtocolHoverContents(ctx, hover, view.Options())
return &protocol.Hover{
Contents: contents,
Range: &rng,
Range: rng,
}, nil
}

Expand Down
26 changes: 16 additions & 10 deletions internal/lsp/lsp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,9 @@ func (r *runner) Import(t *testing.T, spn span.Span) {
t.Fatal(err)
}
got := string(m.Content)
if len(actions) > 0 {
res, err := applyWorkspaceEdits(r, actions[0].Edit)
xact := actions.([]protocol.CodeAction)
if len(xact) > 0 {
res, err := applyWorkspaceEdits(r, xact[0].Edit)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -354,10 +355,11 @@ func (r *runner) SuggestedFix(t *testing.T, spn span.Span) {
t.Fatal(err)
}
// TODO: This test should probably be able to handle multiple code actions.
if len(actions) > 1 {
xact := actions.([]protocol.CodeAction)
if len(xact) > 1 {
t.Fatal("expected only 1 code action")
}
res, err := applyWorkspaceEdits(r, actions[0].Edit)
res, err := applyWorkspaceEdits(r, xact[0].Edit)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -575,7 +577,7 @@ func (r *runner) Rename(t *testing.T, spn span.Span, newText string) {
}
return
}
res, err := applyWorkspaceEdits(r, wedit)
res, err := applyWorkspaceEdits(r, *wedit)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -628,18 +630,23 @@ func (r *runner) PrepareRename(t *testing.T, src span.Span, want *source.Prepare
t.Errorf("prepare rename failed for %v: got error: %v", src, err)
return
}
if got == nil {
// we all love typed nils
if got == nil || got.(*protocol.Range) == nil {
if want.Text != "" { // expected an ident.
t.Errorf("prepare rename failed for %v: got nil", src)
}
return
}
if protocol.CompareRange(*got, want.Range) != 0 {
t.Errorf("prepare rename failed: incorrect range got %v want %v", *got, want.Range)
xx, ok := got.(*protocol.Range)
if !ok {
t.Fatalf("got %T, wanted Range", got)
}
if protocol.CompareRange(*xx, want.Range) != 0 {
t.Errorf("prepare rename failed: incorrect range got %v want %v", *xx, want.Range)
}
}

func applyWorkspaceEdits(r *runner, wedit *protocol.WorkspaceEdit) (map[span.URI]string, error) {
func applyWorkspaceEdits(r *runner, wedit protocol.WorkspaceEdit) (map[span.URI]string, error) {
res := map[span.URI]string{}
for _, docEdits := range wedit.DocumentChanges {
uri := span.URI(docEdits.TextDocument.URI)
Expand Down Expand Up @@ -682,7 +689,6 @@ func (r *runner) Symbols(t *testing.T, uri span.URI, expectedSymbols []protocol.
if err != nil {
t.Fatal(err)
}

if len(symbols) != len(expectedSymbols) {
t.Errorf("want %d top-level symbols in %v, got %d", len(expectedSymbols), uri, len(symbols))
return
Expand Down
12 changes: 11 additions & 1 deletion internal/lsp/protocol/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package protocol
import (
"context"
"encoding/json"
"fmt"

"golang.org/x/tools/internal/jsonrpc2"
"golang.org/x/tools/internal/telemetry/log"
Expand Down Expand Up @@ -39,7 +40,16 @@ func (canceller) Request(ctx context.Context, conn *jsonrpc2.Conn, direction jso
if err := json.Unmarshal(*r.Params, &params); err != nil {
log.Error(ctx, "", err)
} else {
conn.Cancel(params.ID)
v := jsonrpc2.ID{}
if n, ok := params.ID.(float64); ok {
v.Number = int64(n)
} else if s, ok := params.ID.(string); ok {
v.Name = s
} else {
log.Error(ctx, fmt.Sprintf("Request ID %v malformed", params.ID), nil)
return ctx
}
conn.Cancel(v)
}
}
return ctx
Expand Down
29 changes: 14 additions & 15 deletions internal/lsp/protocol/tsclient.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 5091d64

Please sign in to comment.