diff options
author | Rebecca Stambler <rstambler@golang.org> | 2020-04-21 21:28:44 -0400 |
---|---|---|
committer | Rebecca Stambler <rstambler@golang.org> | 2020-04-22 20:52:58 +0000 |
commit | 72e4a01eba4315301fd9ce00c8c2f492580ded8a (patch) | |
tree | 3048e7b3c18aabd69e698e24a5ad7bb45ed2696f /internal/lsp | |
parent | 3d37a677963775f298425e28f9ebc473003bee39 (diff) | |
download | golang-x-tools-72e4a01eba4315301fd9ce00c8c2f492580ded8a.tar.gz |
internal/lsp: refactor code for formatting signatures
The code for formatting function signatures is fairly confusing.
Factoring out an unexported signature type simplifies things a bit.
Hopefully we'll be able to pull out more formatting logic from the other
features. Ideally, I'd like to return to the separation between
internal/lsp/source and internal/lsp so that a formatting package can be
pulled out and used in internal/lsp.
Change-Id: I7428db5004eab371e46402188e0dc6bb30f0c425
Reviewed-on: https://go-review.googlesource.com/c/tools/+/229318
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Diffstat (limited to 'internal/lsp')
-rw-r--r-- | internal/lsp/source/completion_format.go | 76 | ||||
-rw-r--r-- | internal/lsp/source/hover.go | 12 | ||||
-rw-r--r-- | internal/lsp/source/signature_help.go | 61 | ||||
-rw-r--r-- | internal/lsp/source/symbols.go | 8 | ||||
-rw-r--r-- | internal/lsp/source/types_format.go | 218 | ||||
-rw-r--r-- | internal/lsp/source/util.go | 130 | ||||
-rw-r--r-- | internal/lsp/testdata/lsp/primarymod/godef/a/random.go.golden | 1 | ||||
-rw-r--r-- | internal/lsp/testdata/lsp/primarymod/signature/signature.go.golden | 6 |
8 files changed, 276 insertions, 236 deletions
diff --git a/internal/lsp/source/completion_format.go b/internal/lsp/source/completion_format.go index b40b9f4a9..88ff10299 100644 --- a/internal/lsp/source/completion_format.go +++ b/internal/lsp/source/completion_format.go @@ -5,11 +5,9 @@ package source import ( - "bytes" "context" "fmt" "go/ast" - "go/printer" "go/types" "strings" @@ -28,7 +26,7 @@ func (c *completer) item(ctx context.Context, cand candidate) (CompletionItem, e // Handle builtin types separately. if obj.Parent() == types.Universe { - return c.formatBuiltin(ctx, cand), nil + return c.formatBuiltin(ctx, cand) } var ( @@ -46,10 +44,12 @@ func (c *completer) item(ctx context.Context, cand candidate) (CompletionItem, e // expandFuncCall mutates the completion label, detail, and snippet // to that of an invocation of sig. expandFuncCall := func(sig *types.Signature) { - params := formatParams(ctx, c.snapshot, c.pkg, sig, c.qf) - snip = c.functionCallSnippet(label, params) - results, writeParens := formatResults(sig.Results(), c.qf) - detail = "func" + formatFunction(params, results, writeParens) + s, err := newSignature(ctx, c.snapshot, c.pkg, "", sig, nil, c.qf) + if err != nil { + return + } + snip = c.functionCallSnippet(label, s.params) + detail = "func" + s.format() // Add variadic "..." if we are using a function result to fill in a variadic parameter. if sig.Results().Len() == 1 && c.inference.matchesVariadic(sig.Results().At(0).Type()) { @@ -232,7 +232,7 @@ func (c *completer) importEdits(ctx context.Context, imp *importInfo) ([]protoco }) } -func (c *completer) formatBuiltin(ctx context.Context, cand candidate) CompletionItem { +func (c *completer) formatBuiltin(ctx context.Context, cand candidate) (CompletionItem, error) { obj := cand.obj item := CompletionItem{ Label: obj.Name(), @@ -244,20 +244,12 @@ func (c *completer) formatBuiltin(ctx context.Context, cand candidate) Completio item.Kind = protocol.ConstantCompletion case *types.Builtin: item.Kind = protocol.FunctionCompletion - astObj, err := c.snapshot.View().LookupBuiltin(ctx, obj.Name()) + sig, err := newBuiltinSignature(ctx, c.snapshot.View(), obj.Name()) if err != nil { - event.Error(ctx, "no builtin package", err) - break - } - decl, ok := astObj.Decl.(*ast.FuncDecl) - if !ok { - break + return CompletionItem{}, err } - params, _ := formatFieldList(ctx, c.snapshot.View(), decl.Type.Params) - results, writeResultParens := formatFieldList(ctx, c.snapshot.View(), decl.Type.Results) - item.Label = obj.Name() - item.Detail = "func" + formatFunction(params, results, writeResultParens) - item.snippet = c.functionCallSnippet(obj.Name(), params) + item.Detail = "func" + sig.format() + item.snippet = c.functionCallSnippet(obj.Name(), sig.params) case *types.TypeName: if types.IsInterface(obj.Type()) { item.Kind = protocol.InterfaceCompletion @@ -267,48 +259,7 @@ func (c *completer) formatBuiltin(ctx context.Context, cand candidate) Completio case *types.Nil: item.Kind = protocol.VariableCompletion } - return item -} - -var replacer = strings.NewReplacer( - `ComplexType`, `complex128`, - `FloatType`, `float64`, - `IntegerType`, `int`, -) - -func formatFieldList(ctx context.Context, v View, list *ast.FieldList) ([]string, bool) { - if list == nil { - return nil, false - } - var writeResultParens bool - var result []string - for i := 0; i < len(list.List); i++ { - if i >= 1 { - writeResultParens = true - } - p := list.List[i] - cfg := printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 4} - b := &bytes.Buffer{} - if err := cfg.Fprint(b, v.Session().Cache().FileSet(), p.Type); err != nil { - event.Error(ctx, "unable to print type", nil, tag.Type.Of(p.Type)) - continue - } - typ := replacer.Replace(b.String()) - if len(p.Names) == 0 { - result = append(result, typ) - } - for _, name := range p.Names { - if name.Name != "" { - if i == 0 { - writeResultParens = true - } - result = append(result, fmt.Sprintf("%s %s", name.Name, typ)) - } else { - result = append(result, typ) - } - } - } - return result, writeResultParens + return item, nil } // qualifier returns a function that appropriately formats a types.PkgName @@ -321,7 +272,6 @@ func qualifier(f *ast.File, pkg *types.Package, info *types.Info) types.Qualifie if imp.Name != nil { obj = info.Defs[imp.Name] } else { - obj = info.Implicits[imp] } if pkgname, ok := obj.(*types.PkgName); ok { diff --git a/internal/lsp/source/hover.go b/internal/lsp/source/hover.go index 6c0024f6b..b15cccbb1 100644 --- a/internal/lsp/source/hover.go +++ b/internal/lsp/source/hover.go @@ -307,7 +307,10 @@ func formatVar(node ast.Spec, obj types.Object, decl *ast.GenDecl) *HoverInforma } func FormatHover(h *HoverInformation, options Options) (string, error) { - signature := formatSignature(h.Signature, options) + signature := h.Signature + if options.PreferredContentFormat == protocol.Markdown { + signature = fmt.Sprintf("```go\n%s\n```", signature) + } switch options.HoverKind { case SingleLine: return h.SingleLine, nil @@ -347,13 +350,6 @@ func formatLink(h *HoverInformation, options Options) string { } } -func formatSignature(signature string, options Options) string { - if options.PreferredContentFormat == protocol.Markdown { - signature = fmt.Sprintf("```go\n%s\n```", signature) - } - return signature -} - func formatDoc(doc string, options Options) string { if options.PreferredContentFormat == protocol.Markdown { return CommentToMarkdown(doc) diff --git a/internal/lsp/source/signature_help.go b/internal/lsp/source/signature_help.go index e80ea2fcf..20d2431a3 100644 --- a/internal/lsp/source/signature_help.go +++ b/internal/lsp/source/signature_help.go @@ -63,6 +63,8 @@ FindCall: return nil, 0, errors.Errorf("cannot find an enclosing function") } + qf := qualifier(file, pkg.GetTypes(), pkg.GetTypesInfo()) + // Get the object representing the function, if available. // There is no object in certain cases such as calling a function returned by // a function (e.g. "foo()()"). @@ -90,9 +92,6 @@ FindCall: return nil, 0, errors.Errorf("cannot find signature for Fun %[1]T (%[1]v)", callExpr.Fun) } - qf := qualifier(file, pkg.GetTypes(), pkg.GetTypesInfo()) - params := formatParams(ctx, snapshot, pkg, sig, qf) - results, writeResultParens := formatResults(sig.Results(), qf) activeParam := activeParameter(callExpr, sig.Params().Len(), sig.Variadic(), rng.Start) var ( @@ -122,51 +121,37 @@ FindCall: } else { name = "func" } - return signatureInformation(name, comment, params, results, writeResultParens), activeParam, nil -} - -func builtinSignature(ctx context.Context, v View, callExpr *ast.CallExpr, name string, pos token.Pos) (*protocol.SignatureInformation, int, error) { - astObj, err := v.LookupBuiltin(ctx, name) + s, err := newSignature(ctx, snapshot, pkg, name, sig, comment, qf) if err != nil { return nil, 0, err } - decl, ok := astObj.Decl.(*ast.FuncDecl) - if !ok { - return nil, 0, errors.Errorf("no function declaration for builtin: %s", name) - } - params, _ := formatFieldList(ctx, v, decl.Type.Params) - results, writeResultParens := formatFieldList(ctx, v, decl.Type.Results) - - var ( - numParams int - variadic bool - ) - if decl.Type.Params.List != nil { - numParams = len(decl.Type.Params.List) - lastParam := decl.Type.Params.List[numParams-1] - if _, ok := lastParam.Type.(*ast.Ellipsis); ok { - variadic = true - } + paramInfo := make([]protocol.ParameterInformation, 0, len(s.params)) + for _, p := range s.params { + paramInfo = append(paramInfo, protocol.ParameterInformation{Label: p}) } - activeParam := activeParameter(callExpr, numParams, variadic, pos) - return signatureInformation(name, nil, params, results, writeResultParens), activeParam, nil + return &protocol.SignatureInformation{ + Label: name + s.format(), + Documentation: doc.Synopsis(s.doc), + Parameters: paramInfo, + }, activeParam, nil } -func signatureInformation(name string, comment *ast.CommentGroup, params, results []string, writeResultParens bool) *protocol.SignatureInformation { - paramInfo := make([]protocol.ParameterInformation, 0, len(params)) - for _, p := range params { - paramInfo = append(paramInfo, protocol.ParameterInformation{Label: p}) +func builtinSignature(ctx context.Context, view View, callExpr *ast.CallExpr, name string, pos token.Pos) (*protocol.SignatureInformation, int, error) { + sig, err := newBuiltinSignature(ctx, view, name) + if err != nil { + return nil, 0, err } - label := name + formatFunction(params, results, writeResultParens) - var c string - if comment != nil { - c = doc.Synopsis(comment.Text()) + paramInfo := make([]protocol.ParameterInformation, 0, len(sig.params)) + for _, p := range sig.params { + paramInfo = append(paramInfo, protocol.ParameterInformation{Label: p}) } + activeParam := activeParameter(callExpr, len(sig.params), sig.variadic, pos) return &protocol.SignatureInformation{ - Label: label, - Documentation: c, + Label: sig.name + sig.format(), + Documentation: doc.Synopsis(sig.doc), Parameters: paramInfo, - } + }, activeParam, nil + } func activeParameter(callExpr *ast.CallExpr, numParams int, variadic bool, pos token.Pos) (activeParam int) { diff --git a/internal/lsp/source/symbols.go b/internal/lsp/source/symbols.go index 1a1624dec..8b09f81dc 100644 --- a/internal/lsp/source/symbols.go +++ b/internal/lsp/source/symbols.go @@ -112,11 +112,11 @@ func funcSymbol(view View, pkg Package, decl *ast.FuncDecl, obj types.Object, q return s, nil } -func typeSymbol(view View, pkg Package, info *types.Info, spec *ast.TypeSpec, obj types.Object, q types.Qualifier) (protocol.DocumentSymbol, error) { +func typeSymbol(view View, pkg Package, info *types.Info, spec *ast.TypeSpec, obj types.Object, qf types.Qualifier) (protocol.DocumentSymbol, error) { s := protocol.DocumentSymbol{ Name: obj.Name(), } - s.Detail, _ = formatType(obj.Type(), q) + s.Detail, _ = formatType(obj.Type(), qf) s.Kind = typeToKind(obj.Type()) var err error @@ -137,7 +137,7 @@ func typeSymbol(view View, pkg Package, info *types.Info, spec *ast.TypeSpec, ob Name: f.Name(), Kind: protocol.Field, } - child.Detail, _ = formatType(f.Type(), q) + child.Detail, _ = formatType(f.Type(), qf) spanNode, selectionNode := nodesForStructField(i, st) if span, err := nodeToProtocolRange(view, pkg, spanNode); err == nil { @@ -189,7 +189,7 @@ func typeSymbol(view View, pkg Package, info *types.Info, spec *ast.TypeSpec, ob } child := protocol.DocumentSymbol{ - Name: types.TypeString(embedded, q), + Name: types.TypeString(embedded, qf), } child.Kind = typeToKind(embedded) var spanNode, selectionNode ast.Node diff --git a/internal/lsp/source/types_format.go b/internal/lsp/source/types_format.go new file mode 100644 index 000000000..a536ffd9f --- /dev/null +++ b/internal/lsp/source/types_format.go @@ -0,0 +1,218 @@ +// Copyright 2020 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 source + +import ( + "bytes" + "context" + "fmt" + "go/ast" + "go/doc" + "go/printer" + "go/types" + "strings" + + "golang.org/x/tools/internal/lsp/debug/tag" + "golang.org/x/tools/internal/lsp/protocol" + "golang.org/x/tools/internal/telemetry/event" +) + +// formatType returns the detail and kind for a types.Type. +func formatType(typ types.Type, qf types.Qualifier) (detail string, kind protocol.CompletionItemKind) { + if types.IsInterface(typ) { + detail = "interface{...}" + kind = protocol.InterfaceCompletion + } else if _, ok := typ.(*types.Struct); ok { + detail = "struct{...}" + kind = protocol.StructCompletion + } else if typ != typ.Underlying() { + detail, kind = formatType(typ.Underlying(), qf) + } else { + detail = types.TypeString(typ, qf) + kind = protocol.ClassCompletion + } + return detail, kind +} + +type signature struct { + name, doc string + params, results []string + variadic bool + needResultParens bool +} + +func (s *signature) format() string { + var b strings.Builder + b.WriteByte('(') + for i, p := range s.params { + if i > 0 { + b.WriteString(", ") + } + b.WriteString(p) + } + b.WriteByte(')') + + // Add space between parameters and results. + if len(s.results) > 0 { + b.WriteByte(' ') + } + if s.needResultParens { + b.WriteByte('(') + } + for i, r := range s.results { + if i > 0 { + b.WriteString(", ") + } + b.WriteString(r) + } + if s.needResultParens { + b.WriteByte(')') + } + return b.String() +} + +func newBuiltinSignature(ctx context.Context, view View, name string) (*signature, error) { + astObj, err := view.LookupBuiltin(ctx, name) + if err != nil { + return nil, err + } + decl, ok := astObj.Decl.(*ast.FuncDecl) + if !ok { + return nil, fmt.Errorf("no function declaration for builtin: %s", name) + } + if decl.Type == nil { + return nil, fmt.Errorf("no type for builtin decl %s", decl.Name) + } + var variadic bool + if decl.Type.Params.List != nil { + numParams := len(decl.Type.Params.List) + lastParam := decl.Type.Params.List[numParams-1] + if _, ok := lastParam.Type.(*ast.Ellipsis); ok { + variadic = true + } + } + params, _ := formatFieldList(ctx, view, decl.Type.Params, variadic) + results, needResultParens := formatFieldList(ctx, view, decl.Type.Results, false) + return &signature{ + doc: decl.Doc.Text(), + name: name, + needResultParens: needResultParens, + params: params, + results: results, + variadic: variadic, + }, nil +} + +func newSignature(ctx context.Context, s Snapshot, pkg Package, name string, sig *types.Signature, comment *ast.CommentGroup, qf types.Qualifier) (*signature, error) { + params := make([]string, 0, sig.Params().Len()) + for i := 0; i < sig.Params().Len(); i++ { + el := sig.Params().At(i) + typ, err := formatFieldType(ctx, s, pkg, el) + if err != nil { + typ = types.TypeString(el.Type(), qf) + } + // Handle a variadic parameter (can only be the final parameter). + if sig.Variadic() && i == sig.Params().Len()-1 { + typ = strings.Replace(typ, "[]", "...", 1) + } + p := typ + if el.Name() != "" { + p = el.Name() + " " + typ + } + params = append(params, p) + } + var needResultParens bool + results := make([]string, 0, sig.Results().Len()) + for i := 0; i < sig.Results().Len(); i++ { + if i >= 1 { + needResultParens = true + } + el := sig.Results().At(i) + typ := types.TypeString(el.Type(), qf) + + if el.Name() == "" { + results = append(results, typ) + } else { + if i == 0 { + needResultParens = true + } + results = append(results, el.Name()+" "+typ) + } + } + var c string + if comment != nil { + c = doc.Synopsis(comment.Text()) + } + return &signature{ + doc: c, + params: params, + results: results, + variadic: sig.Variadic(), + needResultParens: needResultParens, + }, nil +} + +func formatFieldType(ctx context.Context, s Snapshot, srcpkg Package, obj *types.Var) (string, error) { + file, pkg, err := findPosInPackage(s.View(), srcpkg, obj.Pos()) + if err != nil { + return "", err + } + ident, err := findIdentifier(ctx, s, pkg, file, obj.Pos()) + if err != nil { + return "", err + } + if i := ident.ident; i == nil || i.Obj == nil || i.Obj.Decl == nil { + return "", fmt.Errorf("no object for ident %v", i.Name) + } + f, ok := ident.ident.Obj.Decl.(*ast.Field) + if !ok { + return "", fmt.Errorf("ident %s is not a field type", ident.Name) + } + return formatNode(s.View().Session().Cache().FileSet(), f.Type), nil +} + +var replacer = strings.NewReplacer( + `ComplexType`, `complex128`, + `FloatType`, `float64`, + `IntegerType`, `int`, +) + +func formatFieldList(ctx context.Context, view View, list *ast.FieldList, variadic bool) ([]string, bool) { + if list == nil { + return nil, false + } + var writeResultParens bool + var result []string + for i := 0; i < len(list.List); i++ { + if i >= 1 { + writeResultParens = true + } + p := list.List[i] + cfg := printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 4} + b := &bytes.Buffer{} + if err := cfg.Fprint(b, view.Session().Cache().FileSet(), p.Type); err != nil { + event.Error(ctx, "unable to print type", nil, tag.Type.Of(p.Type)) + continue + } + typ := replacer.Replace(b.String()) + if len(p.Names) == 0 { + result = append(result, typ) + } + for _, name := range p.Names { + if name.Name != "" { + if i == 0 { + writeResultParens = true + } + result = append(result, fmt.Sprintf("%s %s", name.Name, typ)) + } else { + result = append(result, typ) + } + } + } + if variadic { + result[len(result)-1] = strings.Replace(result[len(result)-1], "[]", "...", 1) + } + return result, writeResultParens +} diff --git a/internal/lsp/source/util.go b/internal/lsp/source/util.go index 5d275bddc..69cfba9f1 100644 --- a/internal/lsp/source/util.go +++ b/internal/lsp/source/util.go @@ -376,6 +376,14 @@ func resolveInvalid(fset *token.FileSet, obj types.Object, node ast.Node, info * return types.NewVar(obj.Pos(), obj.Pkg(), obj.Name(), typ) } +func formatNode(fset *token.FileSet, n ast.Node) string { + var buf strings.Builder + if err := printer.Fprint(&buf, fset, n); err != nil { + return "" + } + return buf.String() +} + func isPointer(T types.Type) bool { _, ok := T.(*types.Pointer) return ok @@ -499,128 +507,6 @@ func fieldsAccessible(s *types.Struct, p *types.Package) bool { return false } -func formatParams(ctx context.Context, s Snapshot, pkg Package, sig *types.Signature, qf types.Qualifier) []string { - params := make([]string, 0, sig.Params().Len()) - for i := 0; i < sig.Params().Len(); i++ { - el := sig.Params().At(i) - typ, err := formatFieldType(ctx, s, pkg, el) - if err != nil { - typ = types.TypeString(el.Type(), qf) - } - - // Handle a variadic parameter (can only be the final parameter). - if sig.Variadic() && i == sig.Params().Len()-1 { - typ = strings.Replace(typ, "[]", "...", 1) - } - - if el.Name() == "" { - params = append(params, typ) - } else { - params = append(params, el.Name()+" "+typ) - } - } - return params -} - -func formatFieldType(ctx context.Context, s Snapshot, srcpkg Package, obj types.Object) (string, error) { - file, pkg, err := findPosInPackage(s.View(), srcpkg, obj.Pos()) - if err != nil { - return "", err - } - ident, err := findIdentifier(ctx, s, pkg, file, obj.Pos()) - if err != nil { - return "", err - } - if i := ident.ident; i == nil || i.Obj == nil || i.Obj.Decl == nil { - return "", errors.Errorf("no object for ident %v", i.Name) - } - f, ok := ident.ident.Obj.Decl.(*ast.Field) - if !ok { - return "", errors.Errorf("ident %s is not a field type", ident.Name) - } - return formatNode(s.View().Session().Cache().FileSet(), f.Type), nil -} - -func formatNode(fset *token.FileSet, n ast.Node) string { - var buf strings.Builder - if err := printer.Fprint(&buf, fset, n); err != nil { - return "" - } - return buf.String() -} - -func formatResults(tup *types.Tuple, qf types.Qualifier) ([]string, bool) { - var writeResultParens bool - results := make([]string, 0, tup.Len()) - for i := 0; i < tup.Len(); i++ { - if i >= 1 { - writeResultParens = true - } - el := tup.At(i) - typ := types.TypeString(el.Type(), qf) - - if el.Name() == "" { - results = append(results, typ) - } else { - if i == 0 { - writeResultParens = true - } - results = append(results, el.Name()+" "+typ) - } - } - return results, writeResultParens -} - -// formatType returns the detail and kind for an object of type *types.TypeName. -func formatType(typ types.Type, qf types.Qualifier) (detail string, kind protocol.CompletionItemKind) { - if types.IsInterface(typ) { - detail = "interface{...}" - kind = protocol.InterfaceCompletion - } else if _, ok := typ.(*types.Struct); ok { - detail = "struct{...}" - kind = protocol.StructCompletion - } else if typ != typ.Underlying() { - detail, kind = formatType(typ.Underlying(), qf) - } else { - detail = types.TypeString(typ, qf) - kind = protocol.ClassCompletion - } - return detail, kind -} - -func formatFunction(params []string, results []string, writeResultParens bool) string { - var detail strings.Builder - - detail.WriteByte('(') - for i, p := range params { - if i > 0 { - detail.WriteString(", ") - } - detail.WriteString(p) - } - detail.WriteByte(')') - - // Add space between parameters and results. - if len(results) > 0 { - detail.WriteByte(' ') - } - - if writeResultParens { - detail.WriteByte('(') - } - for i, p := range results { - if i > 0 { - detail.WriteString(", ") - } - detail.WriteString(p) - } - if writeResultParens { - detail.WriteByte(')') - } - - return detail.String() -} - func SortDiagnostics(d []*Diagnostic) { sort.Slice(d, func(i int, j int) bool { return CompareDiagnostic(d[i], d[j]) < 0 diff --git a/internal/lsp/testdata/lsp/primarymod/godef/a/random.go.golden b/internal/lsp/testdata/lsp/primarymod/godef/a/random.go.golden index 033e581cb..adba70063 100644 --- a/internal/lsp/testdata/lsp/primarymod/godef/a/random.go.golden +++ b/internal/lsp/testdata/lsp/primarymod/godef/a/random.go.golden @@ -88,7 +88,6 @@ var y int godef/a/random.go:17:18-23: defined here as ```go field field string ``` - -- TypField-definition-json -- { "span": { diff --git a/internal/lsp/testdata/lsp/primarymod/signature/signature.go.golden b/internal/lsp/testdata/lsp/primarymod/signature/signature.go.golden index 22d2a515e..387abf6dc 100644 --- a/internal/lsp/testdata/lsp/primarymod/signature/signature.go.golden +++ b/internal/lsp/testdata/lsp/primarymod/signature/signature.go.golden @@ -27,12 +27,18 @@ func(string, int) bool -- make(t Type, size ...int) Type-signature -- make(t Type, size ...int) Type +The make built-in function allocates and initializes an object of type slice, map, or chan (only). + -- myFunc(foo int) string-signature -- myFunc(foo int) string -- panic(v interface{})-signature -- panic(v interface{}) +The panic built-in function stops normal execution of the current goroutine. + -- println(args ...Type)-signature -- println(args ...Type) +The println built-in function formats its arguments in an implementation-specific way and writes the result to standard error. + |