stdlib.go raw

   1  // Copyright 2022 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  //go:generate go run generate.go
   6  
   7  // Package stdlib provides a table of all exported symbols in the
   8  // standard library, along with the version at which they first
   9  // appeared. It also provides the import graph of std packages.
  10  package stdlib
  11  
  12  import (
  13  	"fmt"
  14  	"strings"
  15  )
  16  
  17  type Symbol struct {
  18  	Name    string
  19  	Kind    Kind
  20  	Version Version // Go version that first included the symbol
  21  	// Signature provides the type of a function (defined only for Kind=Func).
  22  	// Imported types are denoted as pkg.T; pkg is not fully qualified.
  23  	// TODO(adonovan): use an unambiguous encoding that is parseable.
  24  	//
  25  	// Example2:
  26  	//    func[M ~map[K]V, K comparable, V any](m M) M
  27  	//    func(fi fs.FileInfo, link string) (*Header, error)
  28  	Signature string // if Kind == stdlib.Func
  29  }
  30  
  31  // A Kind indicates the kind of a symbol:
  32  // function, variable, constant, type, and so on.
  33  type Kind int8
  34  
  35  const (
  36  	Invalid Kind = iota // Example name:
  37  	Type                // "Buffer"
  38  	Func                // "Println"
  39  	Var                 // "EOF"
  40  	Const               // "Pi"
  41  	Field               // "Point.X"
  42  	Method              // "(*Buffer).Grow" or "(Reader).Read"
  43  )
  44  
  45  func (kind Kind) String() string {
  46  	return [...]string{
  47  		Invalid: "invalid",
  48  		Type:    "type",
  49  		Func:    "func",
  50  		Var:     "var",
  51  		Const:   "const",
  52  		Field:   "field",
  53  		Method:  "method",
  54  	}[kind]
  55  }
  56  
  57  // A Version represents a version of Go of the form "go1.%d".
  58  type Version int8
  59  
  60  // String returns a version string of the form "go1.23", without allocating.
  61  func (v Version) String() string { return versions[v] }
  62  
  63  var versions [30]string // (increase constant as needed)
  64  
  65  func init() {
  66  	for i := range versions {
  67  		versions[i] = fmt.Sprintf("go1.%d", i)
  68  	}
  69  }
  70  
  71  // HasPackage reports whether the specified package path is part of
  72  // the standard library's public API.
  73  func HasPackage(path string) bool {
  74  	_, ok := PackageSymbols[path]
  75  	return ok
  76  }
  77  
  78  // SplitField splits the field symbol name into type and field
  79  // components. It must be called only on Field symbols.
  80  //
  81  // Example: "File.Package" -> ("File", "Package")
  82  func (sym *Symbol) SplitField() (typename, name string) {
  83  	if sym.Kind != Field {
  84  		panic("not a field")
  85  	}
  86  	typename, name, _ = strings.Cut(sym.Name, ".")
  87  	return
  88  }
  89  
  90  // SplitMethod splits the method symbol name into pointer, receiver,
  91  // and method components. It must be called only on Method symbols.
  92  //
  93  // Example: "(*Buffer).Grow" -> (true, "Buffer", "Grow")
  94  func (sym *Symbol) SplitMethod() (ptr bool, recv, name string) {
  95  	if sym.Kind != Method {
  96  		panic("not a method")
  97  	}
  98  	recv, name, _ = strings.Cut(sym.Name, ".")
  99  	recv = recv[len("(") : len(recv)-len(")")]
 100  	ptr = recv[0] == '*'
 101  	if ptr {
 102  		recv = recv[len("*"):]
 103  	}
 104  	return
 105  }
 106