golang.org/x/tools/gopls@v0.15.3/internal/protocol/generate/generate.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build go1.19 6 // +build go1.19 7 8 package main 9 10 import ( 11 "bytes" 12 "fmt" 13 "log" 14 "strings" 15 ) 16 17 // a newType is a type that needs a name and a definition 18 // These are the various types that the json specification doesn't name 19 type newType struct { 20 name string 21 properties Properties // for struct/literal types 22 items []*Type // for other types ("and", "tuple") 23 line int 24 kind string // Or, And, Tuple, Lit, Map 25 typ *Type 26 } 27 28 func generateDoc(out *bytes.Buffer, doc string) { 29 if doc == "" { 30 return 31 } 32 33 if !strings.Contains(doc, "\n") { 34 fmt.Fprintf(out, "// %s\n", doc) 35 return 36 } 37 var list bool 38 for _, line := range strings.Split(doc, "\n") { 39 // Lists in metaModel.json start with a dash. 40 // To make a go doc list they have to be preceded 41 // by a blank line, and indented. 42 // (see type TextDccumentFilter in protocol.go) 43 if len(line) > 0 && line[0] == '-' { 44 if !list { 45 list = true 46 fmt.Fprintf(out, "//\n") 47 } 48 fmt.Fprintf(out, "// %s\n", line) 49 } else { 50 if len(line) == 0 { 51 list = false 52 } 53 fmt.Fprintf(out, "// %s\n", line) 54 } 55 } 56 } 57 58 // decide if a property is optional, and if it needs a * 59 // return ",omitempty" if it is optional, and "*" if it needs a pointer 60 func propStar(name string, t NameType, gotype string) (string, string) { 61 var opt, star string 62 if t.Optional { 63 star = "*" 64 opt = ",omitempty" 65 } 66 if strings.HasPrefix(gotype, "[]") || strings.HasPrefix(gotype, "map[") { 67 star = "" // passed by reference, so no need for * 68 } else { 69 switch gotype { 70 case "bool", "uint32", "int32", "string", "interface{}": 71 star = "" // gopls compatibility if t.Optional 72 } 73 } 74 ostar, oopt := star, opt 75 if newStar, ok := goplsStar[prop{name, t.Name}]; ok { 76 switch newStar { 77 case nothing: 78 star, opt = "", "" 79 case wantStar: 80 star, opt = "*", "" 81 case wantOpt: 82 star, opt = "", ",omitempty" 83 case wantOptStar: 84 star, opt = "*", ",omitempty" 85 } 86 if star == ostar && opt == oopt { // no change 87 log.Printf("goplsStar[ {%q, %q} ](%d) useless %s/%s %s/%s", name, t.Name, t.Line, ostar, star, oopt, opt) 88 } 89 usedGoplsStar[prop{name, t.Name}] = true 90 } 91 92 return opt, star 93 } 94 95 func goName(s string) string { 96 // Go naming conventions 97 if strings.HasSuffix(s, "Id") { 98 s = s[:len(s)-len("Id")] + "ID" 99 } else if strings.HasSuffix(s, "Uri") { 100 s = s[:len(s)-3] + "URI" 101 } else if s == "uri" { 102 s = "URI" 103 } else if s == "id" { 104 s = "ID" 105 } 106 107 // renames for temporary GOPLS compatibility 108 if news := goplsType[s]; news != "" { 109 usedGoplsType[s] = true 110 s = news 111 } 112 // Names beginning _ are not exported 113 if strings.HasPrefix(s, "_") { 114 s = strings.Replace(s, "_", "X", 1) 115 } 116 if s != "string" { // base types are unchanged (textDocuemnt/diagnostic) 117 // Title is deprecated, but a) s is only one word, b) replacement is too heavy-weight 118 s = strings.Title(s) 119 } 120 return s 121 }