From b25759cab708722fb6c97a0816085c8f4ec24b98 Mon Sep 17 00:00:00 2001 From: Mark Schaller Date: Wed, 29 Jul 2015 17:09:18 +0000 Subject: Extract base class from TransitiveTargetFunction -- MOS_MIGRATED_REVID=99386094 --- .../skyframe/TransitiveBaseTraversalFunction.java | 376 +++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java (limited to 'src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java') diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java new file mode 100644 index 0000000000..36484551e6 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java @@ -0,0 +1,376 @@ +// Copyright 2015 Google Inc. 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.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; +import com.google.devtools.build.lib.events.Event; +import com.google.devtools.build.lib.events.EventHandler; +import com.google.devtools.build.lib.packages.AspectDefinition; +import com.google.devtools.build.lib.packages.Attribute; +import com.google.devtools.build.lib.packages.InputFile; +import com.google.devtools.build.lib.packages.NoSuchPackageException; +import com.google.devtools.build.lib.packages.NoSuchTargetException; +import com.google.devtools.build.lib.packages.NoSuchThingException; +import com.google.devtools.build.lib.packages.OutputFile; +import com.google.devtools.build.lib.packages.Package; +import com.google.devtools.build.lib.packages.PackageGroup; +import com.google.devtools.build.lib.packages.Rule; +import com.google.devtools.build.lib.packages.Target; +import com.google.devtools.build.lib.packages.TargetUtils; +import com.google.devtools.build.lib.syntax.Label; +import com.google.devtools.build.skyframe.SkyFunction; +import com.google.devtools.build.skyframe.SkyFunctionException; +import com.google.devtools.build.skyframe.SkyKey; +import com.google.devtools.build.skyframe.SkyValue; +import com.google.devtools.build.skyframe.ValueOrException2; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; + +import javax.annotation.Nullable; + +/** + * This class can be extended to define {@link SkyFunction}s that traverse a target and its + * transitive dependencies and return values based on that traversal. + * + *

The {@code TProcessedTargets} type parameter represents the result of processing a target and + * its transitive dependencies. + * + *

{@code TransitiveBaseTraversalFunction} asks for one to be constructed via {@link + * #processTarget}, and then asks for it to be updated based on the current target's + * attributes' dependencies via {@link #processDeps}, and then asks for it to be updated based + * on the current target' aspects' dependencies via {@link #processDeps}. Finally, it calls + * {@link #computeSkyValue} with the {#code ProcessedTargets} to get the {@link SkyValue} to + * return. + */ +abstract class TransitiveBaseTraversalFunction + implements SkyFunction { + + /** + * Returns a {@link SkyKey} corresponding to the traversal of a target specified by {@code label} + * and its transitive dependencies. + * + *

Extenders of this class should implement this function to return a key with their + * specialized {@link SkyFunction}'s name. + * + *

{@link TransitiveBaseTraversalFunction} calls this for each dependency of a target, and + * then gets their values from the environment. + * + *

The key's {@link SkyFunction} may throw at most {@link NoSuchPackageException} and + * {@link NoSuchTargetException}. Other exception types are not handled by {@link + * TransitiveBaseTraversalFunction}. + */ + abstract SkyKey getKey(Label label); + + abstract TProcessedTargets processTarget(Label label, + TargetAndErrorIfAny targetAndErrorIfAny); + + abstract void processDeps(TProcessedTargets processedTargets, EventHandler eventHandler, + TargetAndErrorIfAny targetAndErrorIfAny, + Iterable>> + depEntries); + + /** + * Returns a {@link SkyValue} based on the target and any errors it has, and the values + * accumulated across it and a traversal of its transitive dependencies. + */ + abstract SkyValue computeSkyValue(TargetAndErrorIfAny targetAndErrorIfAny, + TProcessedTargets processedTargets); + + @Override + public SkyValue compute(SkyKey key, Environment env) + throws TransitiveBaseTraversalFunctionException { + Label label = (Label) key.argument(); + LoadTargetResults loadTargetResults; + try { + loadTargetResults = loadTarget(env, label); + } catch (NoSuchTargetException e) { + throw new TransitiveBaseTraversalFunctionException(e); + } catch (NoSuchPackageException e) { + throw new TransitiveBaseTraversalFunctionException(e); + } + LoadTargetResultsType loadTargetResultsType = loadTargetResults.getType(); + if (loadTargetResultsType.equals(LoadTargetResultsType.VALUES_MISSING)) { + return null; + } + Preconditions.checkState( + loadTargetResultsType.equals(LoadTargetResultsType.TARGET_AND_ERROR_IF_ANY), + loadTargetResultsType); + TargetAndErrorIfAny targetAndErrorIfAny = (TargetAndErrorIfAny) loadTargetResults; + TProcessedTargets processedTargets = processTarget(label, targetAndErrorIfAny); + + // Process deps from attributes of current target. + Iterable labelDepKeys = getLabelDepKeys(targetAndErrorIfAny.getTarget()); + Set>> + labelDepEntries = env.getValuesOrThrow(labelDepKeys, NoSuchPackageException.class, + NoSuchTargetException.class).entrySet(); + processDeps(processedTargets, env.getListener(), targetAndErrorIfAny, labelDepEntries); + if (env.valuesMissing()) { + return null; + } + + // Process deps from aspects. + Iterable labelAspectKeys = getLabelAspectKeys(targetAndErrorIfAny.getTarget(), env); + Set>> + labelAspectEntries = env.getValuesOrThrow(labelAspectKeys, NoSuchPackageException.class, + NoSuchTargetException.class).entrySet(); + processDeps(processedTargets, env.getListener(), targetAndErrorIfAny, labelAspectEntries); + if (env.valuesMissing()) { + return null; + } + + return computeSkyValue(targetAndErrorIfAny, processedTargets); + } + + @Override + public String extractTag(SkyKey skyKey) { + return Label.print(((Label) skyKey.argument())); + } + + private Iterable getLabelAspectKeys(Target target, Environment env) { + List depKeys = Lists.newArrayList(); + if (target instanceof Rule) { + Multimap transitions = + ((Rule) target).getTransitions(Rule.NO_NODEP_ATTRIBUTES); + for (Entry entry : transitions.entries()) { + SkyKey packageKey = PackageValue.key(entry.getValue().getPackageIdentifier()); + try { + PackageValue pkgValue = (PackageValue) env.getValueOrThrow(packageKey, + NoSuchThingException.class); + if (pkgValue == null) { + continue; + } + Collection

In keep_going mode, used the same way, but only for targets that could not be loaded at + * all (we proceed with transitive loading on targets that contain errors).

+ */ + public TransitiveBaseTraversalFunctionException(NoSuchTargetException e) { + super(e, Transience.PERSISTENT); + } + } +} -- cgit v1.2.3