mirror of https://github.com/golang/go.git
228 lines
5.0 KiB
Go
228 lines
5.0 KiB
Go
// Copyright 2016 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 syntax
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestPrint(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("skipping test in short mode")
|
|
}
|
|
|
|
// provide a no-op error handler so parsing doesn't stop after first error
|
|
ast, err := ParseFile(*src_, func(error) {}, nil, 0)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
if ast != nil {
|
|
Fprint(testOut(), ast, LineForm)
|
|
fmt.Println()
|
|
}
|
|
}
|
|
|
|
type shortBuffer struct {
|
|
buf []byte
|
|
}
|
|
|
|
func (w *shortBuffer) Write(data []byte) (n int, err error) {
|
|
w.buf = append(w.buf, data...)
|
|
n = len(data)
|
|
if len(w.buf) > 10 {
|
|
err = io.ErrShortBuffer
|
|
}
|
|
return
|
|
}
|
|
|
|
func TestPrintError(t *testing.T) {
|
|
const src = "package p; var x int"
|
|
ast, err := Parse(nil, strings.NewReader(src), nil, nil, 0)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var buf shortBuffer
|
|
_, err = Fprint(&buf, ast, 0)
|
|
if err == nil || err != io.ErrShortBuffer {
|
|
t.Errorf("got err = %s, want %s", err, io.ErrShortBuffer)
|
|
}
|
|
}
|
|
|
|
var stringTests = []string{
|
|
"package p",
|
|
"package p; type _ int; type T1 = struct{}; type ( _ *struct{}; T2 = float32 )",
|
|
|
|
// generic type declarations
|
|
"package p; type _[T any] struct{}",
|
|
"package p; type _[A, B, C interface{m()}] struct{}",
|
|
"package p; type _[T any, A, B, C interface{m()}, X, Y, Z interface{type int}] struct{}",
|
|
|
|
// generic function declarations
|
|
"package p; func _[T any]()",
|
|
"package p; func _[A, B, C interface{m()}]()",
|
|
"package p; func _[T any, A, B, C interface{m()}, X, Y, Z interface{type int}]()",
|
|
|
|
// methods with generic receiver types
|
|
"package p; func (R[T]) _()",
|
|
"package p; func (*R[A, B, C]) _()",
|
|
"package p; func (_ *R[A, B, C]) _()",
|
|
|
|
// channels
|
|
"package p; type _ chan chan int",
|
|
"package p; type _ chan (<-chan int)",
|
|
"package p; type _ chan chan<- int",
|
|
|
|
"package p; type _ <-chan chan int",
|
|
"package p; type _ <-chan <-chan int",
|
|
"package p; type _ <-chan chan<- int",
|
|
|
|
"package p; type _ chan<- chan int",
|
|
"package p; type _ chan<- <-chan int",
|
|
"package p; type _ chan<- chan<- int",
|
|
|
|
// TODO(gri) expand
|
|
}
|
|
|
|
func TestPrintString(t *testing.T) {
|
|
for _, want := range stringTests {
|
|
ast, err := Parse(nil, strings.NewReader(want), nil, nil, AllowGenerics)
|
|
if err != nil {
|
|
t.Error(err)
|
|
continue
|
|
}
|
|
if got := String(ast); got != want {
|
|
t.Errorf("%q: got %q", want, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testOut() io.Writer {
|
|
if testing.Verbose() {
|
|
return os.Stdout
|
|
}
|
|
return ioutil.Discard
|
|
}
|
|
|
|
func dup(s string) [2]string { return [2]string{s, s} }
|
|
|
|
var exprTests = [][2]string{
|
|
// basic type literals
|
|
dup("x"),
|
|
dup("true"),
|
|
dup("42"),
|
|
dup("3.1415"),
|
|
dup("2.71828i"),
|
|
dup(`'a'`),
|
|
dup(`"foo"`),
|
|
dup("`bar`"),
|
|
|
|
// func and composite literals
|
|
dup("func() {}"),
|
|
dup("[]int{}"),
|
|
{"func(x int) complex128 { return 0 }", "func(x int) complex128 {…}"},
|
|
{"[]int{1, 2, 3}", "[]int{…}"},
|
|
|
|
// type expressions
|
|
dup("[1 << 10]byte"),
|
|
dup("[]int"),
|
|
dup("*int"),
|
|
dup("struct{x int}"),
|
|
dup("func()"),
|
|
dup("func(int, float32) string"),
|
|
dup("interface{m()}"),
|
|
dup("interface{m() string; n(x int)}"),
|
|
dup("interface{type int}"),
|
|
dup("interface{type int, float64, string}"),
|
|
dup("interface{type int; m()}"),
|
|
dup("interface{type int, float64, string; m() string; n(x int)}"),
|
|
dup("map[string]int"),
|
|
dup("chan E"),
|
|
dup("<-chan E"),
|
|
dup("chan<- E"),
|
|
|
|
// new interfaces
|
|
dup("interface{int}"),
|
|
dup("interface{~int}"),
|
|
dup("interface{~int}"),
|
|
dup("interface{int | string}"),
|
|
dup("interface{~int | ~string; float64; m()}"),
|
|
dup("interface{type a, b, c; ~int | ~string; float64; m()}"),
|
|
dup("interface{~T[int, string] | string}"),
|
|
|
|
// non-type expressions
|
|
dup("(x)"),
|
|
dup("x.f"),
|
|
dup("a[i]"),
|
|
|
|
dup("s[:]"),
|
|
dup("s[i:]"),
|
|
dup("s[:j]"),
|
|
dup("s[i:j]"),
|
|
dup("s[:j:k]"),
|
|
dup("s[i:j:k]"),
|
|
|
|
dup("x.(T)"),
|
|
|
|
dup("x.([10]int)"),
|
|
dup("x.([...]int)"),
|
|
|
|
dup("x.(struct{})"),
|
|
dup("x.(struct{x int; y, z float32; E})"),
|
|
|
|
dup("x.(func())"),
|
|
dup("x.(func(x int))"),
|
|
dup("x.(func() int)"),
|
|
dup("x.(func(x, y int, z float32) (r int))"),
|
|
dup("x.(func(a, b, c int))"),
|
|
dup("x.(func(x ...T))"),
|
|
|
|
dup("x.(interface{})"),
|
|
dup("x.(interface{m(); n(x int); E})"),
|
|
dup("x.(interface{m(); n(x int) T; E; F})"),
|
|
|
|
dup("x.(map[K]V)"),
|
|
|
|
dup("x.(chan E)"),
|
|
dup("x.(<-chan E)"),
|
|
dup("x.(chan<- chan int)"),
|
|
dup("x.(chan<- <-chan int)"),
|
|
dup("x.(<-chan chan int)"),
|
|
dup("x.(chan (<-chan int))"),
|
|
|
|
dup("f()"),
|
|
dup("f(x)"),
|
|
dup("int(x)"),
|
|
dup("f(x, x + y)"),
|
|
dup("f(s...)"),
|
|
dup("f(a, s...)"),
|
|
|
|
dup("*x"),
|
|
dup("&x"),
|
|
dup("x + y"),
|
|
dup("x + y << (2 * s)"),
|
|
}
|
|
|
|
func TestShortString(t *testing.T) {
|
|
for _, test := range exprTests {
|
|
src := "package p; var _ = " + test[0]
|
|
ast, err := Parse(nil, strings.NewReader(src), nil, nil, AllowGenerics)
|
|
if err != nil {
|
|
t.Errorf("%s: %s", test[0], err)
|
|
continue
|
|
}
|
|
x := ast.DeclList[0].(*VarDecl).Values
|
|
if got := String(x); got != test[1] {
|
|
t.Errorf("%s: got %s, want %s", test[0], got, test[1])
|
|
}
|
|
}
|
|
}
|