Skip to content

Commit 397fef9

Browse files
committed
gopls/internal/protocol: add links to LSP spec
This makes it a little easier to click one's way to the authoritative description. It isn't perfect; notably, the LSP spec has irregular anchors (workspace_symbolResolve should be workspaceSymbol_Resolve). Change-Id: I62f88b53d2398d777a298ca765f6c71167761e74 Reviewed-on: https://go-review.googlesource.com/c/tools/+/581120 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Peter Weinberger <[email protected]>
1 parent e2a352c commit 397fef9

File tree

6 files changed

+1035
-146
lines changed

6 files changed

+1035
-146
lines changed

gopls/internal/protocol/generate/main.go

Lines changed: 20 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ const vscodeRepo = "https://github.com/microsoft/vscode-languageserver-node"
2727

2828
// lspGitRef names a branch or tag in vscodeRepo.
2929
// It implicitly determines the protocol version of the LSP used by gopls.
30-
// For example, tag release/protocol/3.17.3 of the repo defines protocol version 3.17.0.
30+
// For example, tag release/protocol/3.17.3 of the repo defines
31+
// protocol version 3.17.0 (as declared by the metaData.version field).
3132
// (Point releases are reflected in the git tag version even when they are cosmetic
3233
// and don't change the protocol.)
3334
var lspGitRef = "release/protocol/3.17.6-next.2"
@@ -116,16 +117,7 @@ func writeclient() {
116117
for _, k := range cfuncs.keys() {
117118
out.WriteString(cfuncs[k])
118119
}
119-
120-
x, err := format.Source(out.Bytes())
121-
if err != nil {
122-
os.WriteFile("/tmp/a.go", out.Bytes(), 0644)
123-
log.Fatalf("tsclient.go: %v", err)
124-
}
125-
126-
if err := os.WriteFile(filepath.Join(*outputdir, "tsclient.go"), x, 0644); err != nil {
127-
log.Fatalf("%v writing tsclient.go", err)
128-
}
120+
formatTo("tsclient.go", out.Bytes())
129121
}
130122

131123
func writeserver() {
@@ -156,15 +148,7 @@ func serverDispatch(ctx context.Context, server Server, reply jsonrpc2.Replier,
156148
for _, k := range sfuncs.keys() {
157149
out.WriteString(sfuncs[k])
158150
}
159-
x, err := format.Source(out.Bytes())
160-
if err != nil {
161-
os.WriteFile("/tmp/a.go", out.Bytes(), 0644)
162-
log.Fatalf("tsserver.go: %v", err)
163-
}
164-
165-
if err := os.WriteFile(filepath.Join(*outputdir, "tsserver.go"), x, 0644); err != nil {
166-
log.Fatalf("%v writing tsserver.go", err)
167-
}
151+
formatTo("tsserver.go", out.Bytes())
168152
}
169153

170154
func writeprotocol() {
@@ -197,14 +181,7 @@ func writeprotocol() {
197181
out.WriteString(consts[k])
198182
}
199183
out.WriteString(")\n\n")
200-
x, err := format.Source(out.Bytes())
201-
if err != nil {
202-
os.WriteFile("/tmp/a.go", out.Bytes(), 0644)
203-
log.Fatalf("tsprotocol.go: %v", err)
204-
}
205-
if err := os.WriteFile(filepath.Join(*outputdir, "tsprotocol.go"), x, 0644); err != nil {
206-
log.Fatalf("%v writing tsprotocol.go", err)
207-
}
184+
formatTo("tsprotocol.go", out.Bytes())
208185
}
209186

210187
func writejsons() {
@@ -228,18 +205,24 @@ func (e UnmarshalError) Error() string {
228205
for _, k := range jsons.keys() {
229206
out.WriteString(jsons[k])
230207
}
231-
x, err := format.Source(out.Bytes())
208+
formatTo("tsjson.go", out.Bytes())
209+
}
210+
211+
// formatTo formats the Go source and writes it to *outputdir/basename.
212+
func formatTo(basename string, src []byte) {
213+
formatted, err := format.Source(src)
232214
if err != nil {
233-
os.WriteFile("/tmp/a.go", out.Bytes(), 0644)
234-
log.Fatalf("tsjson.go: %v", err)
215+
failed := filepath.Join("/tmp", basename+".fail")
216+
os.WriteFile(failed, src, 0644)
217+
log.Fatalf("formatting %s: %v (see %s)", basename, err, failed)
235218
}
236-
if err := os.WriteFile(filepath.Join(*outputdir, "tsjson.go"), x, 0644); err != nil {
237-
log.Fatalf("%v writing tsjson.go", err)
219+
if err := os.WriteFile(filepath.Join(*outputdir, basename), formatted, 0644); err != nil {
220+
log.Fatal(err)
238221
}
239222
}
240223

241224
// create the common file header for the output files
242-
func fileHeader(model Model) string {
225+
func fileHeader(model *Model) string {
243226
fname := filepath.Join(*repodir, ".git", "HEAD")
244227
buf, err := os.ReadFile(fname)
245228
if err != nil {
@@ -281,14 +264,14 @@ package protocol
281264
model.Version.Version) // 5
282265
}
283266

284-
func parse(fname string) Model {
267+
func parse(fname string) *Model {
285268
buf, err := os.ReadFile(fname)
286269
if err != nil {
287270
log.Fatal(err)
288271
}
289272
buf = addLineNumbers(buf)
290-
var model Model
291-
if err := json.Unmarshal(buf, &model); err != nil {
273+
model := new(Model)
274+
if err := json.Unmarshal(buf, model); err != nil {
292275
log.Fatal(err)
293276
}
294277
return model

gopls/internal/protocol/generate/output.go

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,19 @@ var (
2828
jsons = make(sortedMap[string])
2929
)
3030

31-
func generateOutput(model Model) {
31+
func generateOutput(model *Model) {
3232
for _, r := range model.Requests {
33-
genDecl(r.Method, r.Params, r.Result, r.Direction)
34-
genCase(r.Method, r.Params, r.Result, r.Direction)
35-
genFunc(r.Method, r.Params, r.Result, r.Direction, false)
33+
genDecl(model, r.Method, r.Params, r.Result, r.Direction)
34+
genCase(model, r.Method, r.Params, r.Result, r.Direction)
35+
genFunc(model, r.Method, r.Params, r.Result, r.Direction, false)
3636
}
3737
for _, n := range model.Notifications {
3838
if n.Method == "$/cancelRequest" {
3939
continue // handled internally by jsonrpc2
4040
}
41-
genDecl(n.Method, n.Params, nil, n.Direction)
42-
genCase(n.Method, n.Params, nil, n.Direction)
43-
genFunc(n.Method, n.Params, nil, n.Direction, true)
41+
genDecl(model, n.Method, n.Params, nil, n.Direction)
42+
genCase(model, n.Method, n.Params, nil, n.Direction)
43+
genFunc(model, n.Method, n.Params, nil, n.Direction, true)
4444
}
4545
genStructs(model)
4646
genAliases(model)
@@ -49,7 +49,7 @@ func generateOutput(model Model) {
4949
genMarshal()
5050
}
5151

52-
func genDecl(method string, param, result *Type, dir string) {
52+
func genDecl(model *Model, method string, param, result *Type, dir string) {
5353
fname := methodName(method)
5454
p := ""
5555
if notNil(param) {
@@ -71,7 +71,8 @@ func genDecl(method string, param, result *Type, dir string) {
7171
p = ", *ParamConfiguration"
7272
ret = "([]LSPAny, error)"
7373
}
74-
msg := fmt.Sprintf("\t%s(context.Context%s) %s // %s\n", fname, p, ret, method)
74+
fragment := strings.ReplaceAll(strings.TrimPrefix(method, "$/"), "/", "_")
75+
msg := fmt.Sprintf("\t%s\t%s(context.Context%s) %s\n", lspLink(model, fragment), fname, p, ret)
7576
switch dir {
7677
case "clientToServer":
7778
sdecls[method] = msg
@@ -85,7 +86,7 @@ func genDecl(method string, param, result *Type, dir string) {
8586
}
8687
}
8788

88-
func genCase(method string, param, result *Type, dir string) {
89+
func genCase(model *Model, method string, param, result *Type, dir string) {
8990
out := new(bytes.Buffer)
9091
fmt.Fprintf(out, "\tcase %q:\n", method)
9192
var p string
@@ -127,7 +128,7 @@ func genCase(method string, param, result *Type, dir string) {
127128
}
128129
}
129130

130-
func genFunc(method string, param, result *Type, dir string, isnotify bool) {
131+
func genFunc(model *Model, method string, param, result *Type, dir string, isnotify bool) {
131132
out := new(bytes.Buffer)
132133
var p, r string
133134
var goResult string
@@ -202,7 +203,7 @@ func genFunc(method string, param, result *Type, dir string, isnotify bool) {
202203
}
203204
}
204205

205-
func genStructs(model Model) {
206+
func genStructs(model *Model) {
206207
structures := make(map[string]*Structure) // for expanding Extends
207208
for _, s := range model.Structures {
208209
structures[s.Name] = s
@@ -215,6 +216,8 @@ func genStructs(model Model) {
215216
// a weird case, and needed only so the generated code contains the old gopls code
216217
nm = "DocumentDiagnosticParams"
217218
}
219+
fmt.Fprintf(out, "//\n")
220+
out.WriteString(lspLink(model, camelCase(s.Name)))
218221
fmt.Fprintf(out, "type %s struct {%s\n", nm, linex(s.Line))
219222
// for gpls compatibilitye, embed most extensions, but expand the rest some day
220223
props := append([]NameType{}, s.Properties...)
@@ -245,6 +248,19 @@ func genStructs(model Model) {
245248

246249
}
247250

251+
// "FooBar" -> "fooBar"
252+
func camelCase(TitleCased string) string {
253+
return strings.ToLower(TitleCased[:1]) + TitleCased[1:]
254+
}
255+
256+
func lspLink(model *Model, fragment string) string {
257+
// Derive URL version from metaData.version in JSON file.
258+
parts := strings.Split(model.Version.Version, ".") // e.g. "3.17.0"
259+
return fmt.Sprintf("// See https://microsoft.github.io/language-server-protocol/specifications/lsp/%s.%s/specification#%s\n",
260+
parts[0], parts[1], // major.minor
261+
fragment)
262+
}
263+
248264
func genProps(out *bytes.Buffer, props []NameType, name string) {
249265
for _, p := range props {
250266
tp := goplsName(p.Type)
@@ -263,7 +279,7 @@ func genProps(out *bytes.Buffer, props []NameType, name string) {
263279
}
264280
}
265281

266-
func genAliases(model Model) {
282+
func genAliases(model *Model) {
267283
for _, ta := range model.TypeAliases {
268284
out := new(bytes.Buffer)
269285
generateDoc(out, ta.Documentation)
@@ -272,6 +288,8 @@ func genAliases(model Model) {
272288
continue // renamed the type, e.g., "DocumentDiagnosticReport", an or-type to "string"
273289
}
274290
tp := goplsName(ta.Type)
291+
fmt.Fprintf(out, "//\n")
292+
out.WriteString(lspLink(model, camelCase(ta.Name)))
275293
fmt.Fprintf(out, "type %s = %s // (alias)\n", nm, tp)
276294
types[nm] = out.String()
277295
}
@@ -320,7 +338,7 @@ func genGenTypes() {
320338
types[nm] = out.String()
321339
}
322340
}
323-
func genConsts(model Model) {
341+
func genConsts(model *Model) {
324342
for _, e := range model.Enumerations {
325343
out := new(bytes.Buffer)
326344
generateDoc(out, e.Documentation)

gopls/internal/protocol/generate/typenames.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
var typeNames = make(map[*Type]string)
1414
var genTypes []*newType
1515

16-
func findTypeNames(model Model) {
16+
func findTypeNames(model *Model) {
1717
for _, s := range model.Structures {
1818
for _, e := range s.Extends {
1919
nameType(e, nil) // all references

gopls/internal/protocol/tsclient.go

Lines changed: 40 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)