diff options
Diffstat (limited to 'gopls/internal/lsp/protocol/generate/generate.go')
-rw-r--r-- | gopls/internal/lsp/protocol/generate/generate.go | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/gopls/internal/lsp/protocol/generate/generate.go b/gopls/internal/lsp/protocol/generate/generate.go new file mode 100644 index 000000000..0496b7d06 --- /dev/null +++ b/gopls/internal/lsp/protocol/generate/generate.go @@ -0,0 +1,121 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.19 +// +build go1.19 + +package main + +import ( + "bytes" + "fmt" + "log" + "strings" +) + +// a newType is a type that needs a name and a definition +// These are the various types that the json specification doesn't name +type newType struct { + name string + properties Properties // for struct/literal types + items []*Type // for other types ("and", "tuple") + line int + kind string // Or, And, Tuple, Lit, Map + typ *Type +} + +func generateDoc(out *bytes.Buffer, doc string) { + if doc == "" { + return + } + + if !strings.Contains(doc, "\n") { + fmt.Fprintf(out, "// %s\n", doc) + return + } + var list bool + for _, line := range strings.Split(doc, "\n") { + // Lists in metaModel.json start with a dash. + // To make a go doc list they have to be preceded + // by a blank line, and indented. + // (see type TextDccumentFilter in protocol.go) + if len(line) > 0 && line[0] == '-' { + if !list { + list = true + fmt.Fprintf(out, "//\n") + } + fmt.Fprintf(out, "// %s\n", line) + } else { + if len(line) == 0 { + list = false + } + fmt.Fprintf(out, "// %s\n", line) + } + } +} + +// decide if a property is optional, and if it needs a * +// return ",omitempty" if it is optional, and "*" if it needs a pointer +func propStar(name string, t NameType, gotype string) (string, string) { + var opt, star string + if t.Optional { + star = "*" + opt = ",omitempty" + } + if strings.HasPrefix(gotype, "[]") || strings.HasPrefix(gotype, "map[") { + star = "" // passed by reference, so no need for * + } else { + switch gotype { + case "bool", "uint32", "int32", "string", "interface{}": + star = "" // gopls compatibility if t.Optional + } + } + ostar, oopt := star, opt + if newStar, ok := goplsStar[prop{name, t.Name}]; ok { + switch newStar { + case nothing: + star, opt = "", "" + case wantStar: + star, opt = "*", "" + case wantOpt: + star, opt = "", ",omitempty" + case wantOptStar: + star, opt = "*", ",omitempty" + } + if star == ostar && opt == oopt { // no change + log.Printf("goplsStar[ {%q, %q} ](%d) useless %s/%s %s/%s", name, t.Name, t.Line, ostar, star, oopt, opt) + } + usedGoplsStar[prop{name, t.Name}] = true + } + + return opt, star +} + +func goName(s string) string { + // Go naming conventions + if strings.HasSuffix(s, "Id") { + s = s[:len(s)-len("Id")] + "ID" + } else if strings.HasSuffix(s, "Uri") { + s = s[:len(s)-3] + "URI" + } else if s == "uri" { + s = "URI" + } else if s == "id" { + s = "ID" + } + + // renames for temporary GOPLS compatibility + if news := goplsType[s]; news != "" { + usedGoplsType[s] = true + s = news + } + // Names beginning _ are not exported + if strings.HasPrefix(s, "_") { + s = strings.Replace(s, "_", "X", 1) + } + if s != "string" { // base types are unchanged (textDocuemnt/diagnostic) + // Title is deprecated, but a) s is only one word, b) replacement is too heavy-weight + s = strings.Title(s) + } + return s +} |