golang.org/x/tools/gopls@v0.15.3/internal/protocol/command/gen/gen.go (about) 1 // Copyright 2021 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 // Package gen is used to generate command bindings from the gopls command 6 // interface. 7 package gen 8 9 import ( 10 "bytes" 11 "fmt" 12 "go/types" 13 "text/template" 14 15 "golang.org/x/tools/gopls/internal/protocol/command/commandmeta" 16 "golang.org/x/tools/internal/imports" 17 ) 18 19 const src = `// Copyright 2021 The Go Authors. All rights reserved. 20 // Use of this source code is governed by a BSD-style 21 // license that can be found in the LICENSE file. 22 23 // Don't include this file during code generation, or it will break the build 24 // if existing interface methods have been modified. 25 //go:build !generate 26 // +build !generate 27 28 // Code generated by gen.go. DO NOT EDIT. 29 30 package command 31 32 import ( 33 {{range $k, $v := .Imports -}} 34 "{{$k}}" 35 {{end}} 36 ) 37 38 // Symbolic names for gopls commands, excluding "gopls." prefix. 39 // These commands may be requested by ExecuteCommand, CodeLens, 40 // CodeAction, and other LSP requests. 41 const ( 42 {{- range .Commands}} 43 {{.MethodName}} Command = "{{.Name}}" 44 {{- end}} 45 ) 46 47 var Commands = []Command { 48 {{- range .Commands}} 49 {{.MethodName}}, 50 {{- end}} 51 } 52 53 func Dispatch(ctx context.Context, params *protocol.ExecuteCommandParams, s Interface) (interface{}, error) { 54 switch params.Command { 55 {{- range .Commands}} 56 case "{{.ID}}": 57 {{- if .Args -}} 58 {{- range $i, $v := .Args}} 59 var a{{$i}} {{typeString $v.Type}} 60 {{- end}} 61 if err := UnmarshalArgs(params.Arguments{{range $i, $v := .Args}}, &a{{$i}}{{end}}); err != nil { 62 return nil, err 63 } 64 {{end -}} 65 return {{if not .Result}}nil, {{end}}s.{{.MethodName}}(ctx{{range $i, $v := .Args}}, a{{$i}}{{end}}) 66 {{- end}} 67 } 68 return nil, fmt.Errorf("unsupported command %q", params.Command) 69 } 70 {{- range .Commands}} 71 72 func New{{.MethodName}}Command(title string, {{range $i, $v := .Args}}{{if $i}}, {{end}}a{{$i}} {{typeString $v.Type}}{{end}}) (protocol.Command, error) { 73 args, err := MarshalArgs({{range $i, $v := .Args}}{{if $i}}, {{end}}a{{$i}}{{end}}) 74 if err != nil { 75 return protocol.Command{}, err 76 } 77 return protocol.Command{ 78 Title: title, 79 Command: "{{.ID}}", 80 Arguments: args, 81 }, nil 82 } 83 {{end}} 84 ` 85 86 type data struct { 87 Imports map[string]bool 88 Commands []*commandmeta.Command 89 } 90 91 func Generate() ([]byte, error) { 92 pkg, cmds, err := commandmeta.Load() 93 if err != nil { 94 return nil, fmt.Errorf("loading command data: %v", err) 95 } 96 qf := func(p *types.Package) string { 97 if p == pkg.Types { 98 return "" 99 } 100 return p.Name() 101 } 102 tmpl, err := template.New("").Funcs(template.FuncMap{ 103 "typeString": func(t types.Type) string { 104 return types.TypeString(t, qf) 105 }, 106 }).Parse(src) 107 if err != nil { 108 return nil, err 109 } 110 d := data{ 111 Commands: cmds, 112 Imports: map[string]bool{ 113 "context": true, 114 "fmt": true, 115 "golang.org/x/tools/gopls/internal/protocol": true, 116 }, 117 } 118 const thispkg = "golang.org/x/tools/gopls/internal/protocol/command" 119 for _, c := range d.Commands { 120 for _, arg := range c.Args { 121 pth := pkgPath(arg.Type) 122 if pth != "" && pth != thispkg { 123 d.Imports[pth] = true 124 } 125 } 126 if c.Result != nil { 127 pth := pkgPath(c.Result.Type) 128 if pth != "" && pth != thispkg { 129 d.Imports[pth] = true 130 } 131 } 132 } 133 134 var buf bytes.Buffer 135 if err := tmpl.Execute(&buf, d); err != nil { 136 return nil, fmt.Errorf("executing: %v", err) 137 } 138 139 opts := &imports.Options{ 140 AllErrors: true, 141 FormatOnly: true, 142 Comments: true, 143 } 144 content, err := imports.Process("", buf.Bytes(), opts) 145 if err != nil { 146 return nil, fmt.Errorf("goimports: %v", err) 147 } 148 return content, nil 149 } 150 151 func pkgPath(t types.Type) string { 152 if n, ok := t.(*types.Named); ok { 153 if pkg := n.Obj().Pkg(); pkg != nil { 154 return pkg.Path() 155 } 156 } 157 return "" 158 }