Refactor analysis failure reporting, report loading failures

Split the AnalysisFailureEvent into a legacy and a new variant; always post an
AnalysisFailureEvent, even if the legacy variant is not posted - this gives us
some coverage for loading failures.

PiperOrigin-RevId: 197862257
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisFailureEvent.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisFailureEvent.java
index 1ab2f8d..b39d826 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisFailureEvent.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisFailureEvent.java
@@ -1,4 +1,4 @@
-// Copyright 2014 The Bazel Authors. All rights reserved.
+// Copyright 2018 The Bazel Authors. All rights reserved.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -15,14 +15,14 @@
 package com.google.devtools.build.lib.analysis;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.buildeventstream.BuildEvent;
 import com.google.devtools.build.lib.buildeventstream.BuildEventContext;
 import com.google.devtools.build.lib.buildeventstream.BuildEventId;
 import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
 import com.google.devtools.build.lib.buildeventstream.GenericBuildEvent;
 import com.google.devtools.build.lib.buildeventstream.NullConfiguration;
-import com.google.devtools.build.lib.causes.LabelCause;
-import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.causes.Cause;
 import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
 import java.util.Collection;
 
@@ -32,32 +32,24 @@
  */
 public class AnalysisFailureEvent implements BuildEvent {
   private final ConfiguredTargetKey failedTarget;
-  private final Label failureReason;
   private final BuildEventId configuration;
+  private final Iterable<Cause> causes;
 
   public AnalysisFailureEvent(
-      ConfiguredTargetKey failedTarget, BuildEventId configuration, Label failureReason) {
+      ConfiguredTargetKey failedTarget, BuildEventId configuration, Iterable<Cause> causes) {
     this.failedTarget = failedTarget;
-    this.failureReason = failureReason;
     if (configuration != null) {
       this.configuration = configuration;
     } else {
-      this.configuration = (new NullConfiguration()).getEventId();
+      this.configuration = NullConfiguration.INSTANCE.getEventId();
     }
-  }
-
-  public AnalysisFailureEvent(ConfiguredTargetKey failedTarget, Label failureReason) {
-    this(failedTarget, null, failureReason);
+    this.causes = causes;
   }
 
   public ConfiguredTargetKey getFailedTarget() {
     return failedTarget;
   }
 
-  public Label getFailureReason() {
-    return failureReason;
-  }
-
   @Override
   public BuildEventId getEventId() {
     return BuildEventId.targetCompleted(failedTarget.getLabel(), configuration);
@@ -65,9 +57,7 @@
 
   @Override
   public Collection<BuildEventId> getChildrenEvents() {
-    // TODO(aehlig): the root cause is not necessarily a label; e.g., it could
-    // also be a configured label.
-    return ImmutableList.of(BuildEventId.fromCause(new LabelCause(failureReason)));
+    return ImmutableList.copyOf(Iterables.transform(causes, BuildEventId::fromCause));
   }
 
   @Override