internal/lsp/protocol: add support for upcoming LSP 3.16
These are the changes needed to support Semantic Tokens in the LSP protocol.
Added a function to server.go to make generating server_gen.go work again.
Change-Id: I2e09220560b080dd666e25eaf1a39b9960b6f871
Reviewed-on: https://go-review.googlesource.com/c/tools/+/253938
Run-TryBot: Peter Weinberger <pjw@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/internal/lsp/protocol/tsclient.go b/internal/lsp/protocol/tsclient.go
index 251c74a..d30594b 100644
--- a/internal/lsp/protocol/tsclient.go
+++ b/internal/lsp/protocol/tsclient.go
@@ -2,8 +2,8 @@
// Package protocol contains data types and code for LSP jsonrpcs
// generated automatically from vscode-languageserver-node
-// commit: 399de64448129835b53c7efe8962de91681d6cde
-// last fetched Wed Aug 26 2020 20:34:24 GMT-0400 (Eastern Daylight Time)
+// commit: 60a5a7825e6f54f57917091f394fd8db7d1724bc
+// last fetched Thu Sep 10 2020 09:21:57 GMT-0400 (Eastern Daylight Time)
// Code generated (see typescript/README.md) DO NOT EDIT.
diff --git a/internal/lsp/protocol/tsprotocol.go b/internal/lsp/protocol/tsprotocol.go
index 8d774a6..13d40c5 100644
--- a/internal/lsp/protocol/tsprotocol.go
+++ b/internal/lsp/protocol/tsprotocol.go
@@ -1,7 +1,7 @@
// Package protocol contains data types and code for LSP jsonrpcs
// generated automatically from vscode-languageserver-node
-// commit: 399de64448129835b53c7efe8962de91681d6cde
-// last fetched Wed Aug 26 2020 20:34:24 GMT-0400 (Eastern Daylight Time)
+// commit: 60a5a7825e6f54f57917091f394fd8db7d1724bc
+// last fetched Thu Sep 10 2020 09:21:57 GMT-0400 (Eastern Daylight Time)
package protocol
// Code generated (see typescript/README.md) DO NOT EDIT.
@@ -390,7 +390,7 @@
*/
Command Command `json:"command,omitempty"`
/**
- * An data entry field that is preserved on a code lens item between
+ * A data entry field that is preserved on a code lens item between
* a [CodeLensRequest](#CodeLensRequest) and a [CodeLensResolveRequest]
* (#CodeLensResolveRequest)
*/
@@ -748,7 +748,7 @@
*/
Command *Command `json:"command,omitempty"`
/**
- * An data entry field that is preserved on a completion item between
+ * A data entry field that is preserved on a completion item between
* a [CompletionRequest](#CompletionRequest) and a [CompletionResolveRequest]
* (#CompletionResolveRequest)
*/
@@ -900,7 +900,7 @@
type Declaration = []Location /*Location | Location[]*/
/**
- * Since 3.14.0
+ * @since 3.14.0
*/
type DeclarationClientCapabilities struct {
/**
@@ -1862,7 +1862,7 @@
}
/**
- * Since 3.6.0
+ * @since 3.6.0
*/
type ImplementationClientCapabilities struct {
/**
@@ -1874,7 +1874,7 @@
/**
* The client supports additional metadata in the form of definition links.
*
- * Since 3.14.0
+ * @since 3.14.0
*/
LinkSupport bool `json:"linkSupport,omitempty"`
}
@@ -2113,9 +2113,17 @@
ExecuteCommandProvider ExecuteCommandOptions `json:"executeCommandProvider,omitempty"`
/**
* The server provides Call Hierarchy support.
+ *
+ * @since 3.16.0 - Proposed state
*/
CallHierarchyProvider interface{}/* bool | CallHierarchyOptions | CallHierarchyRegistrationOptions*/ `json:"callHierarchyProvider,omitempty"`
/**
+ * The server provides semantic tokens support.
+ *
+ * @since 3.16.0 - Proposed state
+ */
+ SemanticTokensProvider interface{}/*SemanticTokensOptions | SemanticTokensRegistrationOptions*/ `json:"semanticTokensProvider,omitempty"`
+ /**
* Experimental server capabilities.
*/
Experimental interface{} `json:"experimental,omitempty"`
@@ -2506,6 +2514,12 @@
* @since version 3.12.0
*/
PrepareSupport bool `json:"prepareSupport,omitempty"`
+ /**
+ * Client supports the default behavior result.
+ *
+ * @since version 3.16.0
+ */
+ PrepareSupportDefaultBehavior bool `json:"prepareSupportDefaultBehavior,omitempty"`
}
/**
@@ -2682,7 +2696,8 @@
*/
TextDocument TextDocumentIdentifier `json:"textDocument"`
/**
- * The previous result id.
+ * The result id of a previous response. The result Id can either point to a full response
+ * or a delta response depending on what was recevied last.
*/
PreviousResultID string `json:"previousResultId"`
WorkDoneProgressParams
@@ -2710,6 +2725,40 @@
/**
* @since 3.16.0 - Proposed state
*/
+type SemanticTokensLegend struct {
+ /**
+ * The token types a server uses.
+ */
+ TokenTypes []string `json:"tokenTypes"`
+ /**
+ * The token modifiers a server uses.
+ */
+ TokenModifiers []string `json:"tokenModifiers"`
+}
+
+/**
+ * @since 3.16.0 - Proposed state
+ */
+type SemanticTokensOptions struct {
+ /**
+ * The legend used by the server
+ */
+ Legend SemanticTokensLegend `json:"legend"`
+ /**
+ * Server supports providing semantic tokens for a sepcific range
+ * of a document.
+ */
+ Range bool/*boolean | { }*/ `json:"range,omitempty"`
+ /**
+ * Server supports providing semantic tokens for a full document.
+ */
+ Full bool/*boolean | <elided struct>*/ `json:"full,omitempty"`
+ WorkDoneProgressOptions
+}
+
+/**
+ * @since 3.16.0 - Proposed state
+ */
type SemanticTokensParams struct {
/**
* The text document.
@@ -2735,6 +2784,15 @@
PartialResultParams
}
+/**
+ * @since 3.16.0 - Proposed state
+ */
+type SemanticTokensRegistrationOptions struct {
+ TextDocumentRegistrationOptions
+ SemanticTokensOptions
+ StaticRegistrationOptions
+}
+
type ServerCapabilities = struct {
/**
* Defines how text documents are synced. Is either a detailed structure defining each notification or
@@ -2835,9 +2893,17 @@
ExecuteCommandProvider ExecuteCommandOptions `json:"executeCommandProvider,omitempty"`
/**
* The server provides Call Hierarchy support.
+ *
+ * @since 3.16.0 - Proposed state
*/
CallHierarchyProvider interface{}/* bool | CallHierarchyOptions | CallHierarchyRegistrationOptions*/ `json:"callHierarchyProvider,omitempty"`
/**
+ * The server provides semantic tokens support.
+ *
+ * @since 3.16.0 - Proposed state
+ */
+ SemanticTokensProvider interface{}/*SemanticTokensOptions | SemanticTokensRegistrationOptions*/ `json:"semanticTokensProvider,omitempty"`
+ /**
* Experimental server capabilities.
*/
Experimental interface{} `json:"experimental,omitempty"`
diff --git a/internal/lsp/protocol/tsserver.go b/internal/lsp/protocol/tsserver.go
index 29285e0..d1dada3 100644
--- a/internal/lsp/protocol/tsserver.go
+++ b/internal/lsp/protocol/tsserver.go
@@ -2,8 +2,8 @@
// Package protocol contains data types and code for LSP jsonrpcs
// generated automatically from vscode-languageserver-node
-// commit: 399de64448129835b53c7efe8962de91681d6cde
-// last fetched Wed Aug 26 2020 20:34:24 GMT-0400 (Eastern Daylight Time)
+// commit: 60a5a7825e6f54f57917091f394fd8db7d1724bc
+// last fetched Thu Sep 10 2020 09:21:57 GMT-0400 (Eastern Daylight Time)
// Code generated (see typescript/README.md) DO NOT EDIT.
@@ -18,6 +18,7 @@
type Server interface {
DidChangeWorkspaceFolders(context.Context, *DidChangeWorkspaceFoldersParams) error
WorkDoneProgressCancel(context.Context, *WorkDoneProgressCancelParams) error
+ SemanticTokensRefresh(context.Context) error
Initialized(context.Context, *InitializedParams) error
Exit(context.Context) error
DidChangeConfiguration(context.Context, *DidChangeConfigurationParams) error
@@ -39,6 +40,9 @@
PrepareCallHierarchy(context.Context, *CallHierarchyPrepareParams) ([]CallHierarchyItem /*CallHierarchyItem[] | null*/, error)
IncomingCalls(context.Context, *CallHierarchyIncomingCallsParams) ([]CallHierarchyIncomingCall /*CallHierarchyIncomingCall[] | null*/, error)
OutgoingCalls(context.Context, *CallHierarchyOutgoingCallsParams) ([]CallHierarchyOutgoingCall /*CallHierarchyOutgoingCall[] | null*/, error)
+ SemanticTokensFull(context.Context, *SemanticTokensParams) (*SemanticTokens /*SemanticTokens | null*/, error)
+ SemanticTokensFullDelta(context.Context, *SemanticTokensDeltaParams) (interface{} /* SemanticTokens | SemanticTokensDelta | nil*/, error)
+ SemanticTokensRange(context.Context, *SemanticTokensRangeParams) (*SemanticTokens /*SemanticTokens | null*/, error)
Initialize(context.Context, *ParamInitialize) (*InitializeResult, error)
Shutdown(context.Context) error
WillSaveWaitUntil(context.Context, *WillSaveTextDocumentParams) ([]TextEdit /*TextEdit[] | null*/, error)
@@ -60,11 +64,8 @@
RangeFormatting(context.Context, *DocumentRangeFormattingParams) ([]TextEdit /*TextEdit[] | null*/, error)
OnTypeFormatting(context.Context, *DocumentOnTypeFormattingParams) ([]TextEdit /*TextEdit[] | null*/, error)
Rename(context.Context, *RenameParams) (*WorkspaceEdit /*WorkspaceEdit | null*/, error)
- PrepareRename(context.Context, *PrepareRenameParams) (*Range /*Range | { range: Range, placeholder: string } | null*/, error)
+ PrepareRename(context.Context, *PrepareRenameParams) (*Range /*Range | { range: Range, placeholder: string } | { defaultBehavior: boolean } | null*/, error)
ExecuteCommand(context.Context, *ExecuteCommandParams) (interface{} /*any | null*/, error)
- SemanticTokensFull(context.Context, *SemanticTokensParams) (*SemanticTokens /*SemanticTokens | null*/, error)
- SemanticTokensFullDelta(context.Context, *SemanticTokensDeltaParams) (interface{} /* SemanticTokens | SemanticTokensDelta | nil*/, error)
- SemanticTokensRange(context.Context, *SemanticTokensRangeParams) (*SemanticTokens /*SemanticTokens | null*/, error)
NonstandardRequest(ctx context.Context, method string, params interface{}) (interface{}, error)
}
@@ -84,6 +85,9 @@
}
err := server.WorkDoneProgressCancel(ctx, ¶ms)
return true, reply(ctx, nil, err)
+ case "workspace/semanticTokens/refresh": // notif
+ err := server.SemanticTokensRefresh(ctx)
+ return true, reply(ctx, nil, err)
case "initialized": // notif
var params InitializedParams
if err := json.Unmarshal(r.Params(), ¶ms); err != nil {
@@ -227,6 +231,27 @@
}
resp, err := server.OutgoingCalls(ctx, ¶ms)
return true, reply(ctx, resp, err)
+ case "textDocument/semanticTokens/full": // req
+ var params SemanticTokensParams
+ if err := json.Unmarshal(r.Params(), ¶ms); err != nil {
+ return true, sendParseError(ctx, reply, err)
+ }
+ resp, err := server.SemanticTokensFull(ctx, ¶ms)
+ return true, reply(ctx, resp, err)
+ case "textDocument/semanticTokens/full/delta": // req
+ var params SemanticTokensDeltaParams
+ if err := json.Unmarshal(r.Params(), ¶ms); err != nil {
+ return true, sendParseError(ctx, reply, err)
+ }
+ resp, err := server.SemanticTokensFullDelta(ctx, ¶ms)
+ return true, reply(ctx, resp, err)
+ case "textDocument/semanticTokens/range": // req
+ var params SemanticTokensRangeParams
+ if err := json.Unmarshal(r.Params(), ¶ms); err != nil {
+ return true, sendParseError(ctx, reply, err)
+ }
+ resp, err := server.SemanticTokensRange(ctx, ¶ms)
+ return true, reply(ctx, resp, err)
case "initialize": // req
var params ParamInitialize
if err := json.Unmarshal(r.Params(), ¶ms); err != nil {
@@ -387,27 +412,6 @@
}
resp, err := server.ExecuteCommand(ctx, ¶ms)
return true, reply(ctx, resp, err)
- case "textDocument/semanticTokens/full": // req
- var params SemanticTokensParams
- if err := json.Unmarshal(r.Params(), ¶ms); err != nil {
- return true, sendParseError(ctx, reply, err)
- }
- resp, err := server.SemanticTokensFull(ctx, ¶ms)
- return true, reply(ctx, resp, err)
- case "textDocument/semanticTokens/full/delta": // req
- var params SemanticTokensDeltaParams
- if err := json.Unmarshal(r.Params(), ¶ms); err != nil {
- return true, sendParseError(ctx, reply, err)
- }
- resp, err := server.SemanticTokensFullDelta(ctx, ¶ms)
- return true, reply(ctx, resp, err)
- case "textDocument/semanticTokens/range": // req
- var params SemanticTokensRangeParams
- if err := json.Unmarshal(r.Params(), ¶ms); err != nil {
- return true, sendParseError(ctx, reply, err)
- }
- resp, err := server.SemanticTokensRange(ctx, ¶ms)
- return true, reply(ctx, resp, err)
default:
return false, nil
@@ -422,6 +426,10 @@
return s.Conn.Notify(ctx, "window/workDoneProgress/cancel", params)
}
+func (s *serverDispatcher) SemanticTokensRefresh(ctx context.Context) error {
+ return s.Conn.Notify(ctx, "workspace/semanticTokens/refresh", nil)
+}
+
func (s *serverDispatcher) Initialized(ctx context.Context, params *InitializedParams) error {
return s.Conn.Notify(ctx, "initialized", params)
}
@@ -545,6 +553,30 @@
return result, nil
}
+func (s *serverDispatcher) SemanticTokensFull(ctx context.Context, params *SemanticTokensParams) (*SemanticTokens /*SemanticTokens | null*/, error) {
+ var result *SemanticTokens /*SemanticTokens | null*/
+ if err := Call(ctx, s.Conn, "textDocument/semanticTokens/full", params, &result); err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+func (s *serverDispatcher) SemanticTokensFullDelta(ctx context.Context, params *SemanticTokensDeltaParams) (interface{} /* SemanticTokens | SemanticTokensDelta | nil*/, error) {
+ var result interface{} /* SemanticTokens | SemanticTokensDelta | nil*/
+ if err := Call(ctx, s.Conn, "textDocument/semanticTokens/full/delta", params, &result); err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
+func (s *serverDispatcher) SemanticTokensRange(ctx context.Context, params *SemanticTokensRangeParams) (*SemanticTokens /*SemanticTokens | null*/, error) {
+ var result *SemanticTokens /*SemanticTokens | null*/
+ if err := Call(ctx, s.Conn, "textDocument/semanticTokens/range", params, &result); err != nil {
+ return nil, err
+ }
+ return result, nil
+}
+
func (s *serverDispatcher) Initialize(ctx context.Context, params *ParamInitialize) (*InitializeResult, error) {
var result *InitializeResult
if err := Call(ctx, s.Conn, "initialize", params, &result); err != nil {
@@ -709,8 +741,8 @@
return result, nil
}
-func (s *serverDispatcher) PrepareRename(ctx context.Context, params *PrepareRenameParams) (*Range /*Range | { range: Range, placeholder: string } | null*/, error) {
- var result *Range /*Range | { range: Range, placeholder: string } | null*/
+func (s *serverDispatcher) PrepareRename(ctx context.Context, params *PrepareRenameParams) (*Range /*Range | { range: Range, placeholder: string } | { defaultBehavior: boolean } | null*/, error) {
+ var result *Range /*Range | { range: Range, placeholder: string } | { defaultBehavior: boolean } | null*/
if err := Call(ctx, s.Conn, "textDocument/prepareRename", params, &result); err != nil {
return nil, err
}
@@ -725,30 +757,6 @@
return result, nil
}
-func (s *serverDispatcher) SemanticTokensFull(ctx context.Context, params *SemanticTokensParams) (*SemanticTokens /*SemanticTokens | null*/, error) {
- var result *SemanticTokens /*SemanticTokens | null*/
- if err := Call(ctx, s.Conn, "textDocument/semanticTokens/full", params, &result); err != nil {
- return nil, err
- }
- return result, nil
-}
-
-func (s *serverDispatcher) SemanticTokensFullDelta(ctx context.Context, params *SemanticTokensDeltaParams) (interface{} /* SemanticTokens | SemanticTokensDelta | nil*/, error) {
- var result interface{} /* SemanticTokens | SemanticTokensDelta | nil*/
- if err := Call(ctx, s.Conn, "textDocument/semanticTokens/full/delta", params, &result); err != nil {
- return nil, err
- }
- return result, nil
-}
-
-func (s *serverDispatcher) SemanticTokensRange(ctx context.Context, params *SemanticTokensRangeParams) (*SemanticTokens /*SemanticTokens | null*/, error) {
- var result *SemanticTokens /*SemanticTokens | null*/
- if err := Call(ctx, s.Conn, "textDocument/semanticTokens/range", params, &result); err != nil {
- return nil, err
- }
- return result, nil
-}
-
func (s *serverDispatcher) NonstandardRequest(ctx context.Context, method string, params interface{}) (interface{}, error) {
var result interface{}
if err := Call(ctx, s.Conn, method, params, &result); err != nil {
diff --git a/internal/lsp/protocol/typescript/code.ts b/internal/lsp/protocol/typescript/code.ts
index 0bf9265..39cea15 100644
--- a/internal/lsp/protocol/typescript/code.ts
+++ b/internal/lsp/protocol/typescript/code.ts
@@ -70,9 +70,13 @@
const decl: ts.VariableDeclaration = dl.declarations[0];
const name = decl.name.getText()
// we want the initializers
- if (name == 'method') { // StringLiteral
- if (!ts.isStringLiteral(decl.initializer))
- throw new Error(`expect StringLiteral at ${loc(decl)}`);
+ if (name == 'method') { // mostly StringLiteral but NoSubstitutionTemplateLiteral in protocol.semanticTokens.ts
+ if (!ts.isStringLiteral(decl.initializer)) {
+ if (!ts.isNoSubstitutionTemplateLiteral(decl.initializer)) {
+ console.log(`${decl.initializer.getText()}`);
+ throw new Error(`expect StringLiteral at ${loc(decl)} got ${strKind(decl.initializer)}`);
+ }
+ }
rpc = decl.initializer.getText()
}
else if (name == 'type') { // NewExpression
@@ -520,7 +524,7 @@
ans = ans.concat(getComments(n));
const json = u.JSON(n);
// SelectionRange is a recursive type
- let gt = goType(n.type, n.name.getText());
+ let gt = goType(n.type, n.name.getText(), nm);
if (gt == d.name) gt = '*' + gt; // avoid recursive types
// there are several cases where a * is needed
starred.forEach(([a, b]) => {
@@ -613,12 +617,12 @@
}
// return a go type and maybe an assocated javascript tag
-function goType(n: ts.TypeNode, nm: string): string {
+function goType(n: ts.TypeNode, nm: string, parent?: string): string {
if (n.getText() == 'T') return 'interface{}'; // should check it's generic
if (ts.isTypeReferenceNode(n)) {
return goName(n.typeName.getText()); // avoid <T>
} else if (ts.isUnionTypeNode(n)) {
- return goUnionType(n, nm);
+ return goUnionType(n, nm, parent);
} else if (ts.isIntersectionTypeNode(n)) {
return goIntersectionType(n, nm);
} else if (strKind(n) == 'StringKeyword') {
@@ -659,8 +663,16 @@
// The choice is uniform interface{}, or some heuristically assigned choice,
// or some better sytematic idea I haven't thought of. Using interface{}
// is, in practice, impossibly complex in the existing code.
-function goUnionType(n: ts.UnionTypeNode, nm: string): string {
- const help = `/*${n.getText()}*/` // show the original as a comment
+function goUnionType(n: ts.UnionTypeNode, nm: string, parent?: string): string {
+ let help = `/*${n.getText()}*/` // show the original as a comment
+ // There are some bad cases with newlines:
+ // range?: boolean | {\n };
+ // full?: boolean | {\n /**\n * The server supports deltas for full documents.\n */\n delta?: boolean;\n }
+ // These are handled specially:
+ if (parent == 'SemanticTokensOptions') {
+ if (nm == 'range') help = help.replace(/\n/, '');
+ if (nm == 'full') help = '/*boolean | <elided struct>*/';
+ }
// handle all the special cases
switch (n.types.length) {
case 2:
@@ -725,8 +737,9 @@
break;
case 4:
if (nm == 'documentChanges') return `TextDocumentEdit ${help} `;
+ if (nm == 'textDocument/prepareRename') return `Range ${help} `;
default:
- throw new Error(`goUnionType ${n.types.length} `)
+ throw new Error(`goUnionType len=${n.types.length} nm=${nm}`)
}
// Result will be interface{} with a comment
diff --git a/internal/lsp/protocol/typescript/util.ts b/internal/lsp/protocol/typescript/util.ts
index 13815d5..77b2023 100644
--- a/internal/lsp/protocol/typescript/util.ts
+++ b/internal/lsp/protocol/typescript/util.ts
@@ -14,7 +14,7 @@
`${dir}/${srcDir}/protocol/src/browser/main.ts`, `${dir}${srcDir}/types/src/main.ts`,
`${dir}${srcDir}/jsonrpc/src/node/main.ts`
];
-export const gitHash = '399de64448129835b53c7efe8962de91681d6cde'
+export const gitHash = '60a5a7825e6f54f57917091f394fd8db7d1724bc'
let outFname = 'tsprotocol.go';
let fda: number, fdb: number, fde: number; // file descriptors
diff --git a/internal/lsp/server.go b/internal/lsp/server.go
index c135b34..dfc2222 100644
--- a/internal/lsp/server.go
+++ b/internal/lsp/server.go
@@ -104,6 +104,10 @@
snapshotID uint64
}
+func (s *Server) workDoneProgressCancel(ctx context.Context, params *protocol.WorkDoneProgressCancelParams) error {
+ return s.progress.cancel(ctx, params.Token)
+}
+
func (s *Server) nonstandardRequest(ctx context.Context, method string, params interface{}) (interface{}, error) {
paramMap := params.(map[string]interface{})
if method == "gopls/diagnoseFiles" {
diff --git a/internal/lsp/server_gen.go b/internal/lsp/server_gen.go
index 471f1a4..d22a5eb 100644
--- a/internal/lsp/server_gen.go
+++ b/internal/lsp/server_gen.go
@@ -176,6 +176,10 @@
return nil, notImplemented("SemanticTokensRange")
}
+func (s *Server) SemanticTokensRefresh(context.Context) error {
+ return notImplemented("SemanticTokensRefresh")
+}
+
func (s *Server) SetTrace(context.Context, *protocol.SetTraceParams) error {
return notImplemented("SetTrace")
}
@@ -205,5 +209,5 @@
}
func (s *Server) WorkDoneProgressCancel(ctx context.Context, params *protocol.WorkDoneProgressCancelParams) error {
- return s.progress.cancel(ctx, params.Token)
+ return s.workDoneProgressCancel(ctx, params)
}