From 6696db2a5b880a69f14c395c0eb0af72986883a3 Mon Sep 17 00:00:00 2001 From: Jon Brandvein Date: Tue, 4 Oct 2016 20:18:19 +0000 Subject: Refactor getAnnotationFromParentClass() to a new SkylarkInterfaceUtils module -- MOS_MIGRATED_REVID=135144084 --- .../skylarkinterface/SkylarkInterfaceUtils.java | 73 ++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkInterfaceUtils.java (limited to 'src/main/java/com/google/devtools/build/lib/skylarkinterface') 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); + } +} -- cgit v1.2.3