aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
diff options
context:
space:
mode:
authorGravatar Dmitry Lomov <dslomov@google.com>2015-10-30 15:50:01 +0000
committerGravatar Florian Weikert <fwe@google.com>2015-11-02 16:53:19 +0000
commitc15ba2e54d0e17fe894bfeadb21228e0a76e9e40 (patch)
treed555d4802586c654771f646d2a04e11d3385256f /src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
parent1b175c478156b20c7e1a77200a5e7717a945d9f2 (diff)
Implement propagation along dependencies for Skylark aspects.
-- MOS_MIGRATED_REVID=106694515
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java141
1 files changed, 136 insertions, 5 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
index ddfe3ff7e5..b27fb45227 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleClassFunctions.java
@@ -28,6 +28,7 @@ import static com.google.devtools.build.lib.syntax.Type.STRING;
import static com.google.devtools.build.lib.syntax.Type.STRING_LIST;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@@ -40,7 +41,11 @@ import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.RunUnder;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
+import com.google.devtools.build.lib.cmdline.PackageIdentifier;
+import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.AspectClass;
+import com.google.devtools.build.lib.packages.AspectDefinition;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.Attribute.ConfigurationTransition;
import com.google.devtools.build.lib.packages.Attribute.LateBoundLabel;
@@ -83,6 +88,7 @@ import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.ExecutionException;
/**
@@ -336,12 +342,26 @@ public class SkylarkRuleClassFunctions {
returnType = SkylarkAspect.class,
documented = false, // TODO(dslomov): Experimental, document later.
mandatoryPositionals = {@Param(name = "implementation", type = BaseFunction.class)},
+ optionalPositionals = {
+ @Param(
+ name = "attr_aspects",
+ type = SkylarkList.class,
+ generic1 = String.class,
+ defaultValue = "[]"
+ )
+ },
useEnvironment = true
)
private static final BuiltinFunction aspect =
new BuiltinFunction("aspect") {
- public SkylarkAspect invoke(BaseFunction implementation, Environment funcallEnv) {
- return new SkylarkAspect(implementation, funcallEnv);
+ public SkylarkAspect invoke(
+ BaseFunction implementation, SkylarkList attributeAspects, Environment funcallEnv)
+ throws ConversionException {
+ ImmutableList.Builder<String> builder = ImmutableList.<String>builder();
+ for (Object attributeAspect : attributeAspects) {
+ builder.add(STRING.convert(attributeAspect, ""));
+ }
+ return new SkylarkAspect(implementation, builder.build(), funcallEnv);
}
};
@@ -399,14 +419,20 @@ public class SkylarkRuleClassFunctions {
}
}
- public static void exportRuleFunctions(Environment env, PathFragment skylarkFile) {
+ public static void exportRuleFunctionsAndAspects(Environment env, PackageIdentifier skylarkFile) {
for (String name : env.getGlobals().getDirectVariableNames()) {
try {
Object value = env.lookup(name);
if (value instanceof RuleFunction) {
RuleFunction function = (RuleFunction) value;
if (function.skylarkFile == null) {
- function.export(skylarkFile, name);
+ function.export(skylarkFile.getPackageFragment(), name);
+ }
+ }
+ if (value instanceof SkylarkAspect) {
+ SkylarkAspect skylarkAspect = (SkylarkAspect) value;
+ if (!skylarkAspect.isExported()) {
+ skylarkAspect.export(skylarkFile, name);
}
}
} catch (NoSuchVariableException e) {
@@ -539,10 +565,16 @@ public class SkylarkRuleClassFunctions {
*/
public static class SkylarkAspect implements SkylarkValue {
private final BaseFunction implementation;
+ private final ImmutableList<String> attributeAspects;
private final Environment funcallEnv;
+ private Exported exported;
- public SkylarkAspect(BaseFunction implementation, Environment funcallEnv) {
+ public SkylarkAspect(
+ BaseFunction implementation,
+ ImmutableList<String> attributeAspects,
+ Environment funcallEnv) {
this.implementation = implementation;
+ this.attributeAspects = attributeAspects;
this.funcallEnv = funcallEnv;
}
@@ -550,6 +582,10 @@ public class SkylarkRuleClassFunctions {
return implementation;
}
+ public ImmutableList<String> getAttributeAspects() {
+ return attributeAspects;
+ }
+
public Environment getFuncallEnv() {
return funcallEnv;
}
@@ -564,5 +600,100 @@ public class SkylarkRuleClassFunctions {
Printer.append(buffer, "Aspect:");
implementation.write(buffer, quotationMark);
}
+
+ public String getName() {
+ return exported != null ? exported.toString() : "<skylark aspect>";
+ }
+
+ void export(PackageIdentifier extensionFile, String name) {
+ this.exported = new Exported(extensionFile, name);
+ }
+
+ public boolean isExported() {
+ return exported != null;
+ }
+
+ private PackageIdentifier getExtensionFile() {
+ Preconditions.checkArgument(isExported());
+ return exported.extensionFile;
+ }
+
+ private String getExportedName() {
+ Preconditions.checkArgument(isExported());
+ return exported.name;
+ }
+
+ @Immutable
+ private static class Exported {
+ private final PackageIdentifier extensionFile;
+ private final String name;
+
+ public Exported(PackageIdentifier extensionFile, String name) {
+ this.extensionFile = extensionFile;
+ this.name = name;
+ }
+
+ public String toString() {
+ return extensionFile.toString() + "%" + name;
+ }
+ }
+ }
+
+ /**
+ * Implementation of an aspect class defined in Skylark.
+ */
+ @Immutable
+ public static final class SkylarkAspectClass implements AspectClass {
+ private final AspectDefinition aspectDefinition;
+ private final PackageIdentifier extensionFile;
+ private final String exportedName;
+
+ public SkylarkAspectClass(SkylarkAspect skylarkAspect) {
+ Preconditions.checkArgument(skylarkAspect.isExported(), "Skylark aspects must be exported");
+ AspectDefinition.Builder builder = new AspectDefinition.Builder(skylarkAspect.getName());
+ for (String attributeAspect : skylarkAspect.getAttributeAspects()) {
+ builder.attributeAspect(attributeAspect, this);
+ }
+ this.aspectDefinition = builder.build();
+
+ this.extensionFile = skylarkAspect.getExtensionFile();
+ this.exportedName = skylarkAspect.getExportedName();
+ }
+
+ @Override
+ public String getName() {
+ return aspectDefinition.getName();
+ }
+
+ @Override
+ public AspectDefinition getDefinition() {
+ return aspectDefinition;
+ }
+
+ public PackageIdentifier getExtensionFile() {
+ return extensionFile;
+ }
+
+ public String getExportedName() {
+ return exportedName;
+ }
+
+ public int hashCode() {
+ return Objects.hash(extensionFile, exportedName);
+ }
+
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof SkylarkAspectClass)) {
+ return false;
+ }
+
+ SkylarkAspectClass that = (SkylarkAspectClass) other;
+ return Objects.equals(this.extensionFile, that.extensionFile)
+ && Objects.equals(this.exportedName, that.exportedName);
+ }
+
}
}