diff options
author | 2016-10-04 20:18:19 +0000 | |
---|---|---|
committer | 2016-10-05 12:26:10 +0000 | |
commit | 6696db2a5b880a69f14c395c0eb0af72986883a3 (patch) | |
tree | f2e00ec3588ac8ec2c562c893b4a76c6680cb01e /src/main/java/com/google/devtools/build/lib/skylarkinterface | |
parent | e67ea04d92f04d15e0e33d41e000a9d22cc21049 (diff) |
Refactor getAnnotationFromParentClass() to a new SkylarkInterfaceUtils module
--
MOS_MIGRATED_REVID=135144084
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skylarkinterface')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkInterfaceUtils.java | 73 |
1 files changed, 73 insertions, 0 deletions
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 new file mode 100644 index 0000000000..95d4f4fcf5 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkInterfaceUtils.java @@ -0,0 +1,73 @@ +// Copyright 2016 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.skylarkinterface; + +import java.lang.reflect.Method; +import javax.annotation.Nullable; + +/** + * Helpers for accessing Skylark interface annotations. + */ +public class SkylarkInterfaceUtils { + + /** + * 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 + * will be returned, starting with {@code classObj} and following its base classes and + * interfaces recursively. + */ + @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; + } + if (keepLooking) { + 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; + } + } + } + return null; + } + + /** + * Convenience version of {@code getAnnotationsFromParentClass(Class, Method)} that uses + * the declaring class of the method. + */ + @Nullable + public static SkylarkCallable getSkylarkCallable(Method method) { + return getSkylarkCallable(method.getDeclaringClass(), method); + } +} |