diff options
Diffstat (limited to 'src/main/java/com')
3 files changed, 52 insertions, 23 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/MergedConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/MergedConfiguredTarget.java index 9a5317f5a0..7451dd68b8 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/MergedConfiguredTarget.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/MergedConfiguredTarget.java @@ -16,6 +16,7 @@ package com.google.devtools.build.lib.analysis; import com.google.common.collect.Iterables; import com.google.devtools.build.lib.packages.SkylarkClassObject; import com.google.devtools.build.lib.packages.SkylarkClassObjectConstructor.Key; +import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -27,6 +28,14 @@ import javax.annotation.Nullable; * <p>This is an ephemeral object created only for the analysis of a single configured target. After * that configured target is analyzed, this is thrown away. */ +// TODO(bazel-team): This annotation is needed for compatibility with Skylark code that expects +// type() of this class to be "MergedConfiguredTarget" instead of "Target". The dependent code +// should be refactored, possibly by adding a field to this class that it could read instead. +@SkylarkModule( + name = "MergedConfiguredTarget", + doc = "", + documented = false +) public final class MergedConfiguredTarget extends AbstractConfiguredTarget { private final ConfiguredTarget base; private final TransitiveInfoProviderMap providers; diff --git a/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkInterfaceUtils.java b/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkInterfaceUtils.java index 95d4f4fcf5..348a9ccef4 100644 --- a/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkInterfaceUtils.java +++ b/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkInterfaceUtils.java @@ -23,40 +23,59 @@ import javax.annotation.Nullable; public class SkylarkInterfaceUtils { /** + * Returns the {@link SkylarkModule} annotation for the given class, if it exists, and + * null otherwise. The first annotation found will be returned, starting with {@code classObj} + * and following its base classes and interfaces recursively. + */ + @Nullable + public static SkylarkModule getSkylarkModule(Class<?> classObj) { + if (classObj.isAnnotationPresent(SkylarkModule.class)) { + return classObj.getAnnotation(SkylarkModule.class); + } + Class<?> superclass = classObj.getSuperclass(); + if (superclass != null) { + SkylarkModule annotation = getSkylarkModule(superclass); + if (annotation != null) { + return annotation; + } + } + for (Class<?> interfaceObj : classObj.getInterfaces()) { + SkylarkModule annotation = getSkylarkModule(interfaceObj); + if (annotation != null) { + return annotation; + } + } + return null; + } + + /** * Returns the {@link SkylarkCallable} annotation for the given method, if it exists, and - * null otherwise. The method must be declared in {@code classObj} or one of its base classes - * or interfaces. The first annotation of an overridden version of the method that is found + * null otherwise. The first annotation of an overridden version of the method that is found * will be returned, starting with {@code classObj} and following its base classes and - * interfaces recursively. + * interfaces recursively, skipping any annotation inside a class not marked + * {@link SkylarkModule}. */ @Nullable public static SkylarkCallable getSkylarkCallable(Class<?> classObj, Method method) { - boolean keepLooking = false; try { Method superMethod = classObj.getMethod(method.getName(), method.getParameterTypes()); if (classObj.isAnnotationPresent(SkylarkModule.class) && superMethod.isAnnotationPresent(SkylarkCallable.class)) { return superMethod.getAnnotation(SkylarkCallable.class); - } else { - keepLooking = true; } } catch (NoSuchMethodException e) { - // The class might not have the specified method, so an exceptions is OK. - keepLooking = true; + // The class might not have the specified method, so an exception is OK. } - if (keepLooking) { - if (classObj.getSuperclass() != null) { - SkylarkCallable annotation = - getSkylarkCallable(classObj.getSuperclass(), method); - if (annotation != null) { - return annotation; - } + if (classObj.getSuperclass() != null) { + SkylarkCallable annotation = getSkylarkCallable(classObj.getSuperclass(), method); + if (annotation != null) { + return annotation; } - for (Class<?> interfaceObj : classObj.getInterfaces()) { - SkylarkCallable annotation = getSkylarkCallable(interfaceObj, method); - if (annotation != null) { - return annotation; - } + } + for (Class<?> interfaceObj : classObj.getInterfaces()) { + SkylarkCallable annotation = getSkylarkCallable(interfaceObj, method); + if (annotation != null) { + return annotation; } } return null; diff --git a/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java b/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java index 5b1834d868..9609544e19 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java @@ -21,6 +21,7 @@ import com.google.common.collect.Ordering; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.events.Location; +import com.google.devtools.build.lib.skylarkinterface.SkylarkInterfaceUtils; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; import com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils; @@ -255,9 +256,9 @@ public final class EvalUtils { * when the given class identifies a Skylark name space. */ public static String getDataTypeNameFromClass(Class<?> c, boolean highlightNameSpaces) { - if (c.isAnnotationPresent(SkylarkModule.class)) { - SkylarkModule module = c.getAnnotation(SkylarkModule.class); - return c.getAnnotation(SkylarkModule.class).name() + SkylarkModule module = SkylarkInterfaceUtils.getSkylarkModule(c); + if (module != null) { + return module.name() + ((module.namespace() && highlightNameSpaces) ? " (a language module)" : ""); } else if (c.equals(Object.class)) { return "unknown"; |