Aspects can get information from their base rule.

--
MOS_MIGRATED_REVID=102126786
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AspectWithParameters.java b/src/main/java/com/google/devtools/build/lib/analysis/AspectWithParameters.java
new file mode 100644
index 0000000..0cffc4c
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AspectWithParameters.java
@@ -0,0 +1,79 @@
+// 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.analysis;
+
+import com.google.devtools.build.lib.packages.AspectParameters;
+
+import java.util.Objects;
+
+/**
+ * Wrapper around {@link ConfiguredAspectFactory} class and {@link AspectParameters}. Aspects are
+ * created with help of aspect factory instances and parameters are used to configure them, so we
+ * have to keep them together. 
+ */
+public final class AspectWithParameters {
+  // TODO(bazel-team): class objects are not really hashable or comparable for equality other than
+  // by reference. We should identify the aspect here in a way that does not rely on comparison
+  // by reference so that keys can be serialized and deserialized properly.
+  private final Class<? extends ConfiguredAspectFactory> aspectFactory;
+  private final AspectParameters parameters;
+
+  public AspectWithParameters(
+      Class<? extends ConfiguredAspectFactory> aspect, AspectParameters parameters) {
+    this.aspectFactory = aspect;
+    this.parameters = parameters;
+  }
+
+  public AspectWithParameters(Class<? extends ConfiguredAspectFactory> aspect) {
+    this.aspectFactory = aspect;
+    this.parameters = AspectParameters.EMPTY;
+  }
+
+  /**
+   * Returns the aspectFactory required for building the aspect.
+   */
+  public Class<? extends ConfiguredAspectFactory> getAspectFactory() {
+    return aspectFactory;
+  }
+
+  /**
+   * Returns parameters for evaluation of the aspect.
+   */
+  public AspectParameters getParameters() {
+    return parameters;
+  }
+
+  @Override
+  public boolean equals(Object other) {
+    if (this == other) {
+      return true;
+    }
+    if (!(other instanceof AspectWithParameters)) {
+      return false;
+    }
+    AspectWithParameters that = (AspectWithParameters) other;
+    return Objects.equals(this.aspectFactory, that.aspectFactory) 
+        && Objects.equals(this.parameters, that.parameters);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(aspectFactory, parameters);
+  }
+
+  @Override
+  public String toString() {
+    return String.format("AspectWithParameters %s(%s)", aspectFactory, parameters);
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
index b27c2f3..a7fff98 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/BuildView.java
@@ -877,8 +877,8 @@
     TargetAndConfiguration ctNode = new TargetAndConfiguration(target);
     ListMultimap<Attribute, Dependency> depNodeNames;
     try {
-      depNodeNames = resolver.dependentNodeMap(ctNode, configurations.getHostConfiguration(), null,
-          getConfigurableAttributeKeys(ctNode));
+      depNodeNames = resolver.dependentNodeMap(ctNode, configurations.getHostConfiguration(),
+          /*aspect=*/null, /*aspectParameters=*/null, getConfigurableAttributeKeys(ctNode));
     } catch (EvalException e) {
       throw new IllegalStateException(e);
     }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
index f193298..9cce2f3 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredTargetFactory.java
@@ -31,6 +31,7 @@
 import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
 import com.google.devtools.build.lib.events.Event;
 import com.google.devtools.build.lib.events.EventHandler;
+import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.ConstantRuleVisibility;
 import com.google.devtools.build.lib.packages.InputFile;
@@ -280,8 +281,10 @@
   public Aspect createAspect(
       AnalysisEnvironment env, RuleConfiguredTarget associatedTarget,
       ConfiguredAspectFactory aspectFactory,
+      AspectParameters aspectParameters,
       ListMultimap<Attribute, ConfiguredTarget> prerequisiteMap,
-      Set<ConfigMatchingProvider> configConditions, BuildConfiguration hostConfiguration) {
+      Set<ConfigMatchingProvider> configConditions,
+      BuildConfiguration hostConfiguration) {
     RuleContext.Builder builder = new RuleContext.Builder(env,
         associatedTarget.getTarget(),
         associatedTarget.getConfiguration(),
@@ -297,7 +300,7 @@
       return null;
     }
 
-    return aspectFactory.create(associatedTarget, ruleContext);
+    return aspectFactory.create(associatedTarget, ruleContext, aspectParameters);
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
index 9b6ea93..f8ec20a 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/DependencyResolver.java
@@ -26,6 +26,7 @@
 import com.google.devtools.build.lib.collect.ImmutableSortedKeyListMultimap;
 import com.google.devtools.build.lib.packages.AspectDefinition;
 import com.google.devtools.build.lib.packages.AspectFactory;
+import com.google.devtools.build.lib.packages.AspectParameters;
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault;
 import com.google.devtools.build.lib.packages.Attribute.SplitTransition;
@@ -100,7 +101,7 @@
     private final Attribute.Transition transition;
 
     private final boolean hasStaticConfiguration;
-    private final ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects;
+    private final ImmutableSet<AspectWithParameters> aspects;
 
     /**
      * Constructs a Dependency with a given configuration (suitable for static configuration
@@ -108,7 +109,7 @@
      */
     public Dependency(Label label,
         @Nullable BuildConfiguration configuration,
-        ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+        ImmutableSet<AspectWithParameters> aspects) {
       this.label = Preconditions.checkNotNull(label);
       this.configuration = configuration;
       this.transition = null;
@@ -121,14 +122,14 @@
      * builds).
      */
     public Dependency(Label label, @Nullable BuildConfiguration configuration) {
-      this(label, configuration, ImmutableSet.<Class<? extends ConfiguredAspectFactory>>of());
+      this(label, configuration, ImmutableSet.<AspectWithParameters>of());
     }
 
     /**
      * Constructs a Dependency with a given transition (suitable for dynamic configuration builds).
      */
     public Dependency(Label label, Attribute.Transition transition,
-        ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+        ImmutableSet<AspectWithParameters> aspects) {
       this.label = Preconditions.checkNotNull(label);
       this.configuration = null;
       this.transition = Preconditions.checkNotNull(transition);
@@ -165,7 +166,7 @@
       return transition;
     }
 
-    public ImmutableSet<Class<? extends ConfiguredAspectFactory>> getAspects() {
+    public ImmutableSet<AspectWithParameters> getAspects() {
       return aspects;
     }
 
@@ -217,7 +218,7 @@
    */
   public final ListMultimap<Attribute, Dependency> dependentNodeMap(
       TargetAndConfiguration node, BuildConfiguration hostConfig, AspectDefinition aspect,
-      Set<ConfigMatchingProvider> configConditions)
+      AspectParameters aspectParameters, Set<ConfigMatchingProvider> configConditions)
       throws EvalException {
     Target target = node.getTarget();
     BuildConfiguration config = node.getConfiguration();
@@ -237,7 +238,7 @@
       Rule rule = (Rule) target;
       ListMultimap<Attribute, LabelAndConfiguration> labelMap =
           resolveAttributes(rule, aspect, config, hostConfig, configConditions);
-      visitRule(rule, aspect, labelMap, outgoingEdges);
+      visitRule(rule, aspect, aspectParameters, labelMap, outgoingEdges);
     } else if (target instanceof PackageGroup) {
       visitPackageGroup(node, (PackageGroup) target, outgoingEdges.get(null));
     } else {
@@ -502,8 +503,8 @@
       TargetAndConfiguration node, BuildConfiguration hostConfig,
       Set<ConfigMatchingProvider> configConditions) {
     try {
-      return ImmutableSet.copyOf(
-          dependentNodeMap(node, hostConfig, null, configConditions).values());
+      return ImmutableSet.copyOf(dependentNodeMap(node, hostConfig, /*aspect=*/null,
+          /*aspectParameters=*/null, configConditions).values());
     } catch (EvalException e) {
       throw new IllegalStateException(e);
     }
@@ -516,12 +517,12 @@
    * @throws IllegalArgumentException if the {@code node} does not refer to a {@link Rule} instance
    */
   public final Collection<Dependency> resolveRuleLabels(
-      TargetAndConfiguration node, AspectDefinition aspect, ListMultimap<Attribute,
+      TargetAndConfiguration node, ListMultimap<Attribute,
       LabelAndConfiguration> labelMap) {
     Preconditions.checkArgument(node.getTarget() instanceof Rule);
     Rule rule = (Rule) node.getTarget();
     ListMultimap<Attribute, Dependency> outgoingEdges = ArrayListMultimap.create();
-    visitRule(rule, aspect, labelMap, outgoingEdges);
+    visitRule(rule, labelMap, outgoingEdges);
     return outgoingEdges.values();
   }
 
@@ -548,39 +549,59 @@
     }
   }
 
-  private ImmutableSet<Class<? extends ConfiguredAspectFactory>> requiredAspects(
-      AspectDefinition aspect, Attribute attribute, Target target) {
+  private ImmutableSet<AspectWithParameters> requiredAspects(AspectDefinition aspectDefinition,
+      AspectParameters aspectParameters, Attribute attribute, Target target, Rule originalRule) {
     if (!(target instanceof Rule)) {
       return ImmutableSet.of();
     }
 
+    Set<AspectWithParameters> aspectCandidates =
+        extractAspectCandidates(aspectDefinition, aspectParameters, attribute, originalRule);
     RuleClass ruleClass = ((Rule) target).getRuleClassObject();
+    ImmutableSet.Builder<AspectWithParameters> result = ImmutableSet.builder();
+    for (AspectWithParameters candidateClass : aspectCandidates) {
+      ConfiguredAspectFactory candidate =
+          (ConfiguredAspectFactory) AspectFactory.Util.create(candidateClass.getAspectFactory());
+      if (Sets.difference(
+          candidate.getDefinition().getRequiredProviders(),
+          ruleClass.getAdvertisedProviders()).isEmpty()) {
+        result.add(candidateClass);
+      }
+    }
+    return result.build();
+  }
 
+  private static Set<AspectWithParameters> extractAspectCandidates(
+      AspectDefinition aspectDefinition, AspectParameters aspectParameters,
+      Attribute attribute, Rule originalRule) {
     // The order of this set will be deterministic. This is necessary because this order eventually
     // influences the order in which aspects are merged into the main configured target, which in
     // turn influences which aspect takes precedence if two emit the same provider (maybe this
     // should be an error)
-    Set<Class<? extends AspectFactory<?, ?, ?>>> aspectCandidates = new LinkedHashSet<>();
-    aspectCandidates.addAll(attribute.getAspects());
-    if (aspect != null) {
-      aspectCandidates.addAll(aspect.getAttributeAspects().get(attribute.getName()));
+    Set<AspectWithParameters> aspectCandidates = new LinkedHashSet<>();
+    for (Map.Entry<Class<? extends AspectFactory<?, ?, ?>>, AspectParameters> aspectWithParameters :
+      attribute.getAspectsWithParameters(originalRule).entrySet()) {
+      aspectCandidates.add(new AspectWithParameters(
+          aspectWithParameters.getKey().asSubclass(ConfiguredAspectFactory.class),
+          aspectWithParameters.getValue()));
     }
-
-    ImmutableSet.Builder<Class<? extends ConfiguredAspectFactory>> result = ImmutableSet.builder();
-    for (Class<? extends AspectFactory<?, ?, ?>> candidateClass : aspectCandidates) {
-      ConfiguredAspectFactory candidate =
-          (ConfiguredAspectFactory) AspectFactory.Util.create(candidateClass);
-      if (Sets.difference(
-          candidate.getDefinition().getRequiredProviders(),
-          ruleClass.getAdvertisedProviders()).isEmpty()) {
-        result.add(candidateClass.asSubclass(ConfiguredAspectFactory.class));
+    if (aspectDefinition != null) {
+      for (Class<? extends AspectFactory<?, ?, ?>> aspect :
+          aspectDefinition.getAttributeAspects().get(attribute.getName())) {
+        aspectCandidates.add(new AspectWithParameters(
+            aspect.asSubclass(ConfiguredAspectFactory.class),
+            aspectParameters));
       }
     }
-
-    return result.build();
+    return aspectCandidates;
   }
 
-  private void visitRule(Rule rule, AspectDefinition aspect,
+  private void visitRule(Rule rule, ListMultimap<Attribute, LabelAndConfiguration> labelMap,
+      ListMultimap<Attribute, Dependency> outgoingEdges) {
+    visitRule(rule, /*aspect=*/null, /*aspectParameters=*/null, labelMap, outgoingEdges);
+  }
+
+  private void visitRule(Rule rule, AspectDefinition aspect, AspectParameters aspectParameters,
       ListMultimap<Attribute, LabelAndConfiguration> labelMap,
       ListMultimap<Attribute, Dependency> outgoingEdges) {
     Preconditions.checkNotNull(labelMap);
@@ -622,7 +643,7 @@
           config.evaluateTransition(rule, attribute, toTarget, transitionApplier);
         }
         for (Dependency dependency : transitionApplier.getDependencies(label,
-            requiredAspects(aspect, attribute, toTarget))) {
+            requiredAspects(aspect, aspectParameters, attribute, toTarget, rule))) {
           outgoingEdges.put(
               entry.getKey(),
               dependency);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
index 29b5f4b..485786f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
@@ -32,8 +32,8 @@
 import com.google.devtools.build.lib.actions.ArtifactFactory;
 import com.google.devtools.build.lib.actions.PackageRootResolver;
 import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.analysis.AspectWithParameters;
 import com.google.devtools.build.lib.analysis.BlazeDirectories;
-import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
 import com.google.devtools.build.lib.analysis.DependencyResolver;
 import com.google.devtools.build.lib.analysis.ViewCreationFailedException;
@@ -1397,7 +1397,7 @@
      * TODO(bazel-team): this is a really ugly reverse dependency: factor this away.
      */
     Iterable<DependencyResolver.Dependency> getDependencies(Label label,
-        ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects);
+        ImmutableSet<AspectWithParameters> aspects);
   }
 
   /**
@@ -1471,7 +1471,7 @@
 
     @Override
     public Iterable<DependencyResolver.Dependency> getDependencies(Label label,
-        ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+        ImmutableSet<AspectWithParameters> aspects) {
       return ImmutableList.of(
           new DependencyResolver.Dependency(label, currentConfiguration, aspects));
     }
@@ -1572,7 +1572,7 @@
 
     @Override
     public Iterable<DependencyResolver.Dependency> getDependencies(Label label,
-        ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+        ImmutableSet<AspectWithParameters> aspects) {
       return ImmutableList.of(new DependencyResolver.Dependency(label, transition, aspects));
     }
   }
@@ -1639,7 +1639,7 @@
 
     @Override
     public Iterable<DependencyResolver.Dependency> getDependencies(Label label,
-        ImmutableSet<Class<? extends ConfiguredAspectFactory>> aspects) {
+        ImmutableSet<AspectWithParameters> aspects) {
       ImmutableList.Builder<DependencyResolver.Dependency> builder = ImmutableList.builder();
       for (TransitionApplier applier : appliers) {
         builder.addAll(applier.getDependencies(label, aspects));