Make two Skyframe nodes with the same events and values equal.

We do this by implementing equality for TaggedEvents (and all objects
it transitively includes). Before this change, if a Skyframe node
re-evaluated to the same value as in the previous build, but had
(transitive) events, change pruning would not cut off the evaluation
of its parents. This is not a big issue in practice because most nodes
that would re-evaluate to the same value (like FileValues or
GlobValues) never emit events, and others (like ActionExecutionValues)
have secondary caches that mask this effect.

Also do a drive-by fix where we were using the hash code of a nested
set instead of the shallow hash code (didn't have any bad effects in
practice because we never hash these values).

(Minor formatting clean-ups from https://bazel-review.googlesource.com/1610 )

--
Change-Id: I751a8479627f0456993c5ec8834528aeb593d736
Reviewed-on: https://bazel-review.googlesource.com/1610
MOS_MIGRATED_REVID=98115908
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java b/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java
index 3bcf0a0..ac629c7 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/LineNumberTable.java
@@ -25,8 +25,10 @@
 import java.io.Serializable;
 import java.nio.CharBuffer;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -146,6 +148,23 @@
           ? linestart[line + 1]
           : bufferLength);
     }
+
+
+    @Override
+    public int hashCode() {
+      return Objects.hash(Arrays.hashCode(linestart), path, bufferLength);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+      if (other == null || !other.getClass().equals(getClass())) {
+        return false;
+      }
+      Regular that = (Regular) other;
+      return this.bufferLength == that.bufferLength
+          && Arrays.equals(this.linestart, that.linestart)
+          && Objects.equals(this.path, that.path);
+    }
   }
 
   /**
@@ -197,7 +216,7 @@
       }
       this.table = hashOrdering.immutableSortedCopy(unorderedTable);
       this.bufferLength = buffer.length;
-      this.defaultPath = defaultPath;
+      this.defaultPath = Preconditions.checkNotNull(defaultPath);
     }
 
     private SingleHashLine getHashLine(int offset) {
@@ -242,5 +261,21 @@
       }
       return Pair.of(0, 0);
     }
+
+    @Override
+    public int hashCode() {
+      return Objects.hash(table, defaultPath, bufferLength);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+      if (other == null || !other.getClass().equals(getClass())) {
+        return false;
+      }
+      HashLine that = (HashLine) other;
+      return this.bufferLength == that.bufferLength
+          && this.defaultPath.equals(that.defaultPath)
+          && this.table.equals(that.table);
+    }
   }
 }