aboutsummaryrefslogtreecommitdiff
path: root/resolve/testdata/resolve.star
diff options
context:
space:
mode:
Diffstat (limited to 'resolve/testdata/resolve.star')
-rw-r--r--resolve/testdata/resolve.star383
1 files changed, 383 insertions, 0 deletions
diff --git a/resolve/testdata/resolve.star b/resolve/testdata/resolve.star
new file mode 100644
index 0000000..ce67110
--- /dev/null
+++ b/resolve/testdata/resolve.star
@@ -0,0 +1,383 @@
+# Tests of resolver errors.
+#
+# The initial environment contains the predeclared names "M"
+# (module-specific) and "U" (universal). This distinction
+# should be unobservable to the Starlark program.
+
+# use of declared global
+x = 1
+_ = x
+
+---
+# premature use of global is not a static error;
+# see github.com/google/skylark/issues/116.
+_ = x
+x = 1
+
+---
+# use of undefined global
+_ = x ### "undefined: x"
+
+---
+# redeclaration of global
+x = 1
+x = 2 ### "cannot reassign global x declared at .*resolve.star:23:1"
+
+---
+# Redeclaration of predeclared names is allowed.
+#
+# This rule permits tool maintainers to add members to the predeclared
+# environment without breaking existing programs.
+
+# module-specific predeclared name
+M = 1 # ok
+M = 2 ### "cannot reassign global M declared at .*/resolve.star"
+
+# universal predeclared name
+U = 1 # ok
+U = 1 ### "cannot reassign global U declared at .*/resolve.star"
+
+---
+# A global declaration shadows all references to a predeclared;
+# see github.com/google/skylark/issues/116.
+
+a = U # ok: U is a reference to the global defined on the next line.
+U = 1
+
+---
+# reference to predeclared name
+M()
+
+---
+# locals may be referenced before they are defined
+
+def f():
+ M(x) # dynamic error
+ x = 1
+
+---
+# Various forms of assignment:
+
+def f(x): # parameter
+ M(x)
+ M(y) ### "undefined: y"
+
+(a, b) = 1, 2
+M(a)
+M(b)
+M(c) ### "undefined: c"
+
+[p, q] = 1, 2
+M(p)
+M(q)
+M(r) ### "undefined: r"
+
+---
+# a comprehension introduces a separate lexical block
+
+_ = [x for x in "abc"]
+M(x) ### "undefined: x"
+
+---
+# Functions may have forward refs.
+def f():
+ g()
+ h() ### "undefined: h"
+ def inner():
+ i()
+ i = lambda: 0
+
+def g():
+ f()
+
+---
+# It is not permitted to rebind a global using a += assignment.
+
+x = [1]
+x.extend([2]) # ok
+x += [3] ### `cannot reassign global x`
+
+def f():
+ x += [4] # x is local to f
+
+y = 1
+y += 2 ### `cannot reassign global y`
+z += 3 # ok (but fails dynamically because z is undefined)
+
+---
+def f(a):
+ if 1==1:
+ b = 1
+ c = 1
+ M(a) # ok: param
+ M(b) # ok: maybe bound local
+ M(c) # ok: bound local
+ M(d) # NB: we don't do a use-before-def check on local vars!
+ M(e) # ok: global
+ M(f) # ok: global
+ d = 1
+
+e = 1
+
+---
+# This program should resolve successfully but fail dynamically.
+x = 1
+
+def f():
+ M(x) # dynamic error: reference to undefined local
+ x = 2
+
+f()
+
+---
+load("module", "name") # ok
+
+def f():
+ load("foo", "bar") ### "load statement within a function"
+
+load("foo",
+ "", ### "load: empty identifier"
+ "_a", ### "load: names with leading underscores are not exported: _a"
+ b="", ### "load: empty identifier"
+ c="_d", ### "load: names with leading underscores are not exported: _d"
+ _e="f") # ok
+
+---
+# option:globalreassign
+if M:
+ load("foo", "bar") ### "load statement within a conditional"
+
+---
+# option:globalreassign
+for x in M:
+ load("foo", "bar") ### "load statement within a loop"
+
+---
+# option:recursion option:globalreassign
+while M:
+ load("foo", "bar") ### "load statement within a loop"
+
+---
+# return statements must be within a function
+
+return ### "return statement not within a function"
+
+---
+# if-statements and for-loops at top-level are forbidden
+# (without globalreassign option)
+
+for x in "abc": ### "for loop not within a function"
+ pass
+
+if x: ### "if statement not within a function"
+ pass
+
+---
+# option:globalreassign
+
+for x in "abc": # ok
+ pass
+
+if x: # ok
+ pass
+
+---
+# while loops are forbidden (without -recursion option)
+
+def f():
+ while U: ### "dialect does not support while loops"
+ pass
+
+---
+# option:recursion
+
+def f():
+ while U: # ok
+ pass
+
+while U: ### "while loop not within a function"
+ pass
+
+---
+# option:globalreassign option:recursion
+
+while U: # ok
+ pass
+
+---
+# The parser allows any expression on the LHS of an assignment.
+
+1 = 0 ### "can't assign to literal"
+1+2 = 0 ### "can't assign to binaryexpr"
+f() = 0 ### "can't assign to callexpr"
+
+[a, b] = 0
+[c, d] += 0 ### "can't use list expression in augmented assignment"
+(e, f) += 0 ### "can't use tuple expression in augmented assignment"
+
+[] = 0 # ok
+() = 0 # ok
+
+---
+# break and continue statements must appear within a loop
+
+break ### "break not in a loop"
+
+continue ### "continue not in a loop"
+
+pass
+
+---
+# Positional arguments (and required parameters)
+# must appear before named arguments (and optional parameters).
+
+M(x=1, 2) ### `positional argument may not follow named`
+
+def f(x=1, y): pass ### `required parameter may not follow optional`
+---
+# No parameters may follow **kwargs in a declaration.
+
+def f(**kwargs, x): ### `parameter may not follow \*\*kwargs`
+ pass
+
+def g(**kwargs, *args): ### `\* parameter may not follow \*\*kwargs`
+ pass
+
+def h(**kwargs1, **kwargs2): ### `multiple \*\* parameters not allowed`
+ pass
+
+---
+# Only keyword-only params and **kwargs may follow *args in a declaration.
+
+def f(*args, x): # ok
+ pass
+
+def g(*args1, *args2): ### `multiple \* parameters not allowed`
+ pass
+
+def h(*, ### `bare \* must be followed by keyword-only parameters`
+ *): ### `multiple \* parameters not allowed`
+ pass
+
+def i(*args, *): ### `multiple \* parameters not allowed`
+ pass
+
+def j(*, ### `bare \* must be followed by keyword-only parameters`
+ *args): ### `multiple \* parameters not allowed`
+ pass
+
+def k(*, **kwargs): ### `bare \* must be followed by keyword-only parameters`
+ pass
+
+def l(*): ### `bare \* must be followed by keyword-only parameters`
+ pass
+
+def m(*args, a=1, **kwargs): # ok
+ pass
+
+def n(*, a=1, **kwargs): # ok
+ pass
+
+---
+# No arguments may follow **kwargs in a call.
+def f(*args, **kwargs):
+ pass
+
+f(**{}, 1) ### `argument may not follow \*\*kwargs`
+f(**{}, x=1) ### `argument may not follow \*\*kwargs`
+f(**{}, *[]) ### `\*args may not follow \*\*kwargs`
+f(**{}, **{}) ### `multiple \*\*kwargs not allowed`
+
+---
+# Only **kwargs may follow *args in a call.
+def f(*args, **kwargs):
+ pass
+
+f(*[], 1) ### `positional argument may not follow \*args`
+f(*[], a=1) ### `keyword argument may not follow \*args`
+f(*[], *[]) ### `multiple \*args not allowed`
+f(*[], **{}) # ok
+
+---
+# Parameter names must be unique.
+
+def f(a, b, a): pass ### "duplicate parameter: a"
+def g(args, b, *args): pass ### "duplicate parameter: args"
+def h(kwargs, a, **kwargs): pass ### "duplicate parameter: kwargs"
+def i(*x, **x): pass ### "duplicate parameter: x"
+
+---
+# Floating-point support is now standard.
+a = float("3.141")
+b = 1 / 2
+c = 3.141
+
+---
+# option:globalreassign
+# Legacy Bazel (and Python) semantics: def must precede use even for globals.
+
+_ = x ### `undefined: x`
+x = 1
+
+---
+# option:globalreassign
+# Legacy Bazel (and Python) semantics: reassignment of globals is allowed.
+x = 1
+x = 2 # ok
+
+---
+# option:globalreassign
+# Redeclaration of predeclared names is allowed.
+
+# module-specific predeclared name
+M = 1 # ok
+M = 2 # ok (legacy)
+
+# universal predeclared name
+U = 1 # ok
+U = 1 # ok (legacy)
+
+---
+# https://github.com/bazelbuild/starlark/starlark/issues/21
+def f(**kwargs): pass
+f(a=1, a=1) ### `keyword argument a repeated`
+
+
+---
+# spelling
+
+print = U
+
+hello = 1
+print(hollo) ### `undefined: hollo \(did you mean hello\?\)`
+
+def f(abc):
+ print(abd) ### `undefined: abd \(did you mean abc\?\)`
+ print(goodbye) ### `undefined: goodbye$`
+
+---
+load("module", "x") # ok
+x = 1 ### `cannot reassign local x`
+load("module", "x") ### `cannot reassign top-level x`
+
+---
+# option:loadbindsglobally
+load("module", "x") # ok
+x = 1 ### `cannot reassign global x`
+load("module", "x") ### `cannot reassign global x`
+
+---
+# option:globalreassign
+load("module", "x") # ok
+x = 1 # ok
+load("module", "x") # ok
+
+---
+# option:globalreassign option:loadbindsglobally
+load("module", "x") # ok
+x = 1
+load("module", "x") # ok
+
+---
+_ = x # forward ref to file-local
+load("module", "x") # ok