aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools
diff options
context:
space:
mode:
authorGravatar laurentlb <laurentlb@google.com>2017-06-23 16:05:36 +0200
committerGravatar Marcel Hlopko <hlopko@google.com>2017-06-26 18:31:30 +0200
commit8880cf221e7124c0444178438d40d618e7c000ad (patch)
tree9f82d50d78c5da506241f80ee8cfc63622ccf76e /src/main/java/com/google/devtools
parentc32efc8375cf482e795a43ecf4f009971722e71a (diff)
Forbid duplicate keys in dictionary literals
RELNOTES: When using the dictionary literal syntax, it is now an error to have duplicated keys (e.g. {'ab': 3, 'ab': 5}). PiperOrigin-RevId: 159945431
Diffstat (limited to 'src/main/java/com/google/devtools')
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/DictionaryLiteral.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/SkylarkDict.java44
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/SkylarkSemanticsOptions.java8
3 files changed, 34 insertions, 25 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/DictionaryLiteral.java b/src/main/java/com/google/devtools/build/lib/syntax/DictionaryLiteral.java
index 87756990ae..c2328b190c 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/DictionaryLiteral.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/DictionaryLiteral.java
@@ -72,11 +72,12 @@ public final class DictionaryLiteral extends Expression {
SkylarkDict<Object, Object> dict = SkylarkDict.<Object, Object>of(env);
Location loc = getLocation();
for (DictionaryEntryLiteral entry : entries) {
- if (entry == null) {
- throw new EvalException(loc, "null expression in " + this);
- }
Object key = entry.key.eval(env);
Object val = entry.value.eval(env);
+ if (env.getSemantics().incompatibleDictLiteralHasNoDuplicates && dict.containsKey(key)) {
+ throw new EvalException(
+ loc, "Duplicated key " + Printer.repr(key) + " when creating dictionary");
+ }
dict.put(key, val, loc, env);
}
return dict;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkDict.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkDict.java
index d622a7ccce..01f104bacb 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkDict.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkDict.java
@@ -22,29 +22,29 @@ import java.util.LinkedHashMap;
import java.util.Map;
import javax.annotation.Nullable;
-/**
- * Skylark Dict module.
- */
-@SkylarkModule(name = "dict",
- category = SkylarkModuleCategory.BUILTIN,
- doc = "A language built-in type representating a dictionary (associative mapping). "
- + "Dictionaries may be constructed with a special literal syntax:<br>"
- + "<pre class=\"language-python\">d = {\"a\": 2, \"b\": 5}</pre>"
- + "Use square brackets to access elements:<br>"
- + "<pre class=\"language-python\">e = d[\"a\"] # e == 2</pre>"
- + "Like lists, they can also be constructed using a comprehension syntax:<br>"
- + "<pre class=\"language-python\">d = {i: 2*i for i in range(20)}\n"
- + "e = d[8] # e == 16</pre>"
- + "See also the <a href=\"globals.html#dict\">dict()</a> constructor function. "
- + "<p>Iterating over a dict is equivalent to iterating over its keys. The <code>in</code> "
- + "operator tests for membership in the keyset of the dict.<br>"
- + "<pre class=\"language-python\">\"a\" in {\"a\" : 2, \"b\" : 5} # evaluates as True</pre>"
- + "The iteration order for a dict is deterministic but not specified. When constructing a dict "
- + "using any of the above methods, if there are two identical keys with conflicting values "
- + "then the last value takes precedence."
+/** Skylark Dict module. */
+@SkylarkModule(
+ name = "dict",
+ category = SkylarkModuleCategory.BUILTIN,
+ doc =
+ "A language built-in type representating a dictionary (associative mapping). "
+ + "Dictionaries may be constructed with a special literal syntax:<br>"
+ + "<pre class=\"language-python\">d = {\"a\": 2, \"b\": 5}</pre>"
+ + "When using the literal syntax, it is an error to have duplicated keys. "
+ + "Use square brackets to access elements:<br>"
+ + "<pre class=\"language-python\">e = d[\"a\"] # e == 2</pre>"
+ + "Like lists, they can also be constructed using a comprehension syntax:<br>"
+ + "<pre class=\"language-python\">d = {i: 2*i for i in range(20)}\n"
+ + "e = d[8] # e == 16</pre>"
+ + "See also the <a href=\"globals.html#dict\">dict()</a> constructor function. "
+ + "<p>Iterating over a dict is equivalent to iterating over its keys. The "
+ + "<code>in</code> operator tests for membership in the keyset of the dict.<br>"
+ + "<pre class=\"language-python\">\"a\" in {\"a\" : 2, \"b\" : 5} "
+ + "# evaluates as True</pre>"
+ + "The iteration order for a dict is deterministic but not specified."
)
-public final class SkylarkDict<K, V>
- extends MutableMap<K, V> implements Map<K, V>, SkylarkIndexable {
+public final class SkylarkDict<K, V> extends MutableMap<K, V>
+ implements Map<K, V>, SkylarkIndexable {
private final LinkedHashMap<K, V> contents = new LinkedHashMap<>();
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSemanticsOptions.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSemanticsOptions.java
index 4cca541ac8..07419e4992 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSemanticsOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkSemanticsOptions.java
@@ -129,4 +129,12 @@ public class SkylarkSemanticsOptions extends OptionsBase implements Serializable
+ "convert to a list."
)
public boolean incompatibleDepsetIsNotIterable;
+
+ @Option(
+ name = "incompatible_dict_literal_has_no_duplicates",
+ defaultValue = "false",
+ category = "incompatible changes",
+ help = "If set to true, the dictionary literal syntax doesn't allow duplicated keys."
+ )
+ public boolean incompatibleDictLiteralHasNoDuplicates;
}