mirror of
https://github.com/golang/go
synced 2024-11-18 16:54:43 -07:00
internal/lsp: support builtin types without hardcoding
This change uses an *ast.Package built from the file go/src/builtin/builtin.go. Completion (and ultimately other features) will be resolved using this AST instead of being hardcoded. Change-Id: I3e34030b3236994faa484cf17cf75da511165133 Reviewed-on: https://go-review.googlesource.com/c/tools/+/174381 Run-TryBot: Rebecca Stambler <rstambler@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Cottrell <iancottrell@google.com>
This commit is contained in:
parent
2d28432af7
commit
2346320968
32
internal/lsp/cache/view.go
vendored
32
internal/lsp/cache/view.go
vendored
@ -6,6 +6,8 @@ package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"os"
|
||||
@ -63,6 +65,9 @@ type View struct {
|
||||
|
||||
// pcache caches type information for the packages of the opened files in a view.
|
||||
pcache *packageCache
|
||||
|
||||
// builtinPkg is the AST package used to resolve builtin types.
|
||||
builtinPkg *ast.Package
|
||||
}
|
||||
|
||||
type metadataCache struct {
|
||||
@ -93,6 +98,7 @@ func NewView(ctx context.Context, log xlog.Logger, name string, folder span.URI,
|
||||
v := &View{
|
||||
baseCtx: ctx,
|
||||
backgroundCtx: backgroundCtx,
|
||||
builtinPkg: builtinPkg(*config),
|
||||
cancel: cancel,
|
||||
log: log,
|
||||
Config: *config,
|
||||
@ -118,6 +124,32 @@ func (v *View) BackgroundContext() context.Context {
|
||||
return v.backgroundCtx
|
||||
}
|
||||
|
||||
func (v *View) BuiltinPackage() *ast.Package {
|
||||
return v.builtinPkg
|
||||
}
|
||||
|
||||
func builtinPkg(cfg packages.Config) *ast.Package {
|
||||
var bpkg *ast.Package
|
||||
cfg.Mode = packages.LoadFiles
|
||||
pkgs, _ := packages.Load(&cfg, "builtin")
|
||||
if len(pkgs) != 1 {
|
||||
bpkg, _ = ast.NewPackage(cfg.Fset, nil, nil, nil)
|
||||
return bpkg
|
||||
}
|
||||
pkg := pkgs[0]
|
||||
files := make(map[string]*ast.File)
|
||||
for _, filename := range pkg.GoFiles {
|
||||
file, err := parser.ParseFile(cfg.Fset, filename, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
bpkg, _ = ast.NewPackage(cfg.Fset, nil, nil, nil)
|
||||
return bpkg
|
||||
}
|
||||
files[filename] = file
|
||||
}
|
||||
bpkg, _ = ast.NewPackage(cfg.Fset, files, nil, nil)
|
||||
return bpkg
|
||||
}
|
||||
|
||||
func (v *View) FileSet() *token.FileSet {
|
||||
return v.Config.Fset
|
||||
}
|
||||
|
@ -14,24 +14,17 @@ import (
|
||||
)
|
||||
|
||||
func (s *Server) cacheAndDiagnose(ctx context.Context, uri span.URI, content string) error {
|
||||
s.log.Debugf(ctx, "cacheAndDiagnose: %s", uri)
|
||||
|
||||
view := s.findView(ctx, uri)
|
||||
if err := view.SetContent(ctx, uri, []byte(content)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.log.Debugf(ctx, "cacheAndDiagnose: set content for %s", uri)
|
||||
|
||||
go func() {
|
||||
ctx := view.BackgroundContext()
|
||||
if ctx.Err() != nil {
|
||||
s.log.Errorf(ctx, "canceling diagnostics for %s: %v", uri, ctx.Err())
|
||||
return
|
||||
}
|
||||
|
||||
s.log.Debugf(ctx, "cacheAndDiagnose: going to get diagnostics for %s", uri)
|
||||
|
||||
reports, err := source.Diagnostics(ctx, view, uri)
|
||||
if err != nil {
|
||||
s.log.Errorf(ctx, "failed to compute diagnostics for %s: %v", uri, err)
|
||||
@ -41,8 +34,6 @@ func (s *Server) cacheAndDiagnose(ctx context.Context, uri span.URI, content str
|
||||
s.undeliveredMu.Lock()
|
||||
defer s.undeliveredMu.Unlock()
|
||||
|
||||
s.log.Debugf(ctx, "cacheAndDiagnose: publishing diagnostics")
|
||||
|
||||
for uri, diagnostics := range reports {
|
||||
if err := s.publishDiagnostics(ctx, view, uri, diagnostics); err != nil {
|
||||
if s.undelivered == nil {
|
||||
@ -54,9 +45,6 @@ func (s *Server) cacheAndDiagnose(ctx context.Context, uri span.URI, content str
|
||||
// In case we had old, undelivered diagnostics.
|
||||
delete(s.undelivered, uri)
|
||||
}
|
||||
|
||||
s.log.Debugf(ctx, "cacheAndDiagnose: publishing undelivered diagnostics")
|
||||
|
||||
// Anytime we compute diagnostics, make sure to also send along any
|
||||
// undelivered ones (only for remaining URIs).
|
||||
for uri, diagnostics := range s.undelivered {
|
||||
@ -66,8 +54,6 @@ func (s *Server) cacheAndDiagnose(ctx context.Context, uri span.URI, content str
|
||||
delete(s.undelivered, uri)
|
||||
}
|
||||
}()
|
||||
|
||||
s.log.Debugf(ctx, "cacheAndDiagnose: returned from diagnostics for %s", uri)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,12 @@ type completer struct {
|
||||
types *types.Package
|
||||
info *types.Info
|
||||
qf types.Qualifier
|
||||
fset *token.FileSet
|
||||
|
||||
// view is the View associated with this completion request.
|
||||
view View
|
||||
|
||||
// ctx is the context associated with this completion request.
|
||||
ctx context.Context
|
||||
|
||||
// pos is the position at which the request was triggered.
|
||||
pos token.Pos
|
||||
@ -186,7 +191,8 @@ func Completion(ctx context.Context, f File, pos token.Pos) ([]CompletionItem, s
|
||||
types: pkg.GetTypes(),
|
||||
info: pkg.GetTypesInfo(),
|
||||
qf: qualifier(file, pkg.GetTypes(), pkg.GetTypesInfo()),
|
||||
fset: f.GetFileSet(ctx),
|
||||
view: f.View(),
|
||||
ctx: ctx,
|
||||
path: path,
|
||||
pos: pos,
|
||||
seen: make(map[types.Object]bool),
|
||||
|
@ -5,8 +5,10 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/printer"
|
||||
"go/types"
|
||||
"strings"
|
||||
|
||||
@ -15,6 +17,11 @@ import (
|
||||
|
||||
// formatCompletion creates a completion item for a given types.Object.
|
||||
func (c *completer) item(obj types.Object, score float64) CompletionItem {
|
||||
// Handle builtin types separately.
|
||||
if obj.Parent() == types.Universe {
|
||||
return c.formatBuiltin(obj, score)
|
||||
}
|
||||
|
||||
var (
|
||||
label = obj.Name()
|
||||
detail = types.TypeString(obj.Type(), c.qf)
|
||||
@ -27,9 +34,6 @@ func (c *completer) item(obj types.Object, score float64) CompletionItem {
|
||||
switch o := obj.(type) {
|
||||
case *types.TypeName:
|
||||
detail, kind = formatType(o.Type(), c.qf)
|
||||
if obj.Parent() == types.Universe {
|
||||
detail = ""
|
||||
}
|
||||
case *types.Const:
|
||||
if obj.Parent() == types.Universe {
|
||||
detail = ""
|
||||
@ -57,27 +61,17 @@ func (c *completer) item(obj types.Object, score float64) CompletionItem {
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
params := formatEachParam(sig, c.qf)
|
||||
label += formatParamParts(params)
|
||||
detail = strings.Trim(types.TypeString(sig.Results(), c.qf), "()")
|
||||
params := formatParams(sig.Params(), sig.Variadic(), c.qf)
|
||||
results, writeParens := formatResults(sig.Results(), c.qf)
|
||||
label, detail = formatFunction(obj.Name(), params, results, writeParens)
|
||||
plainSnippet, placeholderSnippet = c.functionCallSnippets(obj.Name(), params)
|
||||
kind = FunctionCompletionItem
|
||||
if sig.Recv() != nil {
|
||||
kind = MethodCompletionItem
|
||||
}
|
||||
plainSnippet, placeholderSnippet = c.functionCallSnippets(obj.Name(), params)
|
||||
case *types.Builtin:
|
||||
item, ok := builtinDetails[obj.Name()]
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
label, detail = item.label, item.detail
|
||||
kind = FunctionCompletionItem
|
||||
case *types.PkgName:
|
||||
kind = PackageCompletionItem
|
||||
detail = fmt.Sprintf("\"%s\"", o.Imported().Path())
|
||||
case *types.Nil:
|
||||
kind = VariableCompletionItem
|
||||
detail = ""
|
||||
}
|
||||
detail = strings.TrimPrefix(detail, "untyped ")
|
||||
|
||||
@ -106,71 +100,77 @@ func (c *completer) isParameter(v *types.Var) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// formatType returns the detail and kind for an object of type *types.TypeName.
|
||||
func formatType(typ types.Type, qf types.Qualifier) (detail string, kind CompletionItemKind) {
|
||||
if types.IsInterface(typ) {
|
||||
detail = "interface{...}"
|
||||
kind = InterfaceCompletionItem
|
||||
} else if _, ok := typ.(*types.Struct); ok {
|
||||
detail = "struct{...}"
|
||||
kind = StructCompletionItem
|
||||
} else if typ != typ.Underlying() {
|
||||
detail, kind = formatType(typ.Underlying(), qf)
|
||||
} else {
|
||||
detail = types.TypeString(typ, qf)
|
||||
kind = TypeCompletionItem
|
||||
func (c *completer) formatBuiltin(obj types.Object, score float64) CompletionItem {
|
||||
item := CompletionItem{
|
||||
Label: obj.Name(),
|
||||
InsertText: obj.Name(),
|
||||
Score: score,
|
||||
}
|
||||
return detail, kind
|
||||
}
|
||||
|
||||
// formatParams correctly formats the parameters of a function.
|
||||
func formatParams(sig *types.Signature, qualifier types.Qualifier) string {
|
||||
return formatParamParts(formatEachParam(sig, qualifier))
|
||||
}
|
||||
|
||||
func formatParamParts(params []string) string {
|
||||
totalLen := 2 // parens
|
||||
|
||||
// length of each param itself
|
||||
for _, p := range params {
|
||||
totalLen += len(p)
|
||||
}
|
||||
// length of ", " separator
|
||||
if len(params) > 1 {
|
||||
totalLen += 2 * (len(params) - 1)
|
||||
}
|
||||
|
||||
var b strings.Builder
|
||||
b.Grow(totalLen)
|
||||
|
||||
b.WriteByte('(')
|
||||
for i, p := range params {
|
||||
if i > 0 {
|
||||
b.WriteString(", ")
|
||||
switch obj.(type) {
|
||||
case *types.Const:
|
||||
item.Kind = ConstantCompletionItem
|
||||
case *types.Builtin:
|
||||
fn := c.view.BuiltinPackage().Scope.Lookup(obj.Name())
|
||||
decl, ok := fn.Decl.(*ast.FuncDecl)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
b.WriteString(p)
|
||||
}
|
||||
b.WriteByte(')')
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func formatEachParam(sig *types.Signature, qualifier types.Qualifier) []string {
|
||||
params := make([]string, 0, sig.Params().Len())
|
||||
for i := 0; i < sig.Params().Len(); i++ {
|
||||
el := sig.Params().At(i)
|
||||
typ := types.TypeString(el.Type(), qualifier)
|
||||
// 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)
|
||||
params, _ := c.formatFieldList(decl.Type.Params)
|
||||
results, writeResultParens := c.formatFieldList(decl.Type.Results)
|
||||
item.Label, item.Detail = formatFunction(obj.Name(), params, results, writeResultParens)
|
||||
item.Snippet, item.PlaceholderSnippet = c.functionCallSnippets(obj.Name(), params)
|
||||
item.Kind = FunctionCompletionItem
|
||||
case *types.TypeName:
|
||||
if types.IsInterface(obj.Type()) {
|
||||
item.Kind = InterfaceCompletionItem
|
||||
} else {
|
||||
params = append(params, el.Name()+" "+typ)
|
||||
item.Kind = TypeCompletionItem
|
||||
}
|
||||
case *types.Nil:
|
||||
item.Kind = VariableCompletionItem
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
var replacer = strings.NewReplacer(
|
||||
`ComplexType`, `complex128`,
|
||||
`FloatType`, `float64`,
|
||||
`IntegerType`, `int`,
|
||||
)
|
||||
|
||||
func (c *completer) formatFieldList(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, c.view.FileSet(), p.Type); err != nil {
|
||||
c.view.Logger().Errorf(c.ctx, "unable to print type %v", p.Type)
|
||||
continue
|
||||
}
|
||||
typ := replacer.Replace(b.String())
|
||||
if len(p.Names) == 0 {
|
||||
result = append(result, fmt.Sprintf("%s", 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, fmt.Sprintf("%s", typ))
|
||||
}
|
||||
}
|
||||
}
|
||||
return params
|
||||
return result, writeResultParens
|
||||
}
|
||||
|
||||
// qualifier returns a function that appropriately formats a types.PkgName
|
||||
@ -200,65 +200,3 @@ func qualifier(f *ast.File, pkg *types.Package, info *types.Info) types.Qualifie
|
||||
return p.Name()
|
||||
}
|
||||
}
|
||||
|
||||
type itemDetails struct {
|
||||
label, detail string
|
||||
}
|
||||
|
||||
var builtinDetails = map[string]itemDetails{
|
||||
"append": { // append(slice []T, elems ...T)
|
||||
label: "append(slice []T, elems ...T)",
|
||||
detail: "[]T",
|
||||
},
|
||||
"cap": { // cap(v []T) int
|
||||
label: "cap(v []T)",
|
||||
detail: "int",
|
||||
},
|
||||
"close": { // close(c chan<- T)
|
||||
label: "close(c chan<- T)",
|
||||
},
|
||||
"complex": { // complex(r, i float64) complex128
|
||||
label: "complex(real float64, imag float64)",
|
||||
detail: "complex128",
|
||||
},
|
||||
"copy": { // copy(dst, src []T) int
|
||||
label: "copy(dst []T, src []T)",
|
||||
detail: "int",
|
||||
},
|
||||
"delete": { // delete(m map[T]T1, key T)
|
||||
label: "delete(m map[K]V, key K)",
|
||||
},
|
||||
"imag": { // imag(c complex128) float64
|
||||
label: "imag(complex128)",
|
||||
detail: "float64",
|
||||
},
|
||||
"len": { // len(v T) int
|
||||
label: "len(T)",
|
||||
detail: "int",
|
||||
},
|
||||
"make": { // make(t T, size ...int) T
|
||||
label: "make(t T, size ...int)",
|
||||
detail: "T",
|
||||
},
|
||||
"new": { // new(T) *T
|
||||
label: "new(T)",
|
||||
detail: "*T",
|
||||
},
|
||||
"panic": { // panic(v interface{})
|
||||
label: "panic(interface{})",
|
||||
},
|
||||
"print": { // print(args ...T)
|
||||
label: "print(args ...T)",
|
||||
},
|
||||
"println": { // println(args ...T)
|
||||
label: "println(args ...T)",
|
||||
},
|
||||
"real": { // real(c complex128) float64
|
||||
label: "real(complex128)",
|
||||
detail: "float64",
|
||||
},
|
||||
"recover": { // recover() interface{}
|
||||
label: "recover()",
|
||||
detail: "interface{}",
|
||||
},
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ func (c *completer) structFieldSnippets(label, detail string) (*snippet.Builder,
|
||||
|
||||
// If the cursor position is on a different line from the literal's opening brace,
|
||||
// we are in a multiline literal.
|
||||
if c.fset.Position(c.pos).Line != c.fset.Position(lit.Lbrace).Line {
|
||||
if c.view.FileSet().Position(c.pos).Line != c.view.FileSet().Position(lit.Lbrace).Line {
|
||||
plain.WriteText(",")
|
||||
placeholder.WriteText(",")
|
||||
}
|
||||
|
@ -105,23 +105,18 @@ func SignatureHelp(ctx context.Context, f File, pos token.Pos) (*SignatureInform
|
||||
obj = pkg.GetTypesInfo().ObjectOf(t.Sel)
|
||||
}
|
||||
|
||||
var label string
|
||||
var name string
|
||||
if obj != nil {
|
||||
label = obj.Name()
|
||||
name = obj.Name()
|
||||
} else {
|
||||
label = "func"
|
||||
name = "func"
|
||||
}
|
||||
|
||||
label += formatParams(sig, qf)
|
||||
results, writeResultParens := formatResults(sig.Results(), qf)
|
||||
label, detail := formatFunction(name, formatParams(sig.Params(), sig.Variadic(), qf), results, writeResultParens)
|
||||
if sig.Results().Len() > 0 {
|
||||
results := types.TypeString(sig.Results(), qf)
|
||||
if sig.Results().Len() == 1 && sig.Results().At(0).Name() == "" {
|
||||
// Trim off leading/trailing parens to avoid results like "foo(a int) (int)".
|
||||
results = strings.Trim(results, "()")
|
||||
}
|
||||
label += " " + results
|
||||
label += " " + detail
|
||||
}
|
||||
|
||||
return &SignatureInformation{
|
||||
Label: label,
|
||||
Parameters: paramInfo,
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// indexExprAtPos returns the index of the expression containing pos.
|
||||
@ -109,3 +110,90 @@ func deref(typ types.Type) types.Type {
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
func formatParams(tup *types.Tuple, variadic bool, qf types.Qualifier) []string {
|
||||
params := make([]string, 0, tup.Len())
|
||||
for i := 0; i < tup.Len(); i++ {
|
||||
el := tup.At(i)
|
||||
typ := types.TypeString(el.Type(), qf)
|
||||
|
||||
// Handle a variadic parameter (can only be the final parameter).
|
||||
if variadic && i == tup.Len()-1 {
|
||||
typ = strings.Replace(typ, "[]", "...", 1)
|
||||
}
|
||||
|
||||
if el.Name() == "" {
|
||||
params = append(params, typ)
|
||||
} else {
|
||||
params = append(params, el.Name()+" "+typ)
|
||||
}
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
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 CompletionItemKind) {
|
||||
if types.IsInterface(typ) {
|
||||
detail = "interface{...}"
|
||||
kind = InterfaceCompletionItem
|
||||
} else if _, ok := typ.(*types.Struct); ok {
|
||||
detail = "struct{...}"
|
||||
kind = StructCompletionItem
|
||||
} else if typ != typ.Underlying() {
|
||||
detail, kind = formatType(typ.Underlying(), qf)
|
||||
} else {
|
||||
detail = types.TypeString(typ, qf)
|
||||
kind = TypeCompletionItem
|
||||
}
|
||||
return detail, kind
|
||||
}
|
||||
|
||||
func formatFunction(name string, params []string, results []string, writeResultParens bool) (string, string) {
|
||||
var label, detail strings.Builder
|
||||
label.WriteString(name)
|
||||
label.WriteByte('(')
|
||||
for i, p := range params {
|
||||
if i > 0 {
|
||||
label.WriteString(", ")
|
||||
}
|
||||
label.WriteString(p)
|
||||
}
|
||||
label.WriteByte(')')
|
||||
|
||||
if writeResultParens {
|
||||
detail.WriteByte('(')
|
||||
}
|
||||
for i, p := range results {
|
||||
if i > 0 {
|
||||
detail.WriteString(", ")
|
||||
}
|
||||
detail.WriteString(p)
|
||||
}
|
||||
if writeResultParens {
|
||||
detail.WriteByte(')')
|
||||
}
|
||||
|
||||
return label.String(), detail.String()
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
type View interface {
|
||||
Logger() xlog.Logger
|
||||
FileSet() *token.FileSet
|
||||
BuiltinPackage() *ast.Package
|
||||
GetFile(ctx context.Context, uri span.URI) (File, error)
|
||||
SetContent(ctx context.Context, uri span.URI, content []byte) error
|
||||
}
|
||||
|
28
internal/lsp/testdata/builtins/builtins.go
vendored
28
internal/lsp/testdata/builtins/builtins.go
vendored
@ -5,35 +5,35 @@ func _() {
|
||||
}
|
||||
|
||||
/* Create markers for builtin types. Only for use by this test.
|
||||
/* append(slice []T, elems ...T) []T */ //@item(append, "append(slice []T, elems ...T)", "[]T", "func")
|
||||
/* append(slice []Type, elems ...Type) []Type */ //@item(append, "append(slice []Type, elems ...Type)", "[]Type", "func")
|
||||
/* bool */ //@item(bool, "bool", "", "type")
|
||||
/* byte */ //@item(byte, "byte", "", "type")
|
||||
/* cap(v []T) int */ //@item(cap, "cap(v []T)", "int", "func")
|
||||
/* close(c chan<- T) */ //@item(close, "close(c chan<- T)", "", "func")
|
||||
/* complex(real float64, imag float64) */ //@item(complex, "complex(real float64, imag float64)", "complex128", "func")
|
||||
/* cap(v Type) int */ //@item(cap, "cap(v Type)", "int", "func")
|
||||
/* close(c chan<- Type) */ //@item(close, "close(c chan<- Type)", "", "func")
|
||||
/* complex(r float64, i float64) */ //@item(complex, "complex(r float64, i float64)", "complex128", "func")
|
||||
/* complex128 */ //@item(complex128, "complex128", "", "type")
|
||||
/* complex64 */ //@item(complex64, "complex64", "", "type")
|
||||
/* copy(dst []T, src []T) int */ //@item(copy, "copy(dst []T, src []T)", "int", "func")
|
||||
/* delete(m map[K]V, key K) */ //@item(delete, "delete(m map[K]V, key K)", "", "func")
|
||||
/* copy(dst []Type, src []Type) int */ //@item(copy, "copy(dst []Type, src []Type)", "int", "func")
|
||||
/* delete(m map[Type]Type1, key Type) */ //@item(delete, "delete(m map[Type]Type1, key Type)", "", "func")
|
||||
/* error */ //@item(error, "error", "", "interface")
|
||||
/* false */ //@item(_false, "false", "", "const")
|
||||
/* float32 */ //@item(float32, "float32", "", "type")
|
||||
/* float64 */ //@item(float64, "float64", "", "type")
|
||||
/* imag(complex128) float64 */ //@item(imag, "imag(complex128)", "float64", "func")
|
||||
/* imag(c complex128) float64 */ //@item(imag, "imag(c complex128)", "float64", "func")
|
||||
/* int */ //@item(int, "int", "", "type")
|
||||
/* int16 */ //@item(int16, "int16", "", "type")
|
||||
/* int32 */ //@item(int32, "int32", "", "type")
|
||||
/* int64 */ //@item(int64, "int64", "", "type")
|
||||
/* int8 */ //@item(int8, "int8", "", "type")
|
||||
/* iota */ //@item(iota, "iota", "", "const")
|
||||
/* len(T) int */ //@item(len, "len(T)", "int", "func")
|
||||
/* make(t T, size ...int) T */ //@item(make, "make(t T, size ...int)", "T", "func")
|
||||
/* new(T) *T */ //@item(new, "new(T)", "*T", "func")
|
||||
/* len(v Type) int */ //@item(len, "len(v Type)", "int", "func")
|
||||
/* make(t Type, size ...int) Type */ //@item(make, "make(t Type, size ...int)", "Type", "func")
|
||||
/* new(Type) *Type */ //@item(new, "new(Type)", "*Type", "func")
|
||||
/* nil */ //@item(_nil, "nil", "", "var")
|
||||
/* panic(interface{}) */ //@item(panic, "panic(interface{})", "", "func")
|
||||
/* print(args ...T) */ //@item(print, "print(args ...T)", "", "func")
|
||||
/* println(args ...T) */ //@item(println, "println(args ...T)", "", "func")
|
||||
/* real(complex128) float64 */ //@item(real, "real(complex128)", "float64", "func")
|
||||
/* panic(v interface{}) */ //@item(panic, "panic(v interface{})", "", "func")
|
||||
/* print(args ...Type) */ //@item(print, "print(args ...Type)", "", "func")
|
||||
/* println(args ...Type) */ //@item(println, "println(args ...Type)", "", "func")
|
||||
/* real(c complex128) float64 */ //@item(real, "real(c complex128)", "float64", "func")
|
||||
/* recover() interface{} */ //@item(recover, "recover()", "interface{}", "func")
|
||||
/* rune */ //@item(rune, "rune", "", "type")
|
||||
/* string */ //@item(string, "string", "", "type")
|
||||
|
Loading…
Reference in New Issue
Block a user