Update go version

This commit is contained in:
dwrz
2026-08-21 10:23:37 +00:00
parent 78248a6145
commit c2e2d9ea02
466 changed files with 67766 additions and 2881 deletions

View File

@@ -12,7 +12,7 @@ import (
"reflect"
)
// A Kind describes a field of an ast.Node struct.
// A Kind describes a field of an [ast.Node] struct.
type Kind uint8
// String returns a description of the edge kind.
@@ -41,21 +41,25 @@ func (k Kind) Get(n ast.Node, idx int) ast.Node {
panic(fmt.Sprintf("%v.Get(%T): invalid node type", k, n))
}
v := reflect.ValueOf(n).Elem().Field(fieldInfos[k].index)
if idx != -1 {
v = v.Index(idx) // asserts valid index
} else {
// (The type assertion below asserts that v is not a slice.)
if v.Kind() == reflect.Slice {
v = v.Index(idx) // asserts valid idx
} else if idx != -1 {
panic(fmt.Sprintf("%v, Get(%T, %d): cannot index non-slice", v, n, idx))
}
return v.Interface().(ast.Node) // may be nil
out, _ := v.Interface().(ast.Node) // may be nil
return out
}
// Each [Kind] is named Type_Field, where Type is the
// [ast.Node] struct type and Field is the name of the field
const (
Invalid Kind = iota // for nodes at the root of the traversal
// Kinds are sorted alphabetically.
// Numbering is not stable.
// Each is named Type_Field, where Type is the
// ast.Node struct type and Field is the name of the field
// As of Go1.26 these kinds are sorted alphabetically, but
// numbering must be stable, so any new addition of const should
// use a new value (be added at the end of the list).
ArrayType_Elt
ArrayType_Len

View File

@@ -10,6 +10,7 @@ import (
"go/token"
"iter"
"reflect"
"strings"
"golang.org/x/tools/go/ast/edge"
)
@@ -18,8 +19,11 @@ import (
//
// Two Cursors compare equal if they represent the same node.
//
// Call [Inspector.Root] to obtain a valid cursor for the virtual root
// node of the traversal.
// The zero value of Cursor is not valid.
//
// Call [Inspector.Root] to obtain a cursor for the virtual root node
// of the traversal. This is the sole valid cursor for which [Cursor.Node]
// returns nil.
//
// Use the following methods to navigate efficiently around the tree:
// - for ancestors, use [Cursor.Parent] and [Cursor.Enclosing];
@@ -37,7 +41,7 @@ type Cursor struct {
index int32 // index of push node; -1 for virtual root node
}
// Root returns a cursor for the virtual root node,
// Root returns a valid cursor for the virtual root node,
// whose children are the files provided to [New].
//
// Its [Cursor.Node] method return nil.
@@ -61,14 +65,23 @@ func (in *Inspector) At(index int32) Cursor {
return Cursor{in, index}
}
// Valid reports whether the cursor is valid.
// The zero value of cursor is invalid.
// Unless otherwise documented, it is not safe to call
// any other method on an invalid cursor.
func (c Cursor) Valid() bool {
return c.in != nil
}
// Inspector returns the cursor's Inspector.
// It returns nil if the Cursor is not valid.
func (c Cursor) Inspector() *Inspector { return c.in }
// Index returns the index of this cursor position within the package.
//
// Clients should not assume anything about the numeric Index value
// except that it increases monotonically throughout the traversal.
// It is provided for use with [At].
// It is provided for use with [Inspector.At].
//
// Index must not be called on the Root node.
func (c Cursor) Index() int32 {
@@ -89,7 +102,7 @@ func (c Cursor) Node() ast.Node {
// String returns information about the cursor's node, if any.
func (c Cursor) String() string {
if c.in == nil {
if !c.Valid() {
return "(invalid)"
}
if c.index < 0 {
@@ -98,6 +111,46 @@ func (c Cursor) String() string {
return reflect.TypeOf(c.Node()).String()
}
// GoString returns a string describing the cursor's path from the
// root, if any.
func (c Cursor) GoString() string {
if !c.Valid() {
return "(invalid)"
}
if c.index < 0 {
return "(root)"
}
// e.g "File.Decls[1].(*ast.GenDecl).Specs[0].(*ast.TypeSpec)"
//
// In hindsight even the File node should have reported a
// virtual ParentEdge of (Root_Files, i) where i is the index
// among the files passed to NewInspector. Then the path would
// read "(root).Files[i]", etc; but we missed the boat.
var buf strings.Builder
buf.WriteString("File")
var visit func(Cursor)
visit = func(c Cursor) {
ek, idx := c.ParentEdge()
if ek == edge.Invalid {
return // File
}
visit(c.Parent())
fmt.Fprintf(&buf, ".%s", ek.FieldName())
if idx >= 0 {
fmt.Fprintf(&buf, "[%d]", idx)
}
ftype := ek.FieldType()
if idx >= 0 {
ftype = ftype.Elem() // []T -> T
}
if ftype.Kind() == reflect.Interface {
fmt.Fprintf(&buf, ".(%T)", c.Node())
}
}
visit(c)
return buf.String()
}
// indices return the [start, end) half-open interval of event indices.
func (c Cursor) indices() (int32, int32) {
if c.index < 0 {
@@ -233,6 +286,18 @@ func (c Cursor) ParentEdge() (edge.Kind, int) {
return unpackEdgeKindAndIndex(events[pop].parent)
}
// ParentEdgeKind returns the kind component of the result of [Cursor.ParentEdge].
func (c Cursor) ParentEdgeKind() edge.Kind {
ek, _ := c.ParentEdge()
return ek
}
// ParentEdgeIndex returns the index component of the result of [Cursor.ParentEdge].
func (c Cursor) ParentEdgeIndex() int {
_, index := c.ParentEdge()
return index
}
// ChildAt returns the cursor for the child of the
// current node identified by its edge and index.
// The index must be -1 if the edge.Kind is not a slice.
@@ -453,6 +518,9 @@ func (c Cursor) FindNode(n ast.Node) (Cursor, bool) {
// rooted at c such that n.Pos() <= start && end <= n.End().
// (For an *ast.File, it uses the bounds n.FileStart-n.FileEnd.)
//
// An empty range (start == end) between two adjacent nodes is
// considered to belong to the first node.
//
// It returns zero if none is found.
// Precondition: start <= end.
//
@@ -501,10 +569,17 @@ func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) {
break // disjoint, after; stop
}
}
// Inv: node.{Pos,FileStart} <= start
if end <= nodeEnd {
// node fully contains target range
best = i
// Don't search beyond end of the first match.
// This is important only for an empty range (start=end)
// between two adjoining nodes, which would otherwise
// match both nodes; we want to match only the first.
limit = ev.index
} else if nodeEnd < start {
i = ev.index // disjoint, before; skip forward
}

View File

@@ -87,7 +87,7 @@ type event struct {
// Type can be recovered from the sole bit in typ.
// [Tried this, wasn't faster. --adonovan]
// Preorder visits all the nodes of the files supplied to New in
// Preorder visits all the nodes of the files supplied to [New] in
// depth-first order. It calls f(n) for each node n before it visits
// n's children.
//
@@ -133,7 +133,7 @@ func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) {
}
}
// Nodes visits the nodes of the files supplied to New in depth-first
// Nodes visits the nodes of the files supplied to [New] in depth-first
// order. It calls f(n, true) for each node n before it visits n's
// children. If f returns true, Nodes invokes f recursively for each
// of the non-nil children of the node, followed by a call of

View File

@@ -12,13 +12,31 @@ import (
)
// PreorderSeq returns an iterator that visits all the
// nodes of the files supplied to New in depth-first order.
// nodes of the files supplied to [New] in depth-first order.
// It visits each node n before n's children.
// The complete traversal sequence is determined by ast.Inspect.
//
// The types argument, if non-empty, enables type-based
// filtering of events: only nodes whose type matches an
// element of the types slice are included in the sequence.
// The types argument, if non-empty, enables type-based filtering:
// only nodes whose type matches an element of the types slice are
// included in the sequence.
//
// Example:
//
// for call := range in.PreorderSeq((*ast.CallExpr)(nil)) { ... }
//
// The [All] function is more convenient if there is exactly one node type:
//
// for call := range All[*ast.CallExpr](in) { ... }
//
// See also the newer and more flexible [Cursor] API, which lets you
// start the traversal at an arbitrary node, and reports each matching
// node by its Cursor, enabling easier navigation.
// The above example would be written thus:
//
// for curCall := range in.Root().Preorder((*ast.CallExpr)(nil)) {
// call := curCall.Node().(*ast.CallExpr)
// ...
// }
func (in *Inspector) PreorderSeq(types ...ast.Node) iter.Seq[ast.Node] {
// This implementation is identical to Preorder,
@@ -53,6 +71,16 @@ func (in *Inspector) PreorderSeq(types ...ast.Node) iter.Seq[ast.Node] {
// Example:
//
// for call := range All[*ast.CallExpr](in) { ... }
//
// See also the newer and more flexible [Cursor] API, which lets you
// start the traversal at an arbitrary node, and reports each matching
// node by its Cursor, enabling easier navigation.
// The above example would be written thus:
//
// for curCall := range in.Root().Preorder((*ast.CallExpr)(nil)) {
// call := curCall.Node().(*ast.CallExpr)
// ...
// }
func All[N interface {
*S
ast.Node