Source file src/cmd/compile/internal/syntax/printer_test.go

     1  // Copyright 2016 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  package syntax
     6  
     7  import (
     8  	"fmt"
     9  	"io"
    10  	"os"
    11  	"strings"
    12  	"testing"
    13  )
    14  
    15  func TestPrint(t *testing.T) {
    16  	if testing.Short() {
    17  		t.Skip("skipping test in short mode")
    18  	}
    19  
    20  	ast, _ := ParseFile(*src_, func(err error) { t.Error(err) }, nil, 0)
    21  
    22  	if ast != nil {
    23  		Fprint(testOut(), ast, LineForm)
    24  		fmt.Println()
    25  	}
    26  }
    27  
    28  type shortBuffer struct {
    29  	buf []byte
    30  }
    31  
    32  func (w *shortBuffer) Write(data []byte) (n int, err error) {
    33  	w.buf = append(w.buf, data...)
    34  	n = len(data)
    35  	if len(w.buf) > 10 {
    36  		err = io.ErrShortBuffer
    37  	}
    38  	return
    39  }
    40  
    41  func TestPrintError(t *testing.T) {
    42  	const src = "package p; var x int"
    43  	ast, err := Parse(nil, strings.NewReader(src), nil, nil, 0)
    44  	if err != nil {
    45  		t.Fatal(err)
    46  	}
    47  
    48  	var buf shortBuffer
    49  	_, err = Fprint(&buf, ast, 0)
    50  	if err == nil || err != io.ErrShortBuffer {
    51  		t.Errorf("got err = %s, want %s", err, io.ErrShortBuffer)
    52  	}
    53  }
    54  
    55  var stringTests = [][2]string{
    56  	dup("package p"),
    57  	dup("package p; type _ int; type T1 = struct{}; type ( _ *struct{}; T2 = float32 )"),
    58  
    59  	// generic type declarations (given type separated with blank from LHS)
    60  	dup("package p; type _[T any] struct{}"),
    61  	dup("package p; type _[A, B, C interface{m()}] struct{}"),
    62  	dup("package p; type _[T any, A, B, C interface{m()}, X, Y, Z interface{~int}] struct{}"),
    63  
    64  	dup("package p; type _[P *struct{}] struct{}"),
    65  	dup("package p; type _[P *T,] struct{}"),
    66  	dup("package p; type _[P *T, _ any] struct{}"),
    67  	{"package p; type _[P (*T),] struct{}", "package p; type _[P *T,] struct{}"},
    68  	{"package p; type _[P (*T), _ any] struct{}", "package p; type _[P *T, _ any] struct{}"},
    69  	{"package p; type _[P (T),] struct{}", "package p; type _[P T] struct{}"},
    70  	{"package p; type _[P (T), _ any] struct{}", "package p; type _[P T, _ any] struct{}"},
    71  
    72  	{"package p; type _[P (*struct{})] struct{}", "package p; type _[P *struct{}] struct{}"},
    73  	{"package p; type _[P ([]int)] struct{}", "package p; type _[P []int] struct{}"},
    74  	{"package p; type _[P ([]int) | int] struct{}", "package p; type _[P []int | int] struct{}"},
    75  
    76  	// a type literal in an |-expression indicates a type parameter list (blank after type parameter list and type)
    77  	dup("package p; type _[P *[]int] struct{}"),
    78  	dup("package p; type _[P T | T] struct{}"),
    79  	dup("package p; type _[P T | T | T | T] struct{}"),
    80  	dup("package p; type _[P *T | T, Q T] struct{}"),
    81  	dup("package p; type _[P *[]T | T] struct{}"),
    82  	dup("package p; type _[P *T | T | T | T | ~T] struct{}"),
    83  	dup("package p; type _[P *T | T | T | ~T | T] struct{}"),
    84  	dup("package p; type _[P *T | T | struct{} | T] struct{}"),
    85  	dup("package p; type _[P <-chan int] struct{}"),
    86  	dup("package p; type _[P *T | struct{} | T] struct{}"),
    87  
    88  	// a trailing comma always indicates a (possibly invalid) type parameter list (blank after type parameter list and type)
    89  	dup("package p; type _[P *T,] struct{}"),
    90  	dup("package p; type _[P *T | T,] struct{}"),
    91  	dup("package p; type _[P *T | <-T | T,] struct{}"),
    92  
    93  	// slice/array type declarations (no blank between array length and element type)
    94  	dup("package p; type _ []byte"),
    95  	dup("package p; type _ [n]byte"),
    96  	dup("package p; type _ [P(T)]byte"),
    97  	dup("package p; type _ [P((T))]byte"),
    98  	dup("package p; type _ [P * *T]byte"),
    99  	dup("package p; type _ [P * T]byte"),
   100  	dup("package p; type _ [P(*T)]byte"),
   101  	dup("package p; type _ [P(**T)]byte"),
   102  	dup("package p; type _ [P * T - T]byte"),
   103  	dup("package p; type _ [P * T - T]byte"),
   104  	dup("package p; type _ [P * T | T]byte"),
   105  	dup("package p; type _ [P * T | <-T | T]byte"),
   106  
   107  	// generic function declarations
   108  	dup("package p; func _[T any]()"),
   109  	dup("package p; func _[A, B, C interface{m()}]()"),
   110  	dup("package p; func _[T any, A, B, C interface{m()}, X, Y, Z interface{~int}]()"),
   111  
   112  	// generic functions with elided interfaces in type constraints
   113  	dup("package p; func _[P *T]() {}"),
   114  	dup("package p; func _[P *T | T | T | T | ~T]() {}"),
   115  	dup("package p; func _[P *T | T | struct{} | T]() {}"),
   116  	dup("package p; func _[P ~int, Q int | string]() {}"),
   117  	dup("package p; func _[P struct{f int}, Q *P]() {}"),
   118  
   119  	// methods with generic receiver types
   120  	dup("package p; func (R[T]) _()"),
   121  	dup("package p; func (*R[A, B, C]) _()"),
   122  	dup("package p; func (_ *R[A, B, C]) _()"),
   123  
   124  	// channels
   125  	dup("package p; type _ chan chan int"),
   126  	dup("package p; type _ chan (<-chan int)"),
   127  	dup("package p; type _ chan chan<- int"),
   128  
   129  	dup("package p; type _ <-chan chan int"),
   130  	dup("package p; type _ <-chan <-chan int"),
   131  	dup("package p; type _ <-chan chan<- int"),
   132  
   133  	dup("package p; type _ chan<- chan int"),
   134  	dup("package p; type _ chan<- <-chan int"),
   135  	dup("package p; type _ chan<- chan<- int"),
   136  
   137  	// go.dev/issues/69206
   138  	dup("package p; type _[P C] int"),
   139  	{"package p; type _[P (C),] int", "package p; type _[P C] int"},
   140  	{"package p; type _[P ((C)),] int", "package p; type _[P C] int"},
   141  	{"package p; type _[P, Q ((C))] int", "package p; type _[P, Q C] int"},
   142  
   143  	// TODO(gri) expand
   144  }
   145  
   146  func TestPrintString(t *testing.T) {
   147  	for _, test := range stringTests {
   148  		ast, err := Parse(nil, strings.NewReader(test[0]), nil, nil, 0)
   149  		if err != nil {
   150  			t.Error(err)
   151  			continue
   152  		}
   153  		if got := String(ast); got != test[1] {
   154  			t.Errorf("%q: got %q", test[1], got)
   155  		}
   156  	}
   157  }
   158  
   159  func testOut() io.Writer {
   160  	if testing.Verbose() {
   161  		return os.Stdout
   162  	}
   163  	return io.Discard
   164  }
   165  
   166  func dup(s string) [2]string { return [2]string{s, s} }
   167  
   168  var exprTests = [][2]string{
   169  	// basic type literals
   170  	dup("x"),
   171  	dup("true"),
   172  	dup("42"),
   173  	dup("3.1415"),
   174  	dup("2.71828i"),
   175  	dup(`'a'`),
   176  	dup(`"foo"`),
   177  	dup("`bar`"),
   178  	dup("any"),
   179  
   180  	// func and composite literals
   181  	dup("func() {}"),
   182  	dup("[]int{}"),
   183  	{"func(x int) complex128 { return 0 }", "func(x int) complex128 {…}"},
   184  	{"[]int{1, 2, 3}", "[]int{…}"},
   185  
   186  	// type expressions
   187  	dup("[1 << 10]byte"),
   188  	dup("[]int"),
   189  	dup("*int"),
   190  	dup("struct{x int}"),
   191  	dup("func()"),
   192  	dup("func(int, float32) string"),
   193  	dup("interface{m()}"),
   194  	dup("interface{m() string; n(x int)}"),
   195  	dup("interface{~int}"),
   196  	dup("interface{~int | ~float64 | ~string}"),
   197  	dup("interface{~int; m()}"),
   198  	dup("interface{~int | ~float64 | ~string; m() string; n(x int)}"),
   199  	dup("map[string]int"),
   200  	dup("chan E"),
   201  	dup("<-chan E"),
   202  	dup("chan<- E"),
   203  
   204  	// new interfaces
   205  	dup("interface{int}"),
   206  	dup("interface{~int}"),
   207  
   208  	// generic constraints
   209  	dup("interface{~a | ~b | ~c; ~int | ~string; float64; m()}"),
   210  	dup("interface{int | string}"),
   211  	dup("interface{~int | ~string; float64; m()}"),
   212  	dup("interface{~T[int, string] | string}"),
   213  
   214  	// generic types
   215  	dup("x[T]"),
   216  	dup("x[N | A | S]"),
   217  	dup("x[N, A]"),
   218  
   219  	// non-type expressions
   220  	dup("(x)"),
   221  	dup("x.f"),
   222  	dup("a[i]"),
   223  
   224  	dup("s[:]"),
   225  	dup("s[i:]"),
   226  	dup("s[:j]"),
   227  	dup("s[i:j]"),
   228  	dup("s[:j:k]"),
   229  	dup("s[i:j:k]"),
   230  
   231  	dup("x.(T)"),
   232  
   233  	dup("x.([10]int)"),
   234  	dup("x.([...]int)"),
   235  
   236  	dup("x.(struct{})"),
   237  	dup("x.(struct{x int; y, z float32; E})"),
   238  
   239  	dup("x.(func())"),
   240  	dup("x.(func(x int))"),
   241  	dup("x.(func() int)"),
   242  	dup("x.(func(x, y int, z float32) (r int))"),
   243  	dup("x.(func(a, b, c int))"),
   244  	dup("x.(func(x ...T))"),
   245  
   246  	dup("x.(interface{})"),
   247  	dup("x.(interface{m(); n(x int); E})"),
   248  	dup("x.(interface{m(); n(x int) T; E; F})"),
   249  
   250  	dup("x.(map[K]V)"),
   251  
   252  	dup("x.(chan E)"),
   253  	dup("x.(<-chan E)"),
   254  	dup("x.(chan<- chan int)"),
   255  	dup("x.(chan<- <-chan int)"),
   256  	dup("x.(<-chan chan int)"),
   257  	dup("x.(chan (<-chan int))"),
   258  
   259  	dup("f()"),
   260  	dup("f(x)"),
   261  	dup("int(x)"),
   262  	dup("f(x, x + y)"),
   263  	dup("f(s...)"),
   264  	dup("f(a, s...)"),
   265  
   266  	// generic functions
   267  	dup("f[T]()"),
   268  	dup("f[T](T)"),
   269  	dup("f[T, T1]()"),
   270  	dup("f[T, T1](T, T1)"),
   271  
   272  	dup("*x"),
   273  	dup("&x"),
   274  	dup("x + y"),
   275  	dup("x + y << (2 * s)"),
   276  }
   277  
   278  func TestShortString(t *testing.T) {
   279  	for _, test := range exprTests {
   280  		src := "package p; var _ = " + test[0]
   281  		ast, err := Parse(nil, strings.NewReader(src), nil, nil, 0)
   282  		if err != nil {
   283  			t.Errorf("%s: %s", test[0], err)
   284  			continue
   285  		}
   286  		x := ast.DeclList[0].(*VarDecl).Values
   287  		if got := String(x); got != test[1] {
   288  			t.Errorf("%s: got %s, want %s", test[0], got, test[1])
   289  		}
   290  	}
   291  }
   292  

View as plain text