aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryValue.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryValue.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryValue.java230
1 files changed, 172 insertions, 58 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryValue.java
index 1a431e2ca0..f7f48e59ad 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/CollectPackagesUnderDirectoryValue.java
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.skyframe;
import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.cmdline.RepositoryName;
@@ -23,88 +24,201 @@ import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
-
import java.util.Objects;
+import javax.annotation.Nullable;
/**
* The value computed by {@link CollectPackagesUnderDirectoryFunction}. Contains a mapping for all
- * its non-excluded directories to whether there are packages beneath them.
+ * its non-excluded directories to whether there are packages or error messages beneath them.
*
- * <p>This value is used by {@link GraphBackedRecursivePackageProvider#getPackagesUnderDirectory}
- * to help it traverse the graph and find the set of packages under a directory, recursively by
- * {@link CollectPackagesUnderDirectoryFunction} which computes a value for a directory by
- * aggregating results calculated from its subdirectories, and by
- * {@link PrepareDepsOfTargetsUnderDirectoryFunction} which uses this value to find transitive
- * targets to load.
+ * <p>This value is used by {@link GraphBackedRecursivePackageProvider#getPackagesUnderDirectory} to
+ * help it traverse the graph and find the set of packages under a directory, recursively by {@link
+ * CollectPackagesUnderDirectoryFunction} which computes a value for a directory by aggregating
+ * results calculated from its subdirectories, and by {@link
+ * PrepareDepsOfTargetsUnderDirectoryFunction} which uses this value to find transitive targets to
+ * load.
*
- * <p>Note that even though the {@link CollectPackagesUnderDirectoryFunction} is evaluated in
- * part because of its side-effects (i.e. loading transitive dependencies of targets), this value
+ * <p>Note that even though the {@link CollectPackagesUnderDirectoryFunction} is evaluated in part
+ * because of its side-effects (i.e. loading transitive dependencies of targets), this value
* interacts safely with change pruning, despite the fact that this value is a lossy representation
* of the packages beneath a directory (i.e. it doesn't care <b>which</b> packages are under a
- * directory, just whether there are any). When the targets in a package change, the
- * {@link PackageValue} that {@link CollectPackagesUnderDirectoryFunction} depends on will be
- * invalidated, and the PrepareDeps function for that package's directory will be reevaluated,
- * loading any new transitive dependencies. Change pruning may prevent the reevaluation of
- * PrepareDeps for directories above that one, but they don't need to be re-run.
+ * directory, just whether there are any). When the targets in a package change, the {@link
+ * PackageValue} that {@link CollectPackagesUnderDirectoryFunction} depends on will be invalidated,
+ * and the PrepareDeps function for that package's directory will be reevaluated, loading any new
+ * transitive dependencies. Change pruning may prevent the reevaluation of PrepareDeps for
+ * directories above that one, but they don't need to be re-run.
*/
-public class CollectPackagesUnderDirectoryValue implements SkyValue {
- public static final CollectPackagesUnderDirectoryValue EMPTY =
- new CollectPackagesUnderDirectoryValue(false, ImmutableMap.<RootedPath, Boolean>of());
+public abstract class CollectPackagesUnderDirectoryValue implements SkyValue {
- private final boolean isDirectoryPackage;
- private final ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackages;
+ private final ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackagesOrErrors;
- private CollectPackagesUnderDirectoryValue(
- boolean isDirectoryPackage,
- ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackages) {
- this.subdirectoryTransitivelyContainsPackages = subdirectoryTransitivelyContainsPackages;
- this.isDirectoryPackage = isDirectoryPackage;
+ CollectPackagesUnderDirectoryValue(
+ ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackagesOrErrors) {
+ this.subdirectoryTransitivelyContainsPackagesOrErrors =
+ Preconditions.checkNotNull(subdirectoryTransitivelyContainsPackagesOrErrors);
}
- public static CollectPackagesUnderDirectoryValue of(
- boolean isDirectoryPackage,
- ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackages) {
- if (!isDirectoryPackage && subdirectoryTransitivelyContainsPackages.isEmpty()) {
- return EMPTY;
+ /** Represents a successfully loaded package or a directory without a BUILD file. */
+ public static class NoErrorCollectPackagesUnderDirectoryValue
+ extends CollectPackagesUnderDirectoryValue {
+ public static final NoErrorCollectPackagesUnderDirectoryValue EMPTY =
+ new NoErrorCollectPackagesUnderDirectoryValue(false, ImmutableMap.of());
+
+ private final boolean isDirectoryPackage;
+
+ private NoErrorCollectPackagesUnderDirectoryValue(
+ boolean isDirectoryPackage,
+ ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackagesOrErrors) {
+ super(subdirectoryTransitivelyContainsPackagesOrErrors);
+ this.isDirectoryPackage = isDirectoryPackage;
}
- return new CollectPackagesUnderDirectoryValue(
- isDirectoryPackage, subdirectoryTransitivelyContainsPackages);
- }
- public boolean isDirectoryPackage() {
- return isDirectoryPackage;
- }
+ @Override
+ public boolean isDirectoryPackage() {
+ return isDirectoryPackage;
+ }
- public ImmutableMap<RootedPath, Boolean> getSubdirectoryTransitivelyContainsPackages() {
- return subdirectoryTransitivelyContainsPackages;
- }
+ @Nullable
+ @Override
+ public String getErrorMessage() {
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ isDirectoryPackage, getSubdirectoryTransitivelyContainsPackagesOrErrors());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof NoErrorCollectPackagesUnderDirectoryValue)) {
+ return false;
+ }
+ NoErrorCollectPackagesUnderDirectoryValue that =
+ (NoErrorCollectPackagesUnderDirectoryValue) o;
+ return this.isDirectoryPackage == that.isDirectoryPackage
+ && Objects.equals(
+ this.getSubdirectoryTransitivelyContainsPackagesOrErrors(),
+ that.getSubdirectoryTransitivelyContainsPackagesOrErrors());
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("isDirectoryPackage", isDirectoryPackage)
+ .add(
+ "subdirectoryTransitivelyContainsPackagesOrErrors",
+ getSubdirectoryTransitivelyContainsPackagesOrErrors())
+ .toString();
+ }
- @Override
- public int hashCode() {
- return Objects.hash(isDirectoryPackage, subdirectoryTransitivelyContainsPackages);
}
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
+ /** Represents a directory with a BUILD file that failed to load. */
+ public static class ErrorCollectPackagesUnderDirectoryValue
+ extends CollectPackagesUnderDirectoryValue {
+ private final String errorMessage;
+
+ private ErrorCollectPackagesUnderDirectoryValue(
+ String errorMessage,
+ ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackagesOrErrors) {
+ super(subdirectoryTransitivelyContainsPackagesOrErrors);
+ this.errorMessage = Preconditions.checkNotNull(errorMessage);
}
- if (!(o instanceof CollectPackagesUnderDirectoryValue)) {
+
+ @Override
+ public boolean isDirectoryPackage() {
return false;
}
- CollectPackagesUnderDirectoryValue that = (CollectPackagesUnderDirectoryValue) o;
- return this.isDirectoryPackage == that.isDirectoryPackage
- && this
- .subdirectoryTransitivelyContainsPackages.equals(
- that.subdirectoryTransitivelyContainsPackages);
+
+ @Override
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(errorMessage, getSubdirectoryTransitivelyContainsPackagesOrErrors());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof ErrorCollectPackagesUnderDirectoryValue)) {
+ return false;
+ }
+ ErrorCollectPackagesUnderDirectoryValue that = (ErrorCollectPackagesUnderDirectoryValue) o;
+ return Objects.equals(this.errorMessage, that.errorMessage)
+ && Objects.equals(
+ this.getSubdirectoryTransitivelyContainsPackagesOrErrors(),
+ that.getSubdirectoryTransitivelyContainsPackagesOrErrors());
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("errorMessage", errorMessage)
+ .add(
+ "subdirectoryTransitivelyContainsPackagesOrErrors",
+ getSubdirectoryTransitivelyContainsPackagesOrErrors())
+ .toString();
+ }
}
- @Override
- public String toString() {
- return MoreObjects.toStringHelper(this)
- .add("isDirectoryPackage", isDirectoryPackage)
- .add("subdirectoryTransitivelyContainsPackages", subdirectoryTransitivelyContainsPackages)
- .toString();
+ /**
+ * Constructs a {@link CollectPackagesUnderDirectoryValue} for a directory with a BUILD file that
+ * failed to load as a package.
+ */
+ public static CollectPackagesUnderDirectoryValue ofError(
+ String errorMessage,
+ ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackagesOrErrors) {
+ Preconditions.checkNotNull(errorMessage, "errorMessage");
+ return new ErrorCollectPackagesUnderDirectoryValue(
+ errorMessage, subdirectoryTransitivelyContainsPackagesOrErrors);
+ }
+
+ /**
+ * Constructs a {@link CollectPackagesUnderDirectoryValue} for a directory without a BUILD file or
+ * that has a BUILD file that successfully loads as a package.
+ */
+ public static CollectPackagesUnderDirectoryValue ofNoError(
+ boolean isDirectoryPackage,
+ ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackagesOrErrors) {
+ if (!isDirectoryPackage && subdirectoryTransitivelyContainsPackagesOrErrors.isEmpty()) {
+ return NoErrorCollectPackagesUnderDirectoryValue.EMPTY;
+ }
+ return new NoErrorCollectPackagesUnderDirectoryValue(
+ isDirectoryPackage, subdirectoryTransitivelyContainsPackagesOrErrors);
+ }
+
+ /**
+ * Returns whether there is a BUILD file in this directory that can be loaded as a package. If
+ * this returns {@code true}, then {@link #getErrorMessage()} returns {@code null}.
+ */
+ public abstract boolean isDirectoryPackage();
+
+ /**
+ * Returns an error describing why the BUILD file in this directory cannot be loaded as a package,
+ * if there is one and it can't be. Otherwise returns {@code null}. If this returns non-{@code
+ * null}, then {@link #isDirectoryPackage()} returns {@code false}.
+ */
+ @Nullable
+ public abstract String getErrorMessage();
+
+ /**
+ * Returns an {@link ImmutableMap} describing each immediate subdirectory of this directory and
+ * whether there are any packages, or BUILD files that couldn't be loaded, in or beneath that
+ * subdirectory.
+ */
+ public final ImmutableMap<RootedPath, Boolean>
+ getSubdirectoryTransitivelyContainsPackagesOrErrors() {
+ return subdirectoryTransitivelyContainsPackagesOrErrors;
}
/** Create a collect packages under directory request. */