1// Copyright 2019 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
5package cmd
6
7import (
8	"bytes"
9	"context"
10	"encoding/json"
11	"flag"
12	"fmt"
13	"net/url"
14	"os"
15	"strings"
16
17	"golang.org/x/tools/internal/lsp/browser"
18	"golang.org/x/tools/internal/lsp/debug"
19	"golang.org/x/tools/internal/lsp/source"
20)
21
22// version implements the version command.
23type version struct {
24	app *Application
25}
26
27func (v *version) Name() string      { return "version" }
28func (v *version) Usage() string     { return "" }
29func (v *version) ShortHelp() string { return "print the gopls version information" }
30func (v *version) DetailedHelp(f *flag.FlagSet) {
31	fmt.Fprint(f.Output(), ``)
32	f.PrintDefaults()
33}
34
35// Run prints version information to stdout.
36func (v *version) Run(ctx context.Context, args ...string) error {
37	debug.PrintVersionInfo(ctx, os.Stdout, v.app.verbose(), debug.PlainText)
38	return nil
39}
40
41// bug implements the bug command.
42type bug struct{}
43
44func (b *bug) Name() string      { return "bug" }
45func (b *bug) Usage() string     { return "" }
46func (b *bug) ShortHelp() string { return "report a bug in gopls" }
47func (b *bug) DetailedHelp(f *flag.FlagSet) {
48	fmt.Fprint(f.Output(), ``)
49	f.PrintDefaults()
50}
51
52const goplsBugPrefix = "x/tools/gopls: <DESCRIBE THE PROBLEM>"
53const goplsBugHeader = `ATTENTION: Please answer these questions BEFORE submitting your issue. Thanks!
54
55#### What did you do?
56If possible, provide a recipe for reproducing the error.
57A complete runnable program is good.
58A link on play.golang.org is better.
59A failing unit test is the best.
60
61#### What did you expect to see?
62
63
64#### What did you see instead?
65
66
67`
68
69// Run collects some basic information and then prepares an issue ready to
70// be reported.
71func (b *bug) Run(ctx context.Context, args ...string) error {
72	buf := &bytes.Buffer{}
73	fmt.Fprint(buf, goplsBugHeader)
74	debug.PrintVersionInfo(ctx, buf, true, debug.Markdown)
75	body := buf.String()
76	title := strings.Join(args, " ")
77	if !strings.HasPrefix(title, goplsBugPrefix) {
78		title = goplsBugPrefix + title
79	}
80	if !browser.Open("https://github.com/golang/go/issues/new?title=" + url.QueryEscape(title) + "&body=" + url.QueryEscape(body)) {
81		fmt.Print("Please file a new issue at golang.org/issue/new using this template:\n\n")
82		fmt.Print(body)
83	}
84	return nil
85}
86
87type apiJSON struct{}
88
89func (sj *apiJSON) Name() string      { return "api-json" }
90func (sj *apiJSON) Usage() string     { return "" }
91func (sj *apiJSON) ShortHelp() string { return "print json describing gopls API" }
92func (sj *apiJSON) DetailedHelp(f *flag.FlagSet) {
93	fmt.Fprint(f.Output(), ``)
94	f.PrintDefaults()
95}
96
97func (sj *apiJSON) Run(ctx context.Context, args ...string) error {
98	js, err := json.MarshalIndent(source.GeneratedAPIJSON, "", "\t")
99	if err != nil {
100		return err
101	}
102	fmt.Fprint(os.Stdout, string(js))
103	return nil
104}
105