go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/syntax/walk_test.go (about)

     1  package syntax_test
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"reflect"
     8  	"strings"
     9  	"testing"
    10  
    11  	"go.starlark.net/syntax"
    12  )
    13  
    14  func TestWalk(t *testing.T) {
    15  	const src = `
    16  for x in y:
    17    if x:
    18      pass
    19    else:
    20      f([2*x for x in "abc"])
    21  `
    22  	// TODO(adonovan): test that it finds all syntax.Nodes
    23  	// (compare against a reflect-based implementation).
    24  	// TODO(adonovan): test that the result of f is used to prune
    25  	// the descent.
    26  	f, err := syntax.Parse("hello.go", src, 0)
    27  	if err != nil {
    28  		t.Fatal(err)
    29  	}
    30  
    31  	var buf bytes.Buffer
    32  	var depth int
    33  	syntax.Walk(f, func(n syntax.Node) bool {
    34  		if n == nil {
    35  			depth--
    36  			return true
    37  		}
    38  		fmt.Fprintf(&buf, "%s%s\n",
    39  			strings.Repeat("  ", depth),
    40  			strings.TrimPrefix(reflect.TypeOf(n).String(), "*syntax."))
    41  		depth++
    42  		return true
    43  	})
    44  	got := buf.String()
    45  	want := `
    46  File
    47    ForStmt
    48      Ident
    49      Ident
    50      IfStmt
    51        Ident
    52        BranchStmt
    53        ExprStmt
    54          CallExpr
    55            Ident
    56            Comprehension
    57              BinaryExpr
    58                Literal
    59                Ident
    60              ForClause
    61                Ident
    62                Literal`
    63  	got = strings.TrimSpace(got)
    64  	want = strings.TrimSpace(want)
    65  	if got != want {
    66  		t.Errorf("got %s, want %s", got, want)
    67  	}
    68  }
    69  
    70  // ExampleWalk demonstrates the use of Walk to
    71  // enumerate the identifiers in a Starlark source file
    72  // containing a nonsense program with varied grammar.
    73  func ExampleWalk() {
    74  	const src = `
    75  load("library", "a")
    76  
    77  def b(c, *, d=e):
    78      f += {g: h}
    79      i = -(j)
    80      return k.l[m + n]
    81  
    82  for o in [p for q, r in s if t]:
    83      u(lambda: v, w[x:y:z])
    84  `
    85  	f, err := syntax.Parse("hello.star", src, 0)
    86  	if err != nil {
    87  		log.Fatal(err)
    88  	}
    89  
    90  	var idents []string
    91  	syntax.Walk(f, func(n syntax.Node) bool {
    92  		if id, ok := n.(*syntax.Ident); ok {
    93  			idents = append(idents, id.Name)
    94  		}
    95  		return true
    96  	})
    97  	fmt.Println(strings.Join(idents, " "))
    98  
    99  	// The identifier 'a' appears in both LoadStmt.From[0] and LoadStmt.To[0].
   100  
   101  	// Output:
   102  	// a a b c d e f g h i j k l m n o p q r s t u v w x y z
   103  }