MCP Language Server

// 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. package main import ( "bytes" "fmt" "log" "strings" "golang.org/x/text/cases" "golang.org/x/text/language" ) // 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 = cases.Title(language.English, cases.NoLower).String(s) // s = strings.Title(s) } return s }