Extract configuration fragment access logic into ConfigurationFragmentPolicy.

This is the first step toward giving aspects the ability to define their own
required configuration fragments, extracting the required configuration
metadata into a common place.

This should be a no-op refactoring.

--
MOS_MIGRATED_REVID=104249500
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 1a2488f..6d97e86 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
@@ -34,6 +34,8 @@
 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.ConfigurationFragmentPolicy;
+import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy;
 import com.google.devtools.build.lib.packages.ConstantRuleVisibility;
 import com.google.devtools.build.lib.packages.EnvironmentGroup;
 import com.google.devtools.build.lib.packages.InputFile;
@@ -43,7 +45,6 @@
 import com.google.devtools.build.lib.packages.PackageSpecification;
 import com.google.devtools.build.lib.packages.Rule;
 import com.google.devtools.build.lib.packages.RuleClass;
-import com.google.devtools.build.lib.packages.RuleClass.MissingFragmentPolicy;
 import com.google.devtools.build.lib.packages.RuleVisibility;
 import com.google.devtools.build.lib.packages.Target;
 import com.google.devtools.build.lib.rules.SkylarkRuleConfiguredTargetBuilder;
@@ -229,14 +230,16 @@
     if (ruleContext.hasErrors()) {
       return null;
     }
-    if (!rule.getRuleClassObject().getRequiredConfigurationFragments().isEmpty()) {
+    ConfigurationFragmentPolicy configurationFragmentPolicy =
+        rule.getRuleClassObject().getConfigurationFragmentPolicy();
+    if (!configurationFragmentPolicy.getRequiredConfigurationFragments().isEmpty()) {
       MissingFragmentPolicy missingFragmentPolicy =
-          rule.getRuleClassObject().missingFragmentPolicy();
+          configurationFragmentPolicy.getMissingFragmentPolicy();
       if (missingFragmentPolicy != MissingFragmentPolicy.IGNORE
           && !configuration.hasAllFragments(
-              rule.getRuleClassObject().getRequiredConfigurationFragments())) {
+              configurationFragmentPolicy.getRequiredConfigurationFragments())) {
         if (missingFragmentPolicy == MissingFragmentPolicy.FAIL_ANALYSIS) {
-          ruleContext.ruleError(missingFragmentError(ruleContext));
+          ruleContext.ruleError(missingFragmentError(ruleContext, configurationFragmentPolicy));
           return null;
         }
         return createFailConfiguredTarget(ruleContext);
@@ -254,10 +257,11 @@
     }
   }
 
-  private String missingFragmentError(RuleContext ruleContext) {
+  private String missingFragmentError(
+      RuleContext ruleContext, ConfigurationFragmentPolicy configurationFragmentPolicy) {
     RuleClass ruleClass = ruleContext.getRule().getRuleClassObject();
     Set<Class<?>> missingFragments = new LinkedHashSet<>();
-    for (Class<?> fragment : ruleClass.getRequiredConfigurationFragments()) {
+    for (Class<?> fragment : configurationFragmentPolicy.getRequiredConfigurationFragments()) {
       if (!ruleContext.getConfiguration().hasFragment(fragment.asSubclass(Fragment.class))) {
         missingFragments.add(fragment);
       }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index 19dbcc3..9d21ec6 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -51,6 +51,7 @@
 import com.google.devtools.build.lib.packages.Attribute.SplitTransition;
 import com.google.devtools.build.lib.packages.AttributeMap;
 import com.google.devtools.build.lib.packages.BuildType;
+import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy;
 import com.google.devtools.build.lib.packages.FileTarget;
 import com.google.devtools.build.lib.packages.FilesetEntry;
 import com.google.devtools.build.lib.packages.ImplicitOutputsFunction;
@@ -137,6 +138,7 @@
   private final ImmutableSet<String> features;
   private final Map<String, Attribute> attributeMap;
   private final BuildConfiguration hostConfiguration;
+  private final ConfigurationFragmentPolicy configurationFragmentPolicy;
   private final ErrorReporter reporter;
 
   private ActionOwner actionOwner;
@@ -150,6 +152,7 @@
     super(builder.env, builder.rule, builder.configuration, builder.prerequisiteMap.get(null),
         builder.visibility);
     this.rule = builder.rule;
+    this.configurationFragmentPolicy = builder.configurationFragmentPolicy;
     this.targetMap = targetMap;
     this.filesetEntryMap = filesetEntryMap;
     this.configConditions = configConditions;
@@ -167,7 +170,7 @@
     parseFeatures(getConfiguration().getDefaultFeatures(), globallyEnabled, globallyDisabled);
     for (ImmutableMap.Entry<Class<? extends Fragment>, Fragment> entry :
         getConfiguration().getAllFragments().entrySet()) {
-      if (rule.getRuleClassObject().isLegalConfigurationFragment(entry.getKey())) {
+      if (configurationFragmentPolicy.isLegalConfigurationFragment(entry.getKey())) {
         globallyEnabled.addAll(entry.getValue().configurationEnabledFeatures(this));
       }
     }
@@ -308,9 +311,13 @@
     return getConfiguration(config).getSkylarkFragmentNames();
   }
 
+  public ConfigurationFragmentPolicy getConfigurationFragment() {
+    return configurationFragmentPolicy;
+  }
+
   public <T extends Fragment> boolean isLegalFragment(
       Class<T> fragment, ConfigurationTransition config) {
-    return rule.getRuleClassObject().isLegalConfigurationFragment(fragment, config);
+    return configurationFragmentPolicy.isLegalConfigurationFragment(fragment, config);
   }
 
   public <T extends Fragment> boolean isLegalFragment(Class<T> fragment) {
@@ -1223,6 +1230,7 @@
   public static final class Builder implements RuleErrorConsumer  {
     private final AnalysisEnvironment env;
     private final Rule rule;
+    private final ConfigurationFragmentPolicy configurationFragmentPolicy;
     private final BuildConfiguration configuration;
     private final BuildConfiguration hostConfiguration;
     private final PrerequisiteValidator prerequisiteValidator;
@@ -1236,6 +1244,7 @@
         PrerequisiteValidator prerequisiteValidator) {
       this.env = Preconditions.checkNotNull(env);
       this.rule = Preconditions.checkNotNull(rule);
+      this.configurationFragmentPolicy = rule.getRuleClassObject().getConfigurationFragmentPolicy();
       this.configuration = Preconditions.checkNotNull(configuration);
       this.hostConfiguration = Preconditions.checkNotNull(hostConfiguration);
       this.prerequisiteValidator = prerequisiteValidator;
diff --git a/src/main/java/com/google/devtools/build/lib/packages/ConfigurationFragmentPolicy.java b/src/main/java/com/google/devtools/build/lib/packages/ConfigurationFragmentPolicy.java
new file mode 100644
index 0000000..abad8489
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/packages/ConfigurationFragmentPolicy.java
@@ -0,0 +1,214 @@
+// Copyright 2015 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.packages;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition;
+import com.google.devtools.build.lib.syntax.FragmentClassNameResolver;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Policy used to express the set of configuration fragments which are legal for a rule or aspect
+ * to access.
+ */
+public final class ConfigurationFragmentPolicy {
+
+  /**
+   * How to handle the case if the configuration is missing fragments that are required according
+   * to the rule class.
+   */
+  public enum MissingFragmentPolicy {
+    /**
+     * Some rules are monolithic across languages, and we want them to continue to work even when
+     * individual languages are disabled. Use this policy if the rule implementation is handling
+     * missing fragments.
+     */
+    IGNORE,
+
+    /**
+     * Use this policy to generate fail actions for the target rather than failing the analysis
+     * outright. Again, this is used when rules are monolithic across languages, but we still need
+     * to analyze the dependent libraries. (Instead of this mechanism, consider annotating
+     * attributes as unused if certain fragments are unavailable.)
+     */
+    CREATE_FAIL_ACTIONS,
+
+    /**
+     * Use this policy to fail the analysis of that target with an error message; this is the
+     * default.
+     */
+    FAIL_ANALYSIS;
+  }
+
+  /**
+   * Builder to construct a new ConfigurationFragmentPolicy.
+   */
+  public static final class Builder {
+    private Set<Class<?>> requiredConfigurationFragments = new LinkedHashSet<>();
+    private Map<ConfigurationTransition, ImmutableSet<String>> requiredConfigurationFragmentNames =
+        new LinkedHashMap<>();
+    private MissingFragmentPolicy missingFragmentPolicy = MissingFragmentPolicy.FAIL_ANALYSIS;
+    private FragmentClassNameResolver fragmentNameResolver;
+
+    /**
+     * Declares that the implementation of the associated rule class requires the given
+     * configuration fragments to be present in the configuration. The value is inherited by
+     * subclasses.
+     *
+     * <p>For backwards compatibility, if the set is empty, all fragments may be accessed. But note
+     * that this is only enforced in the {@link com.google.devtools.build.lib.analysis.RuleContext}
+     * class.
+     */
+    public Builder requiresConfigurationFragments(Collection<Class<?>> configurationFragments) {
+      requiredConfigurationFragments.addAll(configurationFragments);
+      return this;
+    }
+
+    /**
+     * Declares that the implementation of the associated rule class requires the given
+     * configuration fragments to be present in the configuration. The value is inherited by
+     * subclasses.
+     *
+     * <p>For backwards compatibility, if the set is empty, all fragments may be accessed. But note
+     * that this is only enforced in the {@link com.google.devtools.build.lib.analysis.RuleContext}
+     * class.
+     */
+    public Builder requiresConfigurationFragments(Class<?>... configurationFragments) {
+      Collections.addAll(requiredConfigurationFragments, configurationFragments);
+      return this;
+    }
+
+    /**
+     * Sets the policy for the case where the configuration is missing required fragments (see
+     * {@link #requiresConfigurationFragments}).
+     */
+    public Builder setMissingFragmentPolicy(MissingFragmentPolicy missingFragmentPolicy) {
+      this.missingFragmentPolicy = missingFragmentPolicy;
+      return this;
+    }
+
+    /**
+     * Declares the configuration fragments that are required by this rule.
+     *
+     * <p>In contrast to {@link #requiresConfigurationFragments(Class...)}, this method a) takes the
+     * names of fragments instead of their classes and b) distinguishes whether the fragments can be
+     * accessed in host (HOST) or target (NONE) configuration.
+     */
+    public Builder requiresConfigurationFragments(
+        FragmentClassNameResolver fragmentNameResolver,
+        Map<ConfigurationTransition, ImmutableSet<String>> configurationFragmentNames) {
+      requiredConfigurationFragmentNames.putAll(configurationFragmentNames);
+      this.fragmentNameResolver = fragmentNameResolver;
+      return this;
+    }
+
+    public ConfigurationFragmentPolicy build() {
+      return new ConfigurationFragmentPolicy(
+          ImmutableSet.copyOf(requiredConfigurationFragments),
+          ImmutableMap.copyOf(requiredConfigurationFragmentNames),
+          fragmentNameResolver,
+          missingFragmentPolicy);
+    }
+  }
+
+  /**
+   * The set of required configuration fragments; this should list all fragments that can be
+   * accessed by the rule implementation. If empty, all fragments are allowed to be accessed for
+   * backwards compatibility.
+   */
+  private final ImmutableSet<Class<?>> requiredConfigurationFragments;
+
+  /**
+   * A dictionary that maps configurations (NONE for target configuration, HOST for host
+   * configuration) to lists of names of required configuration fragments.
+   */
+  private final ImmutableMap<ConfigurationTransition, ImmutableSet<String>>
+      requiredConfigurationFragmentNames;
+
+  /**
+   * Used to resolve the names of fragments in order to compare them to values in {@link
+   * #requiredConfigurationFragmentNames}
+   */
+  private final FragmentClassNameResolver fragmentNameResolver;
+
+  /**
+   * What to do during analysis if a configuration fragment is missing.
+   */
+  private final MissingFragmentPolicy missingFragmentPolicy;
+
+  private ConfigurationFragmentPolicy(
+      ImmutableSet<Class<?>> requiredConfigurationFragments,
+      ImmutableMap<ConfigurationTransition, ImmutableSet<String>>
+          requiredConfigurationFragmentNames,
+      FragmentClassNameResolver fragmentNameResolver,
+      MissingFragmentPolicy missingFragmentPolicy) {
+    this.requiredConfigurationFragments = requiredConfigurationFragments;
+    this.requiredConfigurationFragmentNames = requiredConfigurationFragmentNames;
+    this.fragmentNameResolver = fragmentNameResolver;
+    this.missingFragmentPolicy = missingFragmentPolicy;
+  }
+
+  /**
+   * The set of required configuration fragments; this contains all fragments that can be
+   * accessed by the rule implementation. If empty, all fragments are allowed to be accessed for
+   * backwards compatibility.
+   */
+  public Set<Class<?>> getRequiredConfigurationFragments() {
+    return requiredConfigurationFragments;
+  }
+
+  /**
+   * Checks if the configuration fragment may be accessed (i.e., if it's declared) in the specified
+   * configuration (target or host).
+   */
+  public boolean isLegalConfigurationFragment(
+      Class<?> configurationFragment, ConfigurationTransition config) {
+    return requiredConfigurationFragments.contains(configurationFragment)
+        || hasLegalFragmentName(configurationFragment, config);
+  }
+
+  public boolean isLegalConfigurationFragment(Class<?> configurationFragment) {
+    // NONE means target configuration.
+    return isLegalConfigurationFragment(configurationFragment, ConfigurationTransition.NONE);
+  }
+
+  /**
+   * Checks whether the name of the given fragment class was declared as required in the
+   * specified configuration (target or host).
+   */
+  private boolean hasLegalFragmentName(
+      Class<?> configurationFragment, ConfigurationTransition config) {
+    if (fragmentNameResolver == null) {
+      return false;
+    }
+
+    String name = fragmentNameResolver.resolveName(configurationFragment);
+    ImmutableSet<String> fragmentNames = requiredConfigurationFragmentNames.get(config);
+    return (name != null && fragmentNames != null && fragmentNames.contains(name));
+  }
+
+  /**
+   * Whether to fail analysis if any of the required configuration fragments are missing.
+   */
+  public MissingFragmentPolicy getMissingFragmentPolicy() {
+    return missingFragmentPolicy;
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index a806435..6634988 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -35,6 +35,7 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition;
 import com.google.devtools.build.lib.packages.BuildType.SelectorList;
+import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy;
 import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
 import com.google.devtools.build.lib.syntax.Argument;
 import com.google.devtools.build.lib.syntax.BaseFunction;
@@ -198,33 +199,6 @@
   };
 
   /**
-   * How to handle the case if the configuration is missing fragments that are required according
-   * to the rule class.
-   */
-  public enum MissingFragmentPolicy {
-    /**
-     * Some rules are monolithic across languages, and we want them to continue to work even when
-     * individual languages are disabled. Use this policy if the rule implementation is handling
-     * missing fragments.
-     */
-    IGNORE,
-
-    /**
-     * Use this policy to generate fail actions for the target rather than failing the analysis
-     * outright. Again, this is used when rules are monolithic across languages, but we still need
-     * to analyze the dependent libraries. (Instead of this mechanism, consider annotating
-     * attributes as unused if certain fragments are unavailable.)
-     */
-    CREATE_FAIL_ACTIONS,
-
-    /**
-     * Use this policy to fail the analysis of that target with an error message; this is the
-     * default.
-     */
-    FAIL_ANALYSIS;
-  }
-
-  /**
    * For Bazel's constraint system: the attribute that declares the set of environments a rule
    * supports, overriding the defaults for their respective groups.
    */
@@ -502,11 +476,8 @@
     private Function<? super Rule, Map<String, Label>> externalBindingsFunction =
         NO_EXTERNAL_BINDINGS;
     private Environment ruleDefinitionEnvironment = null;
-    private Set<Class<?>> configurationFragments = new LinkedHashSet<>();
-    private MissingFragmentPolicy missingFragmentPolicy = MissingFragmentPolicy.FAIL_ANALYSIS;
-    private Map<ConfigurationTransition, ImmutableSet<String>> requiredFragmentNames =
-        new LinkedHashMap<>();
-    private FragmentClassNameResolver fragmentNameResolver;
+    private ConfigurationFragmentPolicy.Builder configurationFragmentPolicy =
+        new ConfigurationFragmentPolicy.Builder();
 
     private boolean supportsConstraintChecking = true;
 
@@ -534,8 +505,10 @@
         if (parent.preferredDependencyPredicate != Predicates.<String>alwaysFalse()) {
           setPreferredDependencyPredicate(parent.preferredDependencyPredicate);
         }
-        configurationFragments.addAll(parent.requiredConfigurationFragments);
-        missingFragmentPolicy = parent.missingFragmentPolicy;
+        configurationFragmentPolicy.requiresConfigurationFragments(
+            parent.getConfigurationFragmentPolicy().getRequiredConfigurationFragments());
+        configurationFragmentPolicy.setMissingFragmentPolicy(
+            parent.getConfigurationFragmentPolicy().getMissingFragmentPolicy());
         supportsConstraintChecking = parent.supportsConstraintChecking;
 
         for (Attribute attribute : parent.getAttributes()) {
@@ -593,8 +566,7 @@
           workspaceOnly, outputsDefaultExecutable, implicitOutputsFunction, configurator,
           configuredTargetFactory, validityPredicate, preferredDependencyPredicate,
           ImmutableSet.copyOf(advertisedProviders), configuredTargetFunction,
-          externalBindingsFunction, ruleDefinitionEnvironment, configurationFragments,
-          ImmutableMap.copyOf(requiredFragmentNames), fragmentNameResolver, missingFragmentPolicy,
+          externalBindingsFunction, ruleDefinitionEnvironment, configurationFragmentPolicy.build(),
           supportsConstraintChecking, attributes.values().toArray(new Attribute[0]));
     }
 
@@ -606,8 +578,8 @@
      * that this is only enforced in the {@link com.google.devtools.build.lib.analysis.RuleContext}
      * class.
      */
-    public Builder requiresConfigurationFragments(Class<?>... configurationFragment) {
-      Collections.addAll(configurationFragments, configurationFragment);
+    public Builder requiresConfigurationFragments(Class<?>... configurationFragments) {
+      configurationFragmentPolicy.requiresConfigurationFragments(configurationFragments);
       return this;
     }
 
@@ -616,7 +588,7 @@
      * {@link #requiresConfigurationFragments}).
      */
     public Builder setMissingFragmentPolicy(MissingFragmentPolicy missingFragmentPolicy) {
-      this.missingFragmentPolicy = missingFragmentPolicy;
+      configurationFragmentPolicy.setMissingFragmentPolicy(missingFragmentPolicy);
       return this;
     }
 
@@ -630,8 +602,8 @@
     public Builder requiresConfigurationFragments(
         FragmentClassNameResolver fragmentNameResolver,
         Map<ConfigurationTransition, ImmutableSet<String>> configurationFragmentNames) {
-      requiredFragmentNames.putAll(configurationFragmentNames);
-      this.fragmentNameResolver = fragmentNameResolver;
+      configurationFragmentPolicy.requiresConfigurationFragments(
+          fragmentNameResolver, configurationFragmentNames);
       return this;
     }
 
@@ -978,29 +950,9 @@
   @Nullable private final Environment ruleDefinitionEnvironment;
 
   /**
-   * The set of required configuration fragments; this should list all fragments that can be
-   * accessed by the rule implementation. If empty, all fragments are allowed to be accessed for
-   * backwards compatibility.
+   * The set of configuration fragments which are legal for this rule's implementation to access.
    */
-  private final ImmutableSet<Class<?>> requiredConfigurationFragments;
-
-  /**
-   * A dictionary that maps configurations (NONE for target configuration, HOST for host
-   * configuration) to lists of names of required configuration fragments.
-   */
-  private final ImmutableMap<ConfigurationTransition, ImmutableSet<String>>
-      requiredConfigurationFragmentNames;
-
-  /**
-   * Used to resolve the names of fragments in order to compare them to values in {@link
-   * #requiredConfigurationFragmentNames}
-   */
-  private final FragmentClassNameResolver fragmentNameResolver;
-  
-  /**
-   * What to do during analysis if a configuration fragment is missing.
-   */
-  private final MissingFragmentPolicy missingFragmentPolicy;
+  private final ConfigurationFragmentPolicy configurationFragmentPolicy;
 
   /**
    * Determines whether instances of this rule should be checked for constraint compatibility
@@ -1049,10 +1001,10 @@
         configuredTargetFunction,
         externalBindingsFunction,
         ruleDefinitionEnvironment,
-        allowedConfigurationFragments,
-        ImmutableMap.<ConfigurationTransition, ImmutableSet<String>>of(),
-        null, // FragmentClassNameResolver
-        missingFragmentPolicy,
+        new ConfigurationFragmentPolicy.Builder()
+            .requiresConfigurationFragments(allowedConfigurationFragments)
+            .setMissingFragmentPolicy(missingFragmentPolicy)
+            .build(),
         supportsConstraintChecking,
         attributes);
   }
@@ -1091,10 +1043,7 @@
       @Nullable BaseFunction configuredTargetFunction,
       Function<? super Rule, Map<String, Label>> externalBindingsFunction,
       @Nullable Environment ruleDefinitionEnvironment,
-      Set<Class<?>> allowedConfigurationFragments,
-      ImmutableMap<ConfigurationTransition, ImmutableSet<String>> allowedConfigurationFragmentNames,
-      @Nullable FragmentClassNameResolver fragmentNameResolver,
-      MissingFragmentPolicy missingFragmentPolicy,
+      ConfigurationFragmentPolicy configurationFragmentPolicy,
       boolean supportsConstraintChecking,
       Attribute... attributes) {
     this.name = name;
@@ -1115,10 +1064,7 @@
     this.attributes = ImmutableList.copyOf(attributes);
     this.workspaceOnly = workspaceOnly;
     this.outputsDefaultExecutable = outputsDefaultExecutable;
-    this.requiredConfigurationFragments = ImmutableSet.copyOf(allowedConfigurationFragments);
-    this.requiredConfigurationFragmentNames = allowedConfigurationFragmentNames;
-    this.fragmentNameResolver = fragmentNameResolver;
-    this.missingFragmentPolicy = missingFragmentPolicy;
+    this.configurationFragmentPolicy = configurationFragmentPolicy;
     this.supportsConstraintChecking = supportsConstraintChecking;
 
     // create the index:
@@ -1264,49 +1210,10 @@
   }
 
   /**
-   * The set of required configuration fragments; this contains all fragments that can be
-   * accessed by the rule implementation. If empty, all fragments are allowed to be accessed for
-   * backwards compatibility.
+   * Returns this rule's policy for configuration fragment access.
    */
-  public Set<Class<?>> getRequiredConfigurationFragments() {
-    return requiredConfigurationFragments;
-  }
-
-  /**
-   * Checks if the configuration fragment may be accessed (i.e., if it's declared) in the specified
-   * configuration (target or host).
-   */
-  public boolean isLegalConfigurationFragment(
-      Class<?> configurationFragment, ConfigurationTransition config) {
-    return requiredConfigurationFragments.contains(configurationFragment)
-        || hasLegalFragmentName(configurationFragment, config);
-  }
-
-  public boolean isLegalConfigurationFragment(Class<?> configurationFragment) {
-    // NONE means target configuration.
-    return isLegalConfigurationFragment(configurationFragment, ConfigurationTransition.NONE);
-  }
-
-  /**
-   * Checks whether the name of the given fragment class was declared as required fragment in the
-   * specified configuration (target or host).
-   */
-  private boolean hasLegalFragmentName(
-      Class<?> configurationFragment, ConfigurationTransition config) {
-    if (fragmentNameResolver == null) {
-      return false;
-    }
-
-    String name = fragmentNameResolver.resolveName(configurationFragment);
-    ImmutableSet<String> fragmentNames = requiredConfigurationFragmentNames.get(config);
-    return (name != null && fragmentNames != null && fragmentNames.contains(name));
-  }
-
-  /**
-   * Whether to fail analysis if any of the required configuration fragments are missing.
-   */
-  public MissingFragmentPolicy missingFragmentPolicy() {
-    return missingFragmentPolicy;
+  public ConfigurationFragmentPolicy getConfigurationFragmentPolicy() {
+    return configurationFragmentPolicy;
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java
index 06e068d..8053543 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveTargetFunction.java
@@ -26,6 +26,7 @@
 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.ConfigurationFragmentPolicy;
 import com.google.devtools.build.lib.packages.NoSuchPackageException;
 import com.google.devtools.build.lib.packages.NoSuchTargetException;
 import com.google.devtools.build.lib.packages.NoSuchThingException;
@@ -136,8 +137,10 @@
 
     // Get configuration fragments directly required by this target.
     if (target instanceof Rule) {
+      ConfigurationFragmentPolicy configurationFragmentPolicy =
+          target.getAssociatedRule().getRuleClassObject().getConfigurationFragmentPolicy();
       Set<Class<?>> configFragments =
-          target.getAssociatedRule().getRuleClassObject().getRequiredConfigurationFragments();
+          configurationFragmentPolicy.getRequiredConfigurationFragments();
       // An empty result means this rule requires all fragments (which practically means
       // the rule isn't yet declaring its actually needed fragments). So load everything.
       configFragments = configFragments.isEmpty() ? getAllFragments() : configFragments;
diff --git a/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java b/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java
index f64d341..0a89a76 100644
--- a/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java
+++ b/src/test/java/com/google/devtools/build/lib/packages/RuleClassTest.java
@@ -1,4 +1,4 @@
-// Copyright 2006-2015 Google Inc. All rights reserved.
+// Copyright 2015 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.
@@ -43,9 +43,9 @@
 import com.google.devtools.build.lib.events.Location;
 import com.google.devtools.build.lib.events.Location.LineAndColumn;
 import com.google.devtools.build.lib.packages.Attribute.ValidityPredicate;
+import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy;
 import com.google.devtools.build.lib.packages.Package.Builder;
 import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
-import com.google.devtools.build.lib.packages.RuleClass.MissingFragmentPolicy;
 import com.google.devtools.build.lib.packages.util.PackageLoadingTestCase;
 import com.google.devtools.build.lib.syntax.Type;
 import com.google.devtools.build.lib.vfs.Path;
@@ -712,9 +712,9 @@
   public void testRequiredFragmentInheritance() throws Exception {
     RuleClass parentRuleClass = createParentRuleClass();
     RuleClass childRuleClass = createChildRuleClass(parentRuleClass);
-    assertThat(parentRuleClass.getRequiredConfigurationFragments())
+    assertThat(parentRuleClass.getConfigurationFragmentPolicy().getRequiredConfigurationFragments())
         .containsExactly(DummyFragment.class);
-    assertThat(childRuleClass.getRequiredConfigurationFragments())
+    assertThat(childRuleClass.getConfigurationFragmentPolicy().getRequiredConfigurationFragments())
         .containsExactly(DummyFragment.class);
   }