aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build
diff options
context:
space:
mode:
authorGravatar cparsons <cparsons@google.com>2018-04-23 12:04:09 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-04-23 12:05:19 -0700
commit981f65bf0a53239c8d5d55a1469c17721a12b2f4 (patch)
tree097d8c6faea51729bac0e9aee95b2d38eacbcd07 /src/main/java/com/google/devtools/build
parenta4852b5fbf09c40bfebfec6ed231ebeb11950194 (diff)
Start refactoring elements of the Skylark Build API into their own package.
RELNOTES: None. PiperOrigin-RevId: 193962460
Diffstat (limited to 'src/main/java/com/google/devtools/build')
-rw-r--r--src/main/java/com/google/devtools/build/lib/BUILD2
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/skylark/BazelBuildApiGlobals.java47
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkLateBoundDefault.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/skylarkbuildapi/BUILD28
-rw-r--r--src/main/java/com/google/devtools/build/lib/skylarkbuildapi/LateBoundDefaultApi.java24
-rw-r--r--src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkBuildApiGlobals.java (renamed from src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkBuildApiGlobals.java)24
-rw-r--r--src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkInterfaceUtils.java40
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/Runtime.java12
9 files changed, 145 insertions, 38 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index faa54bcb36..895ec859d2 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -56,6 +56,7 @@ filegroup(
"//src/main/java/com/google/devtools/build/lib/shell:srcs",
"//src/main/java/com/google/devtools/build/lib/skyframe/packages:srcs",
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization:srcs",
+ "//src/main/java/com/google/devtools/build/lib/skylarkbuildapi:srcs",
"//src/main/java/com/google/devtools/build/lib/skylarkdebug/proto:srcs",
"//src/main/java/com/google/devtools/build/lib/skylarkinterface/processor:srcs",
"//src/main/java/com/google/devtools/build/lib/ssd:srcs",
@@ -552,6 +553,7 @@ java_library(
"//src/main/java/com/google/devtools/build/lib/profiler/memory:current_rule_tracker",
"//src/main/java/com/google/devtools/build/lib/shell",
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec",
+ "//src/main/java/com/google/devtools/build/lib/skylarkbuildapi",
"//src/main/java/com/google/devtools/build/lib/vfs",
"//src/main/java/com/google/devtools/build/skyframe",
"//src/main/java/com/google/devtools/build/skyframe:skyframe-objects",
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/BazelBuildApiGlobals.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/BazelBuildApiGlobals.java
new file mode 100644
index 0000000000..efd87e7c10
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/BazelBuildApiGlobals.java
@@ -0,0 +1,47 @@
+// Copyright 2018 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.skylark;
+
+import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.skylarkbuildapi.SkylarkBuildApiGlobals;
+import com.google.devtools.build.lib.syntax.Environment;
+import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.SkylarkUtils;
+
+/**
+ * Bazel implementation of {@link SkylarkBuildApiGlobals}: a collection of global skylark build
+ * API functions that belong in the global namespace.
+ */
+public class BazelBuildApiGlobals implements SkylarkBuildApiGlobals {
+
+ @Override
+ public SkylarkLateBoundDefault<?> configurationField(
+ String fragment, String name, Location loc, Environment env)
+ throws EvalException {
+ Class<?> fragmentClass = SkylarkUtils.getFragmentMap(env).get(fragment);
+
+ if (fragmentClass == null) {
+ throw new EvalException(
+ loc,
+ String.format("invalid configuration fragment name '%s'", fragment));
+ }
+ try {
+ return SkylarkLateBoundDefault.forConfigurationField(
+ fragmentClass, name, SkylarkUtils.getToolsRepository(env));
+ } catch (SkylarkLateBoundDefault.InvalidConfigurationFieldException exception) {
+ throw new EvalException(loc, exception);
+ }
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkLateBoundDefault.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkLateBoundDefault.java
index 93fe96e32e..bf91cafbab 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkLateBoundDefault.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkLateBoundDefault.java
@@ -27,9 +27,9 @@ import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
+import com.google.devtools.build.lib.skylarkbuildapi.LateBoundDefaultApi;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
@@ -50,7 +50,7 @@ import javax.annotation.concurrent.Immutable;
@Immutable
@AutoCodec
public class SkylarkLateBoundDefault<FragmentT> extends AbstractLabelLateBoundDefault<FragmentT>
- implements SkylarkValue {
+ implements LateBoundDefaultApi {
private final Method method;
private final String fragmentName;
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java
index 17129ee6f4..a85893197e 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkModules.java
@@ -38,8 +38,8 @@ public final class SkylarkModules {
*/
public static final ImmutableList<Class<?>> MODULES =
ImmutableList.of(
+ BazelBuildApiGlobals.class,
SkylarkAttr.class,
- SkylarkBuildApiGlobals.class,
SkylarkCommandLine.class,
SkylarkNativeModule.class,
SkylarkRuleClassFunctions.class);
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/BUILD b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/BUILD
new file mode 100644
index 0000000000..492daee57e
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/BUILD
@@ -0,0 +1,28 @@
+# Description:
+# This package contains interfaces representing the skylark "build API"
+# (but not the implementation of that API). Ultimately, this package
+# may be broken out of the Bazel package hierarchy to be standalone.
+# Thus, this package should not depend on Bazel-specific packages (only
+# those which contain pure-Skylark concepts, such as the interpretter or
+# annotation interfaces).
+
+package(default_visibility = ["//src/main/java/com/google/devtools/build/lib:__pkg__"])
+
+licenses(["notice"]) # Apache 2.0
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+)
+
+java_library(
+ name = "skylarkbuildapi",
+ srcs = glob(["*.java"]),
+ deps = [
+ "//src/main/java/com/google/devtools/build/lib:events",
+ "//src/main/java/com/google/devtools/build/lib:skylarkinterface",
+ "//src/main/java/com/google/devtools/build/lib:syntax",
+ "//third_party:guava",
+ "//third_party:jsr305",
+ ],
+)
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/LateBoundDefaultApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/LateBoundDefaultApi.java
new file mode 100644
index 0000000000..080a16f1e3
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/LateBoundDefaultApi.java
@@ -0,0 +1,24 @@
+// Copyright 2018 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.skylarkbuildapi;
+
+import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
+
+/**
+ * The interface for late bound defaults in Skylark.
+ */
+public interface LateBoundDefaultApi extends SkylarkValue {
+ // TODO(cparsons): Migrate this API from the Bazel-specific implementation.
+}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkBuildApiGlobals.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkBuildApiGlobals.java
index a8851c92c4..fd24b7ff1e 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkBuildApiGlobals.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkBuildApiGlobals.java
@@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.devtools.build.lib.analysis.skylark;
-
+package com.google.devtools.build.lib.skylarkbuildapi;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skylarkinterface.Param;
@@ -21,13 +20,12 @@ import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkGlobalLibrary;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.EvalException;
-import com.google.devtools.build.lib.syntax.SkylarkUtils;
/**
* A collection of global skylark build API functions that belong in the global namespace.
*/
@SkylarkGlobalLibrary
-public class SkylarkBuildApiGlobals {
+public interface SkylarkBuildApiGlobals {
@SkylarkCallable(
name = "configuration_field",
@@ -52,21 +50,7 @@ public class SkylarkBuildApiGlobals {
useLocation = true,
useEnvironment = true
)
- public SkylarkLateBoundDefault<?> configurationField(
+ public LateBoundDefaultApi configurationField(
String fragment, String name, Location loc, Environment env)
- throws EvalException {
- Class<?> fragmentClass = SkylarkUtils.getFragmentMap(env).get(fragment);
-
- if (fragmentClass == null) {
- throw new EvalException(
- loc,
- String.format("invalid configuration fragment name '%s'", fragment));
- }
- try {
- return SkylarkLateBoundDefault.forConfigurationField(
- fragmentClass, name, SkylarkUtils.getToolsRepository(env));
- } catch (SkylarkLateBoundDefault.InvalidConfigurationFieldException exception) {
- throw new EvalException(loc, exception);
- }
- }
+ throws EvalException;
}
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 2c269a74d9..3ee297993a 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
@@ -14,6 +14,7 @@
package com.google.devtools.build.lib.skylarkinterface;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import javax.annotation.Nullable;
@@ -22,30 +23,32 @@ import javax.annotation.Nullable;
*/
public class SkylarkInterfaceUtils {
- private static final class ClassAndSkylarkModule {
+ private static final class ClassWithAnnotation<T extends Annotation> {
final Class<?> klass;
- final SkylarkModule skylarkModule;
+ final T annotation;
- ClassAndSkylarkModule(Class<?> klass, SkylarkModule skylarkModule) {
+ ClassWithAnnotation(Class<?> klass, T annotation) {
this.klass = klass;
- this.skylarkModule = skylarkModule;
+ this.annotation = annotation;
}
}
@Nullable
- private static ClassAndSkylarkModule searchForSkylarkModule(Class<?> classObj) {
- if (classObj.isAnnotationPresent(SkylarkModule.class)) {
- return new ClassAndSkylarkModule(classObj, classObj.getAnnotation(SkylarkModule.class));
+ private static <T extends Annotation> ClassWithAnnotation<T> searchForClassAnnotation(
+ Class<?> classObj,
+ Class<T> annotationClass) {
+ if (classObj.isAnnotationPresent(annotationClass)) {
+ return new ClassWithAnnotation<T>(classObj, classObj.getAnnotation(annotationClass));
}
Class<?> superclass = classObj.getSuperclass();
if (superclass != null) {
- ClassAndSkylarkModule result = searchForSkylarkModule(superclass);
+ ClassWithAnnotation<T> result = searchForClassAnnotation(superclass, annotationClass);
if (result != null) {
return result;
}
}
for (Class<?> interfaceObj : classObj.getInterfaces()) {
- ClassAndSkylarkModule result = searchForSkylarkModule(interfaceObj);
+ ClassWithAnnotation<T> result = searchForClassAnnotation(interfaceObj, annotationClass);
if (result != null) {
return result;
}
@@ -60,8 +63,9 @@ public class SkylarkInterfaceUtils {
*/
@Nullable
public static SkylarkModule getSkylarkModule(Class<?> classObj) {
- ClassAndSkylarkModule result = searchForSkylarkModule(classObj);
- return result == null ? null : result.skylarkModule;
+ ClassWithAnnotation<SkylarkModule> result =
+ searchForClassAnnotation(classObj, SkylarkModule.class);
+ return result == null ? null : result.annotation;
}
/**
@@ -71,11 +75,23 @@ public class SkylarkInterfaceUtils {
*/
@Nullable
public static Class<?> getParentWithSkylarkModule(Class<?> classObj) {
- ClassAndSkylarkModule result = searchForSkylarkModule(classObj);
+ ClassWithAnnotation<SkylarkModule> result =
+ searchForClassAnnotation(classObj, SkylarkModule.class);
return result == null ? null : result.klass;
}
/**
+ * Searches {@code classObj}'s class hierarchy and for a superclass or interface that
+ * is annotated with {@link SkylarkGlobalLibrary} (including possibly {@code classObj} itself),
+ * and returns true if one is found.
+ */
+ public static boolean hasSkylarkGlobalLibrary(Class<?> classObj) {
+ ClassWithAnnotation<SkylarkGlobalLibrary> result =
+ searchForClassAnnotation(classObj, SkylarkGlobalLibrary.class);
+ return result != null;
+ }
+
+ /**
* Returns the {@link SkylarkCallable} annotation for the given method, if it exists, and
* 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
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java b/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java
index c037db2781..86f95b38b7 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java
@@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkGlobalLibrary;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkInterfaceUtils;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
@@ -337,14 +338,19 @@ public final class Runtime {
* callables.</li>
* </ul>
*
+ * <p>On collisions, this method throws an {@link AssertionError}. Collisions may occur if
+ * multiple global libraries have functions of the same name, two modules of the same name
+ * are given, or if two subclasses of the same module are given.
+ *
* @param env the Environment into which to register fields.
* @param moduleClass the Class object containing globals.
*/
public static void setupModuleGlobals(Environment env, Class<?> moduleClass) {
try {
- if (moduleClass.isAnnotationPresent(SkylarkModule.class)) {
+ SkylarkModule skylarkModule = SkylarkInterfaceUtils.getSkylarkModule(moduleClass);
+ if (skylarkModule != null) {
env.setup(
- moduleClass.getAnnotation(SkylarkModule.class).name(),
+ skylarkModule.name(),
moduleClass.getConstructor().newInstance());
}
for (Field field : moduleClass.getDeclaredFields()) {
@@ -362,7 +368,7 @@ public final class Runtime {
}
}
}
- if (moduleClass.isAnnotationPresent(SkylarkGlobalLibrary.class)) {
+ if (SkylarkInterfaceUtils.hasSkylarkGlobalLibrary(moduleClass)) {
Object moduleInstance = moduleClass.getConstructor().newInstance();
for (String methodName : FuncallExpression.getMethodNames(moduleClass)) {
env.setup(methodName, FuncallExpression.getBuiltinCallable(moduleInstance, methodName));