blob: c0298a1ca38f31311a387e639c5d8e0dcc05d42f [file] [log] [blame]
// Copyright 2021 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.analysis.config;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;
import java.util.List;
/** A registry of all {@link Fragment} and {@link FragmentOptions} classes registered at startup. */
public final class FragmentRegistry {
/**
* Creates a {@code FragmentRegistry}.
*
* <p>Order of elements in the given lists does not matter - the resulting registry will contain
* deterministically ordered sets.
*
* @param allFragments all registered fragment classes, including {@code universalFragments}
* @param universalFragments fragment classes that should be available to all rules even when not
* explicitly required
* @param additionalOptions any additional options classes not accounted for by a {@link
* RequiresOptions} annotation on a {@link Fragment} class in {@code allFragments}
*/
public static FragmentRegistry create(
List<Class<? extends Fragment>> allFragments,
List<Class<? extends Fragment>> universalFragments,
List<Class<? extends FragmentOptions>> additionalOptions) {
FragmentClassSet allFragmentsSet = FragmentClassSet.of(allFragments);
FragmentClassSet universalFragmentsSet = FragmentClassSet.of(universalFragments);
if (!allFragmentsSet.containsAll(universalFragmentsSet)) {
throw new IllegalArgumentException(
"Missing universally required fragments: "
+ Sets.difference(universalFragmentsSet, allFragmentsSet));
}
ImmutableSortedSet.Builder<Class<? extends FragmentOptions>> optionsClasses =
ImmutableSortedSet.orderedBy(BuildOptions.LEXICAL_FRAGMENT_OPTIONS_COMPARATOR);
for (Class<? extends Fragment> fragment : allFragmentsSet) {
optionsClasses.addAll(Fragment.requiredOptions(fragment));
}
optionsClasses.addAll(additionalOptions);
return new FragmentRegistry(allFragmentsSet, universalFragmentsSet, optionsClasses.build());
}
private final FragmentClassSet allFragments;
private final FragmentClassSet universalFragments;
private final ImmutableSortedSet<Class<? extends FragmentOptions>> optionsClasses;
private FragmentRegistry(
FragmentClassSet allFragments,
FragmentClassSet universalFragments,
ImmutableSortedSet<Class<? extends FragmentOptions>> optionsClasses) {
this.allFragments = allFragments;
this.universalFragments = universalFragments;
this.optionsClasses = optionsClasses;
}
/** Returns the set of all registered configuration fragments. */
public FragmentClassSet getAllFragments() {
return allFragments;
}
/**
* Returns a subset of {@link #getAllFragments} that should be available to all rules even when
* not explicitly required.
*/
public FragmentClassSet getUniversalFragments() {
return universalFragments;
}
/**
* Returns the set of all registered {@link FragmentOptions} classes.
*
* <p>Includes at least all options classes {@linkplain RequiresOptions required} by fragments in
* {@link #getAllFragments}.
*/
public ImmutableSortedSet<Class<? extends FragmentOptions>> getOptionsClasses() {
return optionsClasses;
}
}