EvalException can now show a url for additional information Add doc for the "read only" error message. -- MOS_MIGRATED_REVID=138194709
diff --git a/site/versions/master/docs/skylark/errors/read-only-variable.md b/site/versions/master/docs/skylark/errors/read-only-variable.md new file mode 100644 index 0000000..4b1ecce --- /dev/null +++ b/site/versions/master/docs/skylark/errors/read-only-variable.md
@@ -0,0 +1,26 @@ +# Variable x is read only + +A global variable cannot be reassigned. It will always point to the same object. +However, its content might change, if the value is mutable (for example, the +content of a list). Local variables don't have this restriction. + +```python +a = [1, 2] + +a[1] = 3 + +b = 3 + +b = 4 # forbidden +``` + +`ERROR: /path/ext.bzl:7:1: Variable b is read only` + +You will get a similar error if you try to redefine a function (function +overloading is not supported), for example: + +```python +def foo(x): return x + 1 + +def foo(x, y): return x + y # forbidden +```
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/EvalException.java b/src/main/java/com/google/devtools/build/lib/syntax/EvalException.java index 97d695f..ed91459 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/EvalException.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/EvalException.java
@@ -51,6 +51,16 @@ this.dueToIncompleteAST = false; } + public EvalException(Location location, String message, String url) { + this.location = location; + this.dueToIncompleteAST = false; + this.message = + Preconditions.checkNotNull(message) + + "\n" + + "Need help? See " + + Preconditions.checkNotNull(url); + } + /** * @param location the location where evaluation/execution failed. * @param message the error message.
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java b/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java index c1a94c5..6aa5a7d 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java
@@ -90,7 +90,10 @@ private void checkReadonly(String varname, Location location) throws EvalException { if (readOnlyVariables.contains(varname)) { - throw new EvalException(location, String.format("Variable %s is read only", varname)); + throw new EvalException( + location, + String.format("Variable %s is read only", varname), + "https://bazel.build/versions/master/docs/skylark/errors/read-only-variable.html"); } }
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java b/src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java index 6c8cbd7..f303082 100644 --- a/src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java +++ b/src/test/java/com/google/devtools/build/lib/syntax/EnvironmentTest.java
@@ -301,7 +301,7 @@ env.eval("special_var = 41"); throw new AssertionError("failed to fail"); } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("ERROR 1:1: Variable special_var is read only"); + assertThat(e.getMessage()).contains("ERROR 1:1: Variable special_var is read only"); } try {
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java index bd029849..c383ae91 100644 --- a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java +++ b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java
@@ -463,7 +463,7 @@ @Test public void testListComprehensionModifiesGlobalEnv() throws Exception { - new SkylarkTest().update("x", 42).testIfExactError("ERROR 1:1: Variable x is read only", + new SkylarkTest().update("x", 42).testIfErrorContains("ERROR 1:1: Variable x is read only", "[x + 1 for x in [1,2,3]]"); new BuildTest().update("x", 42).setUp("y =[x + 1 for x in [1,2,3]]") .testExactOrder("y", 2, 3, 4).testLookup("x", 3); // (x is global)