RELNOTES: Add global hash() function for strings (only)
--
MOS_MIGRATED_REVID=127979748
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
index a7d168d..c108325 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
@@ -1998,6 +1998,24 @@
}
};
+ @SkylarkSignature(name = "hash", returnType = Integer.class,
+ doc = "Return a hash value for a string. Hash values of equal strings are always equal to "
+ + "one another, but may change over different invocations of the Skylark interpreter. "
+ + "Hashing of values besides strings is not currently supported.",
+ // Java guarantees that Strings are hashed using a specific algorithm and are therefore
+ // consistent across all invocations. Rather than re-export this promise to the user,
+ // we'll just provide the same basic guarantee as Java and Python do for hashing any
+ // kind of value.
+ parameters = {
+ @Param(name = "value", type = String.class,
+ doc = "String value to hash")
+ })
+ private static final BuiltinFunction hash = new BuiltinFunction("hash") {
+ public Integer invoke(String value) throws EvalException {
+ return value.hashCode();
+ }
+ };
+
@SkylarkSignature(name = "range", returnType = MutableList.class,
doc = "Creates a list where items go from <code>start</code> to <code>stop</code>, using a "
+ "<code>step</code> increment. If a single argument is provided, items will "
@@ -2017,8 +2035,8 @@
useLocation = true,
useEnvironment = true)
private static final BuiltinFunction range = new BuiltinFunction("range") {
- public MutableList<?> invoke(Integer startOrStop, Object stopOrNone, Integer step,
- Location loc, Environment env)
+ public MutableList<?> invoke(Integer startOrStop, Object stopOrNone, Integer step,
+ Location loc, Environment env)
throws EvalException, ConversionException {
int start;
int stop;
@@ -2327,7 +2345,7 @@
static final List<BaseFunction> skylarkGlobalFunctions =
ImmutableList.<BaseFunction>builder()
.addAll(buildGlobalFunctions)
- .add(dir, fail, getattr, hasattr, print, struct, type)
+ .add(dir, fail, getattr, hasattr, hash, print, struct, type)
.build();
/**
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
index a9f82d5..b93ce6e 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
@@ -1484,6 +1484,20 @@
}
@Test
+ public void testHash() throws Exception {
+ // This test is too strong, in that it tests whether the hash value of the string follows
+ // Java's specific algorithm for Strings. If our hash implementation is changed then this
+ // test will have to be modified.
+ new SkylarkTest()
+ .testStatement("hash('skylark')", "skylark".hashCode())
+ .testStatement("hash('google')", "google".hashCode())
+ .testIfErrorContains(
+ "Method hash(value: string) is not applicable for arguments (NoneType): "
+ + "'value' is NoneType, but should be string",
+ "hash(None)");
+ }
+
+ @Test
public void testRange() throws Exception {
new BothModesTest()
.testStatement("str(range(5))", "[0, 1, 2, 3, 4]")