build(deps): bump golang.org/x/text from 0.26.0 to 0.27.0

Bumps [golang.org/x/text](https://github.com/golang/text) from 0.26.0 to 0.27.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.26.0...v0.27.0)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-version: 0.27.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2025-07-14 17:22:32 +00:00
committed by GitHub
parent 2d24c27329
commit e07b64fef9
17 changed files with 619 additions and 66 deletions

4
go.mod
View File

@@ -104,7 +104,7 @@ require (
golang.org/x/oauth2 v0.30.0
golang.org/x/sync v0.16.0
golang.org/x/term v0.33.0
golang.org/x/text v0.26.0
golang.org/x/text v0.27.0
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822
google.golang.org/grpc v1.73.0
google.golang.org/protobuf v1.36.6
@@ -331,7 +331,7 @@ require (
golang.org/x/mod v0.25.0 // indirect
golang.org/x/sys v0.34.0 // indirect
golang.org/x/time v0.12.0 // indirect
golang.org/x/tools v0.33.0 // indirect
golang.org/x/tools v0.34.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect

8
go.sum
View File

@@ -1478,8 +1478,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -1542,8 +1542,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -207,6 +207,9 @@ func childrenOf(n ast.Node) []ast.Node {
return false // no recursion
})
// TODO(adonovan): be more careful about missing (!Pos.Valid)
// tokens in trees produced from invalid input.
// Then add fake Nodes for bare tokens.
switch n := n.(type) {
case *ast.ArrayType:
@@ -226,9 +229,12 @@ func childrenOf(n ast.Node) []ast.Node {
children = append(children, tok(n.OpPos, len(n.Op.String())))
case *ast.BlockStmt:
children = append(children,
tok(n.Lbrace, len("{")),
tok(n.Rbrace, len("}")))
if n.Lbrace.IsValid() {
children = append(children, tok(n.Lbrace, len("{")))
}
if n.Rbrace.IsValid() {
children = append(children, tok(n.Rbrace, len("}")))
}
case *ast.BranchStmt:
children = append(children,
@@ -304,9 +310,12 @@ func childrenOf(n ast.Node) []ast.Node {
// TODO(adonovan): Field.{Doc,Comment,Tag}?
case *ast.FieldList:
children = append(children,
tok(n.Opening, len("(")), // or len("[")
tok(n.Closing, len(")"))) // or len("]")
if n.Opening.IsValid() {
children = append(children, tok(n.Opening, len("(")))
}
if n.Closing.IsValid() {
children = append(children, tok(n.Closing, len(")")))
}
case *ast.File:
// TODO test: Doc

View File

@@ -67,6 +67,10 @@ var abort = new(int) // singleton, to signal termination of Apply
//
// The methods Replace, Delete, InsertBefore, and InsertAfter
// can be used to change the AST without disrupting Apply.
//
// This type is not to be confused with [inspector.Cursor] from
// package [golang.org/x/tools/go/ast/inspector], which provides
// stateless navigation of immutable syntax trees.
type Cursor struct {
parent ast.Node
name string

502
vendor/golang.org/x/tools/go/ast/inspector/cursor.go generated vendored Normal file
View File

@@ -0,0 +1,502 @@
// Copyright 2025 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 inspector
import (
"fmt"
"go/ast"
"go/token"
"iter"
"reflect"
"golang.org/x/tools/go/ast/edge"
)
// A Cursor represents an [ast.Node]. It is immutable.
//
// 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.
//
// Use the following methods to navigate efficiently around the tree:
// - for ancestors, use [Cursor.Parent] and [Cursor.Enclosing];
// - for children, use [Cursor.Child], [Cursor.Children],
// [Cursor.FirstChild], and [Cursor.LastChild];
// - for siblings, use [Cursor.PrevSibling] and [Cursor.NextSibling];
// - for descendants, use [Cursor.FindByPos], [Cursor.FindNode],
// [Cursor.Inspect], and [Cursor.Preorder].
//
// Use the [Cursor.ChildAt] and [Cursor.ParentEdge] methods for
// information about the edges in a tree: which field (and slice
// element) of the parent node holds the child.
type Cursor struct {
in *Inspector
index int32 // index of push node; -1 for virtual root node
}
// Root returns a cursor for the virtual root node,
// whose children are the files provided to [New].
//
// Its [Cursor.Node] and [Cursor.Stack] methods return nil.
func (in *Inspector) Root() Cursor {
return Cursor{in, -1}
}
// At returns the cursor at the specified index in the traversal,
// which must have been obtained from [Cursor.Index] on a Cursor
// belonging to the same Inspector (see [Cursor.Inspector]).
func (in *Inspector) At(index int32) Cursor {
if index < 0 {
panic("negative index")
}
if int(index) >= len(in.events) {
panic("index out of range for this inspector")
}
if in.events[index].index < index {
panic("invalid index") // (a push, not a pop)
}
return Cursor{in, index}
}
// Inspector returns the cursor's Inspector.
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].
//
// Index must not be called on the Root node.
func (c Cursor) Index() int32 {
if c.index < 0 {
panic("Index called on Root node")
}
return c.index
}
// Node returns the node at the current cursor position,
// or nil for the cursor returned by [Inspector.Root].
func (c Cursor) Node() ast.Node {
if c.index < 0 {
return nil
}
return c.in.events[c.index].node
}
// String returns information about the cursor's node, if any.
func (c Cursor) String() string {
if c.in == nil {
return "(invalid)"
}
if c.index < 0 {
return "(root)"
}
return reflect.TypeOf(c.Node()).String()
}
// indices return the [start, end) half-open interval of event indices.
func (c Cursor) indices() (int32, int32) {
if c.index < 0 {
return 0, int32(len(c.in.events)) // root: all events
} else {
return c.index, c.in.events[c.index].index + 1 // just one subtree
}
}
// Preorder returns an iterator over the nodes of the subtree
// represented by c in depth-first order. Each node in the sequence is
// represented by a Cursor that allows access to the Node, but may
// also be used to start a new traversal, or to obtain the stack of
// nodes enclosing the cursor.
//
// The traversal sequence is determined by [ast.Inspect]. The types
// argument, if non-empty, enables type-based filtering of events. The
// function f if is called only for nodes whose type matches an
// element of the types slice.
//
// If you need control over descent into subtrees,
// or need both pre- and post-order notifications, use [Cursor.Inspect]
func (c Cursor) Preorder(types ...ast.Node) iter.Seq[Cursor] {
mask := maskOf(types)
return func(yield func(Cursor) bool) {
events := c.in.events
for i, limit := c.indices(); i < limit; {
ev := events[i]
if ev.index > i { // push?
if ev.typ&mask != 0 && !yield(Cursor{c.in, i}) {
break
}
pop := ev.index
if events[pop].typ&mask == 0 {
// Subtree does not contain types: skip.
i = pop + 1
continue
}
}
i++
}
}
}
// Inspect visits the nodes of the subtree represented by c in
// depth-first order. It calls f(n) for each node n before it
// visits n's children. If f returns true, Inspect invokes f
// recursively for each of the non-nil children of the node.
//
// Each node is represented by a Cursor that allows access to the
// Node, but may also be used to start a new traversal, or to obtain
// the stack of nodes enclosing the cursor.
//
// The complete traversal sequence is determined by [ast.Inspect].
// The types argument, if non-empty, enables type-based filtering of
// events. The function f if is called only for nodes whose type
// matches an element of the types slice.
func (c Cursor) Inspect(types []ast.Node, f func(c Cursor) (descend bool)) {
mask := maskOf(types)
events := c.in.events
for i, limit := c.indices(); i < limit; {
ev := events[i]
if ev.index > i {
// push
pop := ev.index
if ev.typ&mask != 0 && !f(Cursor{c.in, i}) ||
events[pop].typ&mask == 0 {
// The user opted not to descend, or the
// subtree does not contain types:
// skip past the pop.
i = pop + 1
continue
}
}
i++
}
}
// Enclosing returns an iterator over the nodes enclosing the current
// current node, starting with the Cursor itself.
//
// Enclosing must not be called on the Root node (whose [Cursor.Node] returns nil).
//
// The types argument, if non-empty, enables type-based filtering of
// events: the sequence includes only enclosing nodes whose type
// matches an element of the types slice.
func (c Cursor) Enclosing(types ...ast.Node) iter.Seq[Cursor] {
if c.index < 0 {
panic("Cursor.Enclosing called on Root node")
}
mask := maskOf(types)
return func(yield func(Cursor) bool) {
events := c.in.events
for i := c.index; i >= 0; i = events[i].parent {
if events[i].typ&mask != 0 && !yield(Cursor{c.in, i}) {
break
}
}
}
}
// Parent returns the parent of the current node.
//
// Parent must not be called on the Root node (whose [Cursor.Node] returns nil).
func (c Cursor) Parent() Cursor {
if c.index < 0 {
panic("Cursor.Parent called on Root node")
}
return Cursor{c.in, c.in.events[c.index].parent}
}
// ParentEdge returns the identity of the field in the parent node
// that holds this cursor's node, and if it is a list, the index within it.
//
// For example, f(x, y) is a CallExpr whose three children are Idents.
// f has edge kind [edge.CallExpr_Fun] and index -1.
// x and y have kind [edge.CallExpr_Args] and indices 0 and 1, respectively.
//
// If called on a child of the Root node, it returns ([edge.Invalid], -1).
//
// ParentEdge must not be called on the Root node (whose [Cursor.Node] returns nil).
func (c Cursor) ParentEdge() (edge.Kind, int) {
if c.index < 0 {
panic("Cursor.ParentEdge called on Root node")
}
events := c.in.events
pop := events[c.index].index
return unpackEdgeKindAndIndex(events[pop].parent)
}
// 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.
// The indicated child node must exist.
//
// ChildAt must not be called on the Root node (whose [Cursor.Node] returns nil).
//
// Invariant: c.Parent().ChildAt(c.ParentEdge()) == c.
func (c Cursor) ChildAt(k edge.Kind, idx int) Cursor {
target := packEdgeKindAndIndex(k, idx)
// Unfortunately there's no shortcut to looping.
events := c.in.events
i := c.index + 1
for {
pop := events[i].index
if pop < i {
break
}
if events[pop].parent == target {
return Cursor{c.in, i}
}
i = pop + 1
}
panic(fmt.Sprintf("ChildAt(%v, %d): no such child of %v", k, idx, c))
}
// Child returns the cursor for n, which must be a direct child of c's Node.
//
// Child must not be called on the Root node (whose [Cursor.Node] returns nil).
func (c Cursor) Child(n ast.Node) Cursor {
if c.index < 0 {
panic("Cursor.Child called on Root node")
}
if false {
// reference implementation
for child := range c.Children() {
if child.Node() == n {
return child
}
}
} else {
// optimized implementation
events := c.in.events
for i := c.index + 1; events[i].index > i; i = events[i].index + 1 {
if events[i].node == n {
return Cursor{c.in, i}
}
}
}
panic(fmt.Sprintf("Child(%T): not a child of %v", n, c))
}
// NextSibling returns the cursor for the next sibling node in the same list
// (for example, of files, decls, specs, statements, fields, or expressions) as
// the current node. It returns (zero, false) if the node is the last node in
// the list, or is not part of a list.
//
// NextSibling must not be called on the Root node.
//
// See note at [Cursor.Children].
func (c Cursor) NextSibling() (Cursor, bool) {
if c.index < 0 {
panic("Cursor.NextSibling called on Root node")
}
events := c.in.events
i := events[c.index].index + 1 // after corresponding pop
if i < int32(len(events)) {
if events[i].index > i { // push?
return Cursor{c.in, i}, true
}
}
return Cursor{}, false
}
// PrevSibling returns the cursor for the previous sibling node in the
// same list (for example, of files, decls, specs, statements, fields,
// or expressions) as the current node. It returns zero if the node is
// the first node in the list, or is not part of a list.
//
// It must not be called on the Root node.
//
// See note at [Cursor.Children].
func (c Cursor) PrevSibling() (Cursor, bool) {
if c.index < 0 {
panic("Cursor.PrevSibling called on Root node")
}
events := c.in.events
i := c.index - 1
if i >= 0 {
if j := events[i].index; j < i { // pop?
return Cursor{c.in, j}, true
}
}
return Cursor{}, false
}
// FirstChild returns the first direct child of the current node,
// or zero if it has no children.
func (c Cursor) FirstChild() (Cursor, bool) {
events := c.in.events
i := c.index + 1 // i=0 if c is root
if i < int32(len(events)) && events[i].index > i { // push?
return Cursor{c.in, i}, true
}
return Cursor{}, false
}
// LastChild returns the last direct child of the current node,
// or zero if it has no children.
func (c Cursor) LastChild() (Cursor, bool) {
events := c.in.events
if c.index < 0 { // root?
if len(events) > 0 {
// return push of final event (a pop)
return Cursor{c.in, events[len(events)-1].index}, true
}
} else {
j := events[c.index].index - 1 // before corresponding pop
// Inv: j == c.index if c has no children
// or j is last child's pop.
if j > c.index { // c has children
return Cursor{c.in, events[j].index}, true
}
}
return Cursor{}, false
}
// Children returns an iterator over the direct children of the
// current node, if any.
//
// When using Children, NextChild, and PrevChild, bear in mind that a
// Node's children may come from different fields, some of which may
// be lists of nodes without a distinguished intervening container
// such as [ast.BlockStmt].
//
// For example, [ast.CaseClause] has a field List of expressions and a
// field Body of statements, so the children of a CaseClause are a mix
// of expressions and statements. Other nodes that have "uncontained"
// list fields include:
//
// - [ast.ValueSpec] (Names, Values)
// - [ast.CompositeLit] (Type, Elts)
// - [ast.IndexListExpr] (X, Indices)
// - [ast.CallExpr] (Fun, Args)
// - [ast.AssignStmt] (Lhs, Rhs)
//
// So, do not assume that the previous sibling of an ast.Stmt is also
// an ast.Stmt, or if it is, that they are executed sequentially,
// unless you have established that, say, its parent is a BlockStmt
// or its [Cursor.ParentEdge] is [edge.BlockStmt_List].
// For example, given "for S1; ; S2 {}", the predecessor of S2 is S1,
// even though they are not executed in sequence.
func (c Cursor) Children() iter.Seq[Cursor] {
return func(yield func(Cursor) bool) {
c, ok := c.FirstChild()
for ok && yield(c) {
c, ok = c.NextSibling()
}
}
}
// Contains reports whether c contains or is equal to c2.
//
// Both Cursors must belong to the same [Inspector];
// neither may be its Root node.
func (c Cursor) Contains(c2 Cursor) bool {
if c.in != c2.in {
panic("different inspectors")
}
events := c.in.events
return c.index <= c2.index && events[c2.index].index <= events[c.index].index
}
// FindNode returns the cursor for node n if it belongs to the subtree
// rooted at c. It returns zero if n is not found.
func (c Cursor) FindNode(n ast.Node) (Cursor, bool) {
// FindNode is equivalent to this code,
// but more convenient and 15-20% faster:
if false {
for candidate := range c.Preorder(n) {
if candidate.Node() == n {
return candidate, true
}
}
return Cursor{}, false
}
// TODO(adonovan): opt: should we assume Node.Pos is accurate
// and combine type-based filtering with position filtering
// like FindByPos?
mask := maskOf([]ast.Node{n})
events := c.in.events
for i, limit := c.indices(); i < limit; i++ {
ev := events[i]
if ev.index > i { // push?
if ev.typ&mask != 0 && ev.node == n {
return Cursor{c.in, i}, true
}
pop := ev.index
if events[pop].typ&mask == 0 {
// Subtree does not contain type of n: skip.
i = pop
}
}
}
return Cursor{}, false
}
// FindByPos returns the cursor for the innermost node n in the tree
// rooted at c such that n.Pos() <= start && end <= n.End().
// (For an *ast.File, it uses the bounds n.FileStart-n.FileEnd.)
//
// It returns zero if none is found.
// Precondition: start <= end.
//
// See also [astutil.PathEnclosingInterval], which
// tolerates adjoining whitespace.
func (c Cursor) FindByPos(start, end token.Pos) (Cursor, bool) {
if end < start {
panic("end < start")
}
events := c.in.events
// This algorithm could be implemented using c.Inspect,
// but it is about 2.5x slower.
best := int32(-1) // push index of latest (=innermost) node containing range
for i, limit := c.indices(); i < limit; i++ {
ev := events[i]
if ev.index > i { // push?
n := ev.node
var nodeEnd token.Pos
if file, ok := n.(*ast.File); ok {
nodeEnd = file.FileEnd
// Note: files may be out of Pos order.
if file.FileStart > start {
i = ev.index // disjoint, after; skip to next file
continue
}
} else {
nodeEnd = n.End()
if n.Pos() > start {
break // disjoint, after; stop
}
}
// Inv: node.{Pos,FileStart} <= start
if end <= nodeEnd {
// node fully contains target range
best = i
} else if nodeEnd < start {
i = ev.index // disjoint, before; skip forward
}
}
}
if best >= 0 {
return Cursor{c.in, best}, true
}
return Cursor{}, false
}

View File

@@ -13,10 +13,19 @@
// This representation is sometimes called a "balanced parenthesis tree."
//
// Experiments suggest the inspector's traversals are about 2.5x faster
// than ast.Inspect, but it may take around 5 traversals for this
// than [ast.Inspect], but it may take around 5 traversals for this
// benefit to amortize the inspector's construction cost.
// If efficiency is the primary concern, do not use Inspector for
// one-off traversals.
//
// The [Cursor] type provides a more flexible API for efficient
// navigation of syntax trees in all four "cardinal directions". For
// example, traversals may be nested, so you can find each node of
// type A and then search within it for nodes of type B. Or you can
// traverse from a node to its immediate neighbors: its parent, its
// previous and next sibling, or its first and last child. We
// recommend using methods of Cursor in preference to Inspector where
// possible.
package inspector
// There are four orthogonal features in a traversal:
@@ -37,9 +46,8 @@ package inspector
import (
"go/ast"
_ "unsafe"
"golang.org/x/tools/internal/astutil/edge"
"golang.org/x/tools/go/ast/edge"
)
// An Inspector provides methods for inspecting
@@ -48,18 +56,12 @@ type Inspector struct {
events []event
}
//go:linkname events golang.org/x/tools/go/ast/inspector.events
func events(in *Inspector) []event { return in.events }
//go:linkname packEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.packEdgeKindAndIndex
func packEdgeKindAndIndex(ek edge.Kind, index int) int32 {
return int32(uint32(index+1)<<7 | uint32(ek))
}
// unpackEdgeKindAndIndex unpacks the edge kind and edge index (within
// an []ast.Node slice) from the parent field of a pop event.
//
//go:linkname unpackEdgeKindAndIndex golang.org/x/tools/go/ast/inspector.unpackEdgeKindAndIndex
func unpackEdgeKindAndIndex(x int32) (edge.Kind, int) {
// The "parent" field of a pop node holds the
// edge Kind in the lower 7 bits and the index+1
@@ -88,10 +90,15 @@ type event struct {
// depth-first order. It calls f(n) for each node n before it visits
// n's children.
//
// The complete traversal sequence is determined by ast.Inspect.
// The complete traversal sequence is determined by [ast.Inspect].
// The types argument, if non-empty, enables type-based filtering of
// events. The function f is called only for nodes whose type
// matches an element of the types slice.
//
// The [Cursor.Preorder] method provides a richer alternative interface.
// Example:
//
// for c := range in.Root().Preorder(types) { ... }
func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) {
// Because it avoids postorder calls to f, and the pruning
// check, Preorder is almost twice as fast as Nodes. The two
@@ -131,10 +138,18 @@ func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) {
// of the non-nil children of the node, followed by a call of
// f(n, false).
//
// The complete traversal sequence is determined by ast.Inspect.
// The complete traversal sequence is determined by [ast.Inspect].
// The types argument, if non-empty, enables type-based filtering of
// events. The function f if is called only for nodes whose type
// matches an element of the types slice.
//
// The [Cursor.Inspect] method provides a richer alternative interface.
// Example:
//
// in.Root().Inspect(types, func(c Cursor) bool {
// ...
// return true
// }
func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (proceed bool)) {
mask := maskOf(types)
for i := int32(0); i < int32(len(in.events)); {
@@ -168,6 +183,15 @@ func (in *Inspector) Nodes(types []ast.Node, f func(n ast.Node, push bool) (proc
// supplies each call to f an additional argument, the current
// traversal stack. The stack's first element is the outermost node,
// an *ast.File; its last is the innermost, n.
//
// The [Cursor.Inspect] method provides a richer alternative interface.
// Example:
//
// in.Root().Inspect(types, func(c Cursor) bool {
// stack := slices.Collect(c.Enclosing())
// ...
// return true
// })
func (in *Inspector) WithStack(types []ast.Node, f func(n ast.Node, push bool, stack []ast.Node) (proceed bool)) {
mask := maskOf(types)
var stack []ast.Node
@@ -233,7 +257,7 @@ type visitor struct {
type item struct {
index int32 // index of current node's push event
parentIndex int32 // index of parent node's push event
typAccum uint64 // accumulated type bits of current node's descendents
typAccum uint64 // accumulated type bits of current node's descendants
edgeKindAndIndex int32 // edge.Kind and index, bit packed
}

View File

@@ -13,7 +13,7 @@ import (
"fmt"
"go/ast"
"golang.org/x/tools/internal/astutil/edge"
"golang.org/x/tools/go/ast/edge"
)
func walkList[N ast.Node](v *visitor, ek edge.Kind, list []N) {

View File

@@ -603,7 +603,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
type hasTypeParams interface {
TypeParams() *types.TypeParamList
}
// abstraction of *types.{Named,TypeParam}
// abstraction of *types.{Alias,Named,TypeParam}
type hasObj interface {
Obj() *types.TypeName
}

View File

@@ -27,12 +27,13 @@ import (
"unicode"
"unicode/utf8"
"maps"
"golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/gocommand"
"golang.org/x/tools/internal/gopathwalk"
"golang.org/x/tools/internal/stdlib"
"maps"
)
// importToGroup is a list of functions which map from an import path to
@@ -290,8 +291,8 @@ func (p *pass) loadPackageNames(ctx context.Context, imports []*ImportInfo) erro
return nil
}
// if there is a trailing major version, remove it
func withoutVersion(nm string) string {
// WithoutVersion removes a trailing major version, if there is one.
func WithoutVersion(nm string) string {
if v := path.Base(nm); len(v) > 0 && v[0] == 'v' {
if _, err := strconv.Atoi(v[1:]); err == nil {
// this is, for instance, called with rand/v2 and returns rand
@@ -313,7 +314,7 @@ func (p *pass) importIdentifier(imp *ImportInfo) string {
}
known := p.knownPackages[imp.ImportPath]
if known != nil && known.Name != "" {
return withoutVersion(known.Name)
return WithoutVersion(known.Name)
}
return ImportPathToAssumedName(imp.ImportPath)
}

View File

@@ -93,7 +93,7 @@ func FixImports(ctx context.Context, filename string, src []byte, goroot string,
// env is needed.
func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, extraMode parser.Mode) (formatted []byte, err error) {
// Don't use parse() -- we don't care about fragments or statement lists
// here, and we need to work with unparseable files.
// here, and we need to work with unparsable files.
fileSet := token.NewFileSet()
parserMode := parser.SkipObjectResolution
if opt.Comments {

View File

@@ -26,7 +26,7 @@ type directory struct {
syms []symbol
}
// filterDirs groups the directories by import path,
// byImportPath groups the directories by import path,
// sorting the ones with the same import path by semantic version,
// most recent first.
func byImportPath(dirs []Relpath) (map[string][]*directory, error) {

View File

@@ -75,7 +75,7 @@ func (ix *Index) Lookup(pkg, name string, prefix bool) []Candidate {
return nil // didn't find the package
}
var ans []Candidate
// loc is the first entry for this package name, but there may be severeal
// loc is the first entry for this package name, but there may be several
for i := loc; i < len(ix.Entries); i++ {
e := ix.Entries[i]
if e.PkgName != pkg {

View File

@@ -30,7 +30,7 @@ import (
type symbol struct {
pkg string // name of the symbols's package
name string // declared name
kind string // T, C, V, or F, follwed by D if deprecated
kind string // T, C, V, or F, followed by D if deprecated
sig string // signature information, for F
}
@@ -110,7 +110,7 @@ func getFileExports(f *ast.File) []symbol {
// The only place a $ can occur seems to be in a struct tag, which
// can be an arbitrary string literal, and ExprString does not presently
// print struct tags. So for this to happen the type of a formal parameter
// has to be a explict struct, e.g. foo(x struct{a int "$"}) and ExprString
// has to be a explicit struct, e.g. foo(x struct{a int "$"}) and ExprString
// would have to show the struct tag. Even testing for this case seems
// a waste of effort, but let's remember the possibility
if strings.Contains(tp, "$") {

View File

@@ -65,14 +65,16 @@ func ClassifyCall(info *types.Info, call *ast.CallExpr) CallKind {
if info.Types == nil {
panic("ClassifyCall: info.Types is nil")
}
if info.Types[call.Fun].IsType() {
tv := info.Types[call.Fun]
if tv.IsType() {
return CallConversion
}
if tv.IsBuiltin() {
return CallBuiltin
}
obj := info.Uses[UsedIdent(info, call.Fun)]
// Classify the call by the type of the object, if any.
switch obj := obj.(type) {
case *types.Builtin:
return CallBuiltin
case *types.Func:
if interfaceMethod(obj) {
return CallInterface

View File

@@ -69,6 +69,34 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
}
}
// TypeNameFor returns the type name symbol for the specified type, if
// it is a [*types.Alias], [*types.Named], [*types.TypeParam], or a
// [*types.Basic] representing a type.
//
// For all other types, and for Basic types representing a builtin,
// constant, or nil, it returns nil. Be careful not to convert the
// resulting nil pointer to a [types.Object]!
//
// If t is the type of a constant, it may be an "untyped" type, which
// has no TypeName. To access the name of such types (e.g. "untyped
// int"), use [types.Basic.Name].
func TypeNameFor(t types.Type) *types.TypeName {
switch t := t.(type) {
case *types.Alias:
return t.Obj()
case *types.Named:
return t.Obj()
case *types.TypeParam:
return t.Obj()
case *types.Basic:
// See issues #71886 and #66890 for some history.
if tname, ok := types.Universe.Lookup(t.Name()).(*types.TypeName); ok {
return tname
}
}
return nil
}
// A NamedOrAlias is a [types.Type] that is named (as
// defined by the spec) and capable of bearing type parameters: it
// abstracts aliases ([types.Alias]) and defined types
@@ -77,7 +105,7 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
// Every type declared by an explicit "type" declaration is a
// NamedOrAlias. (Built-in type symbols may additionally
// have type [types.Basic], which is not a NamedOrAlias,
// though the spec regards them as "named".)
// though the spec regards them as "named"; see [TypeNameFor].)
//
// NamedOrAlias cannot expose the Origin method, because
// [types.Alias.Origin] and [types.Named.Origin] have different
@@ -85,32 +113,15 @@ func NameRelativeTo(pkg *types.Package) types.Qualifier {
type NamedOrAlias interface {
types.Type
Obj() *types.TypeName
// TODO(hxjiang): add method TypeArgs() *types.TypeList after stop supporting go1.22.
TypeArgs() *types.TypeList
TypeParams() *types.TypeParamList
SetTypeParams(tparams []*types.TypeParam)
}
// TypeParams is a light shim around t.TypeParams().
// (go/types.Alias).TypeParams requires >= 1.23.
func TypeParams(t NamedOrAlias) *types.TypeParamList {
switch t := t.(type) {
case *types.Alias:
return aliases.TypeParams(t)
case *types.Named:
return t.TypeParams()
}
return nil
}
// TypeArgs is a light shim around t.TypeArgs().
// (go/types.Alias).TypeArgs requires >= 1.23.
func TypeArgs(t NamedOrAlias) *types.TypeList {
switch t := t.(type) {
case *types.Alias:
return aliases.TypeArgs(t)
case *types.Named:
return t.TypeArgs()
}
return nil
}
var (
_ NamedOrAlias = (*types.Alias)(nil)
_ NamedOrAlias = (*types.Named)(nil)
)
// Origin returns the generic type of the Named or Alias type t if it
// is instantiated, otherwise it returns t.

6
vendor/modules.txt vendored
View File

@@ -2257,7 +2257,7 @@ golang.org/x/sys/windows/svc/mgr
# golang.org/x/term v0.33.0
## explicit; go 1.23.0
golang.org/x/term
# golang.org/x/text v0.26.0
# golang.org/x/text v0.27.0
## explicit; go 1.23.0
golang.org/x/text/cases
golang.org/x/text/encoding
@@ -2285,10 +2285,11 @@ golang.org/x/text/width
# golang.org/x/time v0.12.0
## explicit; go 1.23.0
golang.org/x/time/rate
# golang.org/x/tools v0.33.0
# golang.org/x/tools v0.34.0
## explicit; go 1.23.0
golang.org/x/tools/cover
golang.org/x/tools/go/ast/astutil
golang.org/x/tools/go/ast/edge
golang.org/x/tools/go/ast/inspector
golang.org/x/tools/go/gcexportdata
golang.org/x/tools/go/packages
@@ -2296,7 +2297,6 @@ golang.org/x/tools/go/types/objectpath
golang.org/x/tools/go/types/typeutil
golang.org/x/tools/imports
golang.org/x/tools/internal/aliases
golang.org/x/tools/internal/astutil/edge
golang.org/x/tools/internal/event
golang.org/x/tools/internal/event/core
golang.org/x/tools/internal/event/keys