| // 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.query2.engine; |
| |
| import com.google.devtools.build.lib.query2.engine.QueryEnvironment.TargetAccessor; |
| |
| /** |
| * A predicate for targets included in the visibility list of a rule. |
| * |
| * <p>A rule's visibility is described by a set of {@link QueryVisibility}. Each element |
| * in the set corresponds to an entry in the rule's visibility attribute, or an entry in the |
| * packages attribute of an included package_group. |
| */ |
| public abstract class QueryVisibility<T> { |
| |
| /** Returns true if the visibility specification includes the given target's package. */ |
| public abstract boolean contains(T target); |
| |
| /** Global visibility. */ |
| @SuppressWarnings("unchecked") // Safe covariant cast. |
| public static <T> QueryVisibility<T> everything() { |
| return (QueryVisibility<T>) (Object) EVERYTHING; |
| } |
| |
| private static final QueryVisibility<?> EVERYTHING = new QueryVisibility<Object>() { |
| @Override |
| public boolean contains(Object target) { |
| return true; |
| } |
| |
| @Override |
| public String toString() { |
| return "QueryVisibility(//visibility:public)"; |
| } |
| }; |
| |
| /** |
| * Empty visibility. |
| * |
| * <p>This is useful as a sentinel to indicate that a package specification could be parsed into |
| * a {@link QueryVisibility}. Same-package visibility is handled separately by |
| * {@link VisibleFunction}. |
| */ |
| @SuppressWarnings("unchecked") // Safe covariant cast. |
| public static <T> QueryVisibility<T> nothing() { |
| return (QueryVisibility<T>) (Object) NOTHING; |
| } |
| |
| private static final QueryVisibility<?> NOTHING = new QueryVisibility<Object>() { |
| @Override |
| public boolean contains(Object target) { |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return "QueryVisibility(//visibility:private)"; |
| } |
| }; |
| |
| /** |
| * Same-package visibility. |
| * |
| * <p>Targets are always visible to other targets in the same package. Additionally, targets |
| * under java/ are always visible to the corresponding package in javatests/. |
| */ |
| public static <T> QueryVisibility<T> samePackage(T from, TargetAccessor<T> accessor) { |
| return new SamePackageVisibility<>(from, accessor); |
| } |
| |
| private static final class SamePackageVisibility<T> extends QueryVisibility<T> { |
| |
| private static final String JAVA_PREFIX = "java/"; |
| private static final String JAVATESTS_PREFIX = "javatests/"; |
| |
| private final String packageName; |
| private final TargetAccessor<T> accessor; |
| |
| public SamePackageVisibility(T target, TargetAccessor<T> accessor) { |
| this.packageName = accessor.getPackage(target); |
| this.accessor = accessor; |
| } |
| |
| @Override |
| public boolean contains(T target) { |
| String other = accessor.getPackage(target); |
| if (packageName.equals(other)) { |
| return true; |
| } |
| |
| // packages in java/ are always visible from the corresponding package in javatests/ |
| if (other.startsWith(JAVATESTS_PREFIX) |
| && packageName.equals(JAVA_PREFIX + other.substring(JAVATESTS_PREFIX.length()))) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return String.format("QueryVisibility(samePackage=%s)", "<PACKAGE>"); |
| } |
| } |
| } |