// 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. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.devtools.build.lib.skyframe; import com.google.common.collect.Interner; import com.google.devtools.build.lib.cmdline.PackageIdentifier; import com.google.devtools.build.lib.concurrent.BlazeInterners; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.skyframe.AbstractSkyKey; import com.google.devtools.build.skyframe.SkyFunctionName; import com.google.devtools.build.skyframe.SkyKey; import com.google.devtools.build.skyframe.SkyValue; /** * Encapsulates the errors, if any, encountered when loading a specific package. * *

This is a change-pruning-friendly convenience {@link SkyValue} for use cases where {@link * Result} is sufficient. */ public abstract class PackageErrorMessageValue implements SkyValue { /** Tri-state result of loading the package. */ enum Result { /** * There was no error loading the package and {@link * com.google.devtools.build.lib.packages.Package#containsErrors} returned {@code false}. */ NO_ERROR, /** * There was no error loading the package and {@link * com.google.devtools.build.lib.packages.Package#containsErrors} returned {@code true}. */ ERROR, /** * There was a {@link com.google.devtools.build.lib.packages.NoSuchPackageException} loading the * package. */ NO_SUCH_PACKAGE_EXCEPTION, } /** Returns the {@link Result} from loading the package. */ abstract Result getResult(); /** * If {@code getResult().equals(NO_SUCH_PACKAGE_EXCEPTION)}, returns the error message from the * {@link com.google.devtools.build.lib.packages.NoSuchPackageException} encountered. */ abstract String getNoSuchPackageExceptionMessage(); static PackageErrorMessageValue ofPackageWithNoErrors() { return NO_ERROR_VALUE; } static PackageErrorMessageValue ofPackageWithErrors() { return ERROR_VALUE; } static PackageErrorMessageValue ofNoSuchPackageException(String errorMessage) { return new NoSuchPackageExceptionValue(errorMessage); } static SkyKey key(PackageIdentifier pkgId) { return Key.create(pkgId); } @AutoCodec.VisibleForSerialization @AutoCodec static class Key extends AbstractSkyKey { private static final Interner interner = BlazeInterners.newWeakInterner(); private Key(PackageIdentifier arg) { super(arg); } @AutoCodec.VisibleForSerialization @AutoCodec.Instantiator static Key create(PackageIdentifier arg) { return interner.intern(new Key(arg)); } @Override public SkyFunctionName functionName() { return SkyFunctions.PACKAGE_ERROR_MESSAGE; } } @AutoCodec static final PackageErrorMessageValue NO_ERROR_VALUE = new PackageErrorMessageValue() { @Override Result getResult() { return Result.NO_ERROR; } @Override String getNoSuchPackageExceptionMessage() { throw new IllegalStateException(); } }; @AutoCodec static final PackageErrorMessageValue ERROR_VALUE = new PackageErrorMessageValue() { @Override Result getResult() { return Result.ERROR; } @Override String getNoSuchPackageExceptionMessage() { throw new IllegalStateException(); } }; @AutoCodec static class NoSuchPackageExceptionValue extends PackageErrorMessageValue { private final String errorMessage; public NoSuchPackageExceptionValue(String errorMessage) { this.errorMessage = errorMessage; } @Override Result getResult() { return Result.NO_SUCH_PACKAGE_EXCEPTION; } @Override String getNoSuchPackageExceptionMessage() { return errorMessage; } @Override public boolean equals(Object obj) { if (!(obj instanceof NoSuchPackageExceptionValue)) { return false; } NoSuchPackageExceptionValue other = (NoSuchPackageExceptionValue) obj; return errorMessage.equals(other.errorMessage); } @Override public int hashCode() { return errorMessage.hashCode(); } } }