mirror of https://github.com/golang/go.git
156 lines
3.5 KiB
Go
156 lines
3.5 KiB
Go
// Copyright 2021 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 gen is used to generate command bindings from the gopls command
|
|
// interface.
|
|
package gen
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"go/types"
|
|
"text/template"
|
|
|
|
"golang.org/x/tools/internal/imports"
|
|
"golang.org/x/tools/internal/lsp/command/commandmeta"
|
|
)
|
|
|
|
const src = `// Copyright 2021 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.
|
|
|
|
// Don't include this file during code generation, or it will break the build
|
|
// if existing interface methods have been modified.
|
|
//go:build !generate
|
|
// +build !generate
|
|
|
|
package command
|
|
|
|
// Code generated by generate.go. DO NOT EDIT.
|
|
|
|
import (
|
|
{{range $k, $v := .Imports -}}
|
|
"{{$k}}"
|
|
{{end}}
|
|
)
|
|
|
|
const (
|
|
{{- range .Commands}}
|
|
{{.MethodName}} Command = "{{.Name}}"
|
|
{{- end}}
|
|
)
|
|
|
|
var Commands = []Command {
|
|
{{- range .Commands}}
|
|
{{.MethodName}},
|
|
{{- end}}
|
|
}
|
|
|
|
func Dispatch(ctx context.Context, params *protocol.ExecuteCommandParams, s Interface) (interface{}, error) {
|
|
switch params.Command {
|
|
{{- range .Commands}}
|
|
case "{{.ID}}":
|
|
{{- if .Args -}}
|
|
{{- range $i, $v := .Args}}
|
|
var a{{$i}} {{typeString $v.Type}}
|
|
{{- end}}
|
|
if err := UnmarshalArgs(params.Arguments{{range $i, $v := .Args}}, &a{{$i}}{{end}}); err != nil {
|
|
return nil, err
|
|
}
|
|
{{end -}}
|
|
return {{if not .Result}}nil, {{end}}s.{{.MethodName}}(ctx{{range $i, $v := .Args}}, a{{$i}}{{end}})
|
|
{{- end}}
|
|
}
|
|
return nil, fmt.Errorf("unsupported command %q", params.Command)
|
|
}
|
|
{{- range .Commands}}
|
|
|
|
func New{{.MethodName}}Command(title string, {{range $i, $v := .Args}}{{if $i}}, {{end}}a{{$i}} {{typeString $v.Type}}{{end}}) (protocol.Command, error) {
|
|
args, err := MarshalArgs({{range $i, $v := .Args}}{{if $i}}, {{end}}a{{$i}}{{end}})
|
|
if err != nil {
|
|
return protocol.Command{}, err
|
|
}
|
|
return protocol.Command{
|
|
Title: title,
|
|
Command: "{{.ID}}",
|
|
Arguments: args,
|
|
}, nil
|
|
}
|
|
{{end}}
|
|
`
|
|
|
|
type data struct {
|
|
Imports map[string]bool
|
|
Commands []*commandmeta.Command
|
|
}
|
|
|
|
func Generate() ([]byte, error) {
|
|
pkg, cmds, err := commandmeta.Load()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("loading command data: %v", err)
|
|
}
|
|
qf := func(p *types.Package) string {
|
|
if p == pkg.Types {
|
|
return ""
|
|
}
|
|
return p.Name()
|
|
}
|
|
tmpl, err := template.New("").Funcs(template.FuncMap{
|
|
"typeString": func(t types.Type) string {
|
|
return types.TypeString(t, qf)
|
|
},
|
|
}).Parse(src)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
d := data{
|
|
Commands: cmds,
|
|
Imports: map[string]bool{
|
|
"context": true,
|
|
"fmt": true,
|
|
"golang.org/x/tools/internal/lsp/protocol": true,
|
|
},
|
|
}
|
|
const thispkg = "golang.org/x/tools/internal/lsp/command"
|
|
for _, c := range d.Commands {
|
|
for _, arg := range c.Args {
|
|
pth := pkgPath(arg.Type)
|
|
if pth != "" && pth != thispkg {
|
|
d.Imports[pth] = true
|
|
}
|
|
}
|
|
if c.Result != nil {
|
|
pth := pkgPath(c.Result.Type)
|
|
if pth != "" && pth != thispkg {
|
|
d.Imports[pth] = true
|
|
}
|
|
}
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
if err := tmpl.Execute(&buf, d); err != nil {
|
|
return nil, fmt.Errorf("executing: %v", err)
|
|
}
|
|
|
|
opts := &imports.Options{
|
|
AllErrors: true,
|
|
FormatOnly: true,
|
|
Comments: true,
|
|
}
|
|
content, err := imports.Process("", buf.Bytes(), opts)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("goimports: %v", err)
|
|
}
|
|
return content, nil
|
|
}
|
|
|
|
func pkgPath(t types.Type) string {
|
|
if n, ok := t.(*types.Named); ok {
|
|
if pkg := n.Obj().Pkg(); pkg != nil {
|
|
return pkg.Path()
|
|
}
|
|
}
|
|
return ""
|
|
}
|