}
}
if len(sizes) == 2 && sizes[0] > sizes[1] {
- check.errorf(call.Args[1], SwappedMakeArgs, invalidArg+"length and capacity swapped")
+ check.error(call.Args[1], SwappedMakeArgs, invalidArg+"length and capacity swapped")
// safe to continue
}
x.mode = value
case _Add:
// unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer
if !check.allowVersion(check.pkg, 1, 17) {
- check.errorf(call.Fun, UnsupportedFeature, "unsafe.Add requires go1.17 or later")
+ check.error(call.Fun, UnsupportedFeature, "unsafe.Add requires go1.17 or later")
return
}
case _Slice:
// unsafe.Slice(ptr *T, len IntegerType) []T
if !check.allowVersion(check.pkg, 1, 17) {
- check.errorf(call.Fun, UnsupportedFeature, "unsafe.Slice requires go1.17 or later")
+ check.error(call.Fun, UnsupportedFeature, "unsafe.Slice requires go1.17 or later")
return
}
case _SliceData:
// unsafe.SliceData(slice []T) *T
if !check.allowVersion(check.pkg, 1, 20) {
- check.errorf(call.Fun, UnsupportedFeature, "unsafe.SliceData requires go1.20 or later")
+ check.error(call.Fun, UnsupportedFeature, "unsafe.SliceData requires go1.20 or later")
return
}
case _String:
// unsafe.String(ptr *byte, len IntegerType) string
if !check.allowVersion(check.pkg, 1, 20) {
- check.errorf(call.Fun, UnsupportedFeature, "unsafe.String requires go1.20 or later")
+ check.error(call.Fun, UnsupportedFeature, "unsafe.String requires go1.20 or later")
return
}
case _StringData:
// unsafe.StringData(str string) *byte
if !check.allowVersion(check.pkg, 1, 20) {
- check.errorf(call.Fun, UnsupportedFeature, "unsafe.StringData requires go1.20 or later")
+ check.error(call.Fun, UnsupportedFeature, "unsafe.StringData requires go1.20 or later")
return
}
if name != "_" {
pkg.name = name
} else {
- check.errorf(file.Name, BlankPkgName, "invalid package name _")
+ check.error(file.Name, BlankPkgName, "invalid package name _")
}
fallthrough
// alias declaration
if alias {
if !check.allowVersion(check.pkg, 1, 9) {
- check.errorf(atPos(tdecl.Assign), UnsupportedFeature, "type aliases requires go1.9 or later")
+ check.error(atPos(tdecl.Assign), UnsupportedFeature, "type aliases requires go1.9 or later")
}
check.brokenAlias(obj)
--- /dev/null
+// Copyright 2021 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 ast.
+
+package types_test
+
+import (
+ "go/ast"
+ "go/token"
+ "testing"
+)
+
+const errorfMinArgCount = 4
+
+// TestErrorCalls makes sure that check.errorf calls have at least
+// errorfMinArgCount arguments (otherwise we should use check.error).
+func TestErrorCalls(t *testing.T) {
+ fset := token.NewFileSet()
+ files, err := pkgFiles(fset, ".", 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for _, file := range files {
+ ast.Inspect(file, func(n ast.Node) bool {
+ call, _ := n.(*ast.CallExpr)
+ if call == nil {
+ return true
+ }
+ selx, _ := call.Fun.(*ast.SelectorExpr)
+ if selx == nil {
+ return true
+ }
+ if !(isName(selx.X, "check") && isName(selx.Sel, "errorf")) {
+ return true
+ }
+ // check.errorf calls should have at least errorfMinArgCount arguments:
+ // position, code, format string, and arguments to format
+ if n := len(call.Args); n < errorfMinArgCount {
+ t.Errorf("%s: got %d arguments, want at least %d", fset.Position(call.Pos()), n, errorfMinArgCount)
+ return false
+ }
+ return true
+ })
+ }
+}
+
+func isName(n ast.Node, name string) bool {
+ if n, ok := n.(*ast.Ident); ok {
+ return n.Name == name
+ }
+ return false
+}
// TODO(gri) We should report exactly what went wrong. At the
// moment we don't have the (go/constant) API for that.
// See also TODO in go/constant/value.go.
- check.errorf(atPos(opPos), InvalidConstVal, "constant result is not representable")
+ check.error(atPos(opPos), InvalidConstVal, "constant result is not representable")
return
}
if op == token.QUO || op == token.REM {
// check for zero divisor
if (x.mode == constant_ || allInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 {
- check.errorf(&y, DivByZero, invalidOp+"division by zero")
+ check.error(&y, DivByZero, invalidOp+"division by zero")
x.mode = invalid
return
}
re, im := constant.Real(y.val), constant.Imag(y.val)
re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im)
if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 {
- check.errorf(&y, DivByZero, invalidOp+"division by zero")
+ check.error(&y, DivByZero, invalidOp+"division by zero")
x.mode = invalid
return
}
case *ast.KeyValueExpr:
// key:value expressions are handled in composite literals
- check.errorf(e, InvalidSyntaxTree, invalidAST+"no key:value expected")
+ check.error(e, InvalidSyntaxTree, invalidAST+"no key:value expected")
goto Error
case *ast.ArrayType, *ast.StructType, *ast.FuncType,
if at == nil {
at = e // e.Index[2] should be present but be careful
}
- check.errorf(at, InvalidSliceExpr, invalidOp+"3-index slice of string")
+ check.error(at, InvalidSliceExpr, invalidOp+"3-index slice of string")
x.mode = invalid
return
}
// spec: "Only the first index may be omitted; it defaults to 0."
if e.Slice3 && (e.High == nil || e.Max == nil) {
- check.errorf(inNode(e, e.Rbrack), InvalidSyntaxTree, invalidAST+"2nd and 3rd index required in 3-index slice")
+ check.error(inNode(e, e.Rbrack), InvalidSyntaxTree, invalidAST+"2nd and 3rd index required in 3-index slice")
x.mode = invalid
return
}
}
if len(expr.Indices) > 1 {
// TODO(rFindley) should this get a distinct error code?
- check.errorf(expr.Indices[1], InvalidIndex, invalidOp+"more than one index")
+ check.error(expr.Indices[1], InvalidIndex, invalidOp+"more than one index")
}
return expr.Indices[0]
}
// We have a method with name f.Names[0].
name := f.Names[0]
if name.Name == "_" {
- check.errorf(name, BlankIfaceMethod, "methods must have a unique non-blank name")
+ check.error(name, BlankIfaceMethod, "methods must have a unique non-blank name")
continue // ignore
}
if ftyp, _ := f.Type.(*ast.FuncType); ftyp != nil && ftyp.TypeParams != nil {
at = ftyp.TypeParams
}
- check.errorf(at, InvalidMethodTypeParams, "methods cannot have type parameters")
+ check.error(at, InvalidMethodTypeParams, "methods cannot have type parameters")
}
// use named receiver type if available (for better error messages)
// TODO(mdempsky): Pivot stack so we report the cycle from the top?
obj0 := check.mono.vertices[v].obj
- check.errorf(obj0, InvalidInstanceCycle, "instantiation cycle:")
+ check.error(obj0, InvalidInstanceCycle, "instantiation cycle:")
qf := RelativeTo(check.pkg)
for _, v := range stack {
case init == nil && r == 0:
// var decl w/o init expr
if s.Type == nil {
- check.errorf(s, code, "missing type or init expr")
+ check.error(s, code, "missing type or init expr")
}
case l < r:
if l < len(s.Values) {
// spec: "A package-scope or file-scope identifier with name init
// may only be declared to be a function with this (func()) signature."
if ident.Name == "init" {
- check.errorf(ident, InvalidInitDecl, "cannot declare init - must be func")
+ check.error(ident, InvalidInitDecl, "cannot declare init - must be func")
return
}
// spec: "The main package must have package name main and declare
// a function main that takes no arguments and returns no value."
if ident.Name == "main" && check.pkg.name == "main" {
- check.errorf(ident, InvalidMainDecl, "cannot declare main - must be func")
+ check.error(ident, InvalidMainDecl, "cannot declare main - must be func")
return
}
name = d.spec.Name.Name
if path == "C" {
// match 1.17 cmd/compile (not prescribed by spec)
- check.errorf(d.spec.Name, ImportCRenamed, `cannot rename import "C"`)
+ check.error(d.spec.Name, ImportCRenamed, `cannot rename import "C"`)
return
}
}
if name == "init" {
- check.errorf(d.spec, InvalidInitDecl, "cannot import package as init - init must be a func")
+ check.error(d.spec, InvalidInitDecl, "cannot import package as init - init must be a func")
return
}
case *ast.BadExpr:
// ignore - error already reported by parser
case nil:
- check.errorf(ix.Orig, InvalidSyntaxTree, invalidAST+"parameterized receiver contains nil parameters")
+ check.error(ix.Orig, InvalidSyntaxTree, invalidAST+"parameterized receiver contains nil parameters")
default:
check.errorf(arg, BadDecl, "receiver type parameter %s must be an identifier", arg)
}
// (A separate check is needed when type-checking interface method signatures because
// they don't have a receiver specification.)
if recvPar != nil {
- check.errorf(ftyp.TypeParams, InvalidMethodTypeParams, "methods cannot have type parameters")
+ check.error(ftyp.TypeParams, InvalidMethodTypeParams, "methods cannot have type parameters")
}
}
// named parameter
for _, name := range field.Names {
if name.Name == "" {
- check.errorf(name, InvalidSyntaxTree, invalidAST+"anonymous parameter")
+ check.error(name, InvalidSyntaxTree, invalidAST+"anonymous parameter")
// ok to continue
}
par := NewParam(name.Pos(), check.pkg, name.Name, typ)
}
if named && anonymous {
- check.errorf(list, InvalidSyntaxTree, invalidAST+"list contains both named and anonymous parameters")
+ check.error(list, InvalidSyntaxTree, invalidAST+"list contains both named and anonymous parameters")
// ok to continue
}
d = s
}
default:
- check.errorf(s, InvalidSyntaxTree, invalidAST+"case/communication clause expected")
+ check.error(s, InvalidSyntaxTree, invalidAST+"case/communication clause expected")
}
if d != nil {
if first != nil {
switch s.Tok {
case token.ASSIGN, token.DEFINE:
if len(s.Lhs) == 0 {
- check.errorf(s, InvalidSyntaxTree, invalidAST+"missing lhs in assignment")
+ check.error(s, InvalidSyntaxTree, invalidAST+"missing lhs in assignment")
return
}
if s.Tok == token.DEFINE {
case *ast.IfStmt, *ast.BlockStmt:
check.stmt(inner, s.Else)
default:
- check.errorf(s.Else, InvalidSyntaxTree, invalidAST+"invalid else branch in if statement")
+ check.error(s.Else, InvalidSyntaxTree, invalidAST+"invalid else branch in if statement")
}
case *ast.SwitchStmt:
for i, c := range s.Body.List {
clause, _ := c.(*ast.CaseClause)
if clause == nil {
- check.errorf(c, InvalidSyntaxTree, invalidAST+"incorrect expression switch case")
+ check.error(c, InvalidSyntaxTree, invalidAST+"incorrect expression switch case")
continue
}
check.caseValues(&x, clause.List, seen)
rhs = guard.X
case *ast.AssignStmt:
if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 {
- check.errorf(s, InvalidSyntaxTree, invalidAST+"incorrect form of type switch guard")
+ check.error(s, InvalidSyntaxTree, invalidAST+"incorrect form of type switch guard")
return
}
lhs, _ = guard.Lhs[0].(*ast.Ident)
if lhs == nil {
- check.errorf(s, InvalidSyntaxTree, invalidAST+"incorrect form of type switch guard")
+ check.error(s, InvalidSyntaxTree, invalidAST+"incorrect form of type switch guard")
return
}
rhs = guard.Rhs[0]
default:
- check.errorf(s, InvalidSyntaxTree, invalidAST+"incorrect form of type switch guard")
+ check.error(s, InvalidSyntaxTree, invalidAST+"incorrect form of type switch guard")
return
}
// rhs must be of the form: expr.(type) and expr must be an ordinary interface
expr, _ := rhs.(*ast.TypeAssertExpr)
if expr == nil || expr.Type != nil {
- check.errorf(s, InvalidSyntaxTree, invalidAST+"incorrect form of type switch guard")
+ check.error(s, InvalidSyntaxTree, invalidAST+"incorrect form of type switch guard")
return
}
var x operand
for _, s := range s.Body.List {
clause, _ := s.(*ast.CaseClause)
if clause == nil {
- check.errorf(s, InvalidSyntaxTree, invalidAST+"incorrect type switch case")
+ check.error(s, InvalidSyntaxTree, invalidAST+"incorrect type switch case")
continue
}
// Check each type in this type switch case.
check.stmt(inner, s.Body)
default:
- check.errorf(s, InvalidSyntaxTree, invalidAST+"invalid statement")
+ check.error(s, InvalidSyntaxTree, invalidAST+"invalid statement")
}
}
}
if obj == universeIota {
if check.iota == nil {
- check.errorf(e, InvalidIota, "cannot use iota outside constant declaration")
+ check.error(e, InvalidIota, "cannot use iota outside constant declaration")
return
}
x.val = check.iota
}
// len(s) > 2
if strings.Contains(s, "_") {
- check.errorf(lit, UnsupportedFeature, "underscores in numeric literals requires go1.13 or later")
+ check.error(lit, UnsupportedFeature, "underscores in numeric literals requires go1.13 or later")
return
}
if s[0] != '0' {
}
radix := s[1]
if radix == 'b' || radix == 'B' {
- check.errorf(lit, UnsupportedFeature, "binary literals requires go1.13 or later")
+ check.error(lit, UnsupportedFeature, "binary literals requires go1.13 or later")
return
}
if radix == 'o' || radix == 'O' {
- check.errorf(lit, UnsupportedFeature, "0o/0O-style octal literals requires go1.13 or later")
+ check.error(lit, UnsupportedFeature, "0o/0O-style octal literals requires go1.13 or later")
return
}
if lit.Kind != token.INT && (radix == 'x' || radix == 'X') {
- check.errorf(lit, UnsupportedFeature, "hexadecimal floating-point literals requires go1.13 or later")
+ check.error(lit, UnsupportedFeature, "hexadecimal floating-point literals requires go1.13 or later")
}
}