Create ValidationEnvironment from Environment
Allow ValidationEnvironment to be created from initial Environment so that
there is no need to manually keep two different sets of constructors in synch.
--
MOS_MIGRATED_REVID=101588695
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
index 543c71e..40253e5 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfiguredRuleClassProvider.java
@@ -229,7 +229,7 @@
* Used to make the label instances unique, so that we don't create a new
* instance for every rule.
*/
- private static LoadingCache<String, Label> LABELS = CacheBuilder.newBuilder().build(
+ private static final LoadingCache<String, Label> LABELS = CacheBuilder.newBuilder().build(
new CacheLoader<String, Label>() {
@Override
public Label load(String from) {
@@ -307,8 +307,9 @@
this.configurationCollectionFactory = configurationCollectionFactory;
this.prerequisiteValidator = prerequisiteValidator;
this.skylarkAccessibleJavaClasses = skylarkAccessibleJavaClasses;
- this.skylarkValidationEnvironment = SkylarkModules.getValidationEnvironment(
- skylarkAccessibleJavaClasses.keySet());
+ this.skylarkValidationEnvironment = new ValidationEnvironment(
+ // TODO(bazel-team): refactor constructors so we don't have those null-s
+ createSkylarkRuleClassEnvironment(null, null));
}
public PrerequisiteValidator getPrerequisiteValidator() {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java
index 470d666..df4876c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkModules.java
@@ -17,7 +17,6 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.packages.SkylarkNativeModule;
import com.google.devtools.build.lib.syntax.BaseFunction;
@@ -30,9 +29,7 @@
import com.google.devtools.build.lib.syntax.ValidationEnvironment;
import java.lang.reflect.Field;
-import java.util.HashSet;
import java.util.Map;
-import java.util.Set;
/**
* A class to handle all Skylark modules, to create and setup Validation and regular Environments.
@@ -111,32 +108,17 @@
for (Map.Entry<String, Object> entry : OBJECTS.entrySet()) {
env.update(entry.getKey(), entry.getValue());
}
+ // Even though PACKAGE_NAME has no value _now_ and will be bound later,
+ // it needs to be visible for the ValidationEnvironment to be happy.
+ env.update(Environment.PKG_NAME, Environment.NONE);
}
/**
* Returns a new ValidationEnvironment with the elements of the Skylark modules.
*/
public static ValidationEnvironment getValidationEnvironment() {
- return getValidationEnvironment(ImmutableSet.<String>of());
- }
-
- /**
- * Returns a new ValidationEnvironment with the elements of the Skylark modules and extraObjects.
- */
- public static ValidationEnvironment getValidationEnvironment(ImmutableSet<String> extraObjects) {
- Set<String> builtIn = new HashSet<>();
- collectSkylarkTypesFromFields(Environment.class, builtIn);
- for (Class<?> moduleClass : MODULES) {
- if (moduleClass.isAnnotationPresent(SkylarkModule.class)) {
- builtIn.add(moduleClass.getAnnotation(SkylarkModule.class).name());
- }
- }
- MethodLibrary.setupValidationEnvironment(builtIn);
- for (Class<?> module : MODULES) {
- collectSkylarkTypesFromFields(module, builtIn);
- }
- builtIn.addAll(extraObjects);
- return new ValidationEnvironment(builtIn);
+ // TODO(bazel-team): refactor constructors so we don't have those null-s
+ return new ValidationEnvironment(getNewEnvironment(null));
}
public static EvaluationContext newEvaluationContext(EventHandler eventHandler) {
@@ -170,24 +152,4 @@
throw new RuntimeException(e);
}
}
-
- /**
- * Collects the BaseFunctions from the fields of the class of the object parameter
- * and adds their class and their corresponding return value to the builder.
- */
- private static void collectSkylarkTypesFromFields(Class<?> classObject, Set<String> builtIn) {
- for (Field field : classObject.getDeclaredFields()) {
- if (field.isAnnotationPresent(SkylarkSignature.class)) {
- SkylarkSignature annotation = field.getAnnotation(SkylarkSignature.class);
- if (BaseFunction.class.isAssignableFrom(field.getType())) {
- // Ignore non-global values.
- if (annotation.objectType().equals(Object.class)) {
- builtIn.add(annotation.name());
- }
- } else {
- builtIn.add(annotation.name());
- }
- }
- }
- }
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java b/src/main/java/com/google/devtools/build/lib/syntax/Environment.java
index 5357d4d..3acbec1 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Environment.java
@@ -101,6 +101,15 @@
protected Set<String> propagatingVariables = new HashSet<>();
/**
+ * Is this a global environment?
+ * @return true if this is a global (top-level) environment
+ * as opposed to inside the body of a function
+ */
+ public boolean isGlobal() {
+ return true;
+ }
+
+ /**
* An EventHandler for errors and warnings. This is not used in the BUILD language,
* however it might be used in Skylark code called from the BUILD language.
*/
@@ -191,9 +200,10 @@
* Updates the value of variable "varname" in the environment, corresponding
* to an {@link AssignmentStatement}.
*/
- public void update(String varname, Object value) {
+ public Environment update(String varname, Object value) {
Preconditions.checkNotNull(value, "update(value == null)");
env.put(varname, value);
+ return this;
}
/**
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkEnvironment.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkEnvironment.java
index c292389..8e2a5c3 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkEnvironment.java
@@ -119,7 +119,7 @@
* Clones this Skylark global environment.
*/
public SkylarkEnvironment cloneEnv(EventHandler eventHandler) {
- Preconditions.checkArgument(isGlobalEnvironment());
+ Preconditions.checkArgument(isGlobal());
SkylarkEnvironment newEnv = new SkylarkEnvironment(eventHandler, this.fileContentHashCode);
for (Entry<String, Object> entry : env.entrySet()) {
newEnv.env.put(entry.getKey(), entry.getValue());
@@ -142,7 +142,8 @@
/**
* Returns true if this is a Skylark global environment.
*/
- public boolean isGlobalEnvironment() {
+ @Override
+ public boolean isGlobal() {
return parent == null;
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java b/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java
index 7aedca2..9b71f96 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/ValidationEnvironment.java
@@ -47,13 +47,21 @@
// Whether this validation environment is not modified therefore clonable or not.
private boolean clonable;
-
+
/**
* Tracks the number of nested for loops that contain the statement that is currently being
* validated
*/
private int loopCount = 0;
+ /**
+ * Create a ValidationEnvironment for a given global Environment
+ */
+ public ValidationEnvironment(Environment env) {
+ this(env.getVariableNames());
+ Preconditions.checkArgument(env.isGlobal());
+ }
+
public ValidationEnvironment(Set<String> builtinVariables) {
parent = null;
variables.addAll(builtinVariables);
@@ -135,7 +143,7 @@
/**
* Starts a session with temporarily disabled readonly checking for variables between branches.
* This is useful to validate control flows like if-else when we know that certain parts of the
- * code cannot both be executed.
+ * code cannot both be executed.
*/
public void startTemporarilyDisableReadonlyCheckSession() {
futureReadOnlyVariables.add(new HashSet<String>());
@@ -190,14 +198,14 @@
public boolean isInsideLoop() {
return (loopCount > 0);
}
-
+
/**
* Signals that the block of a for loop was entered
*/
public void enterLoop() {
++loopCount;
}
-
+
/**
* Signals that the block of a for loop was left
*