diff options
author | 2016-08-10 18:29:04 +0000 | |
---|---|---|
committer | 2016-08-11 09:14:21 +0000 | |
commit | 8a07a959e10040642cdf2e6fa21edcd6a1e9212b (patch) | |
tree | e0109611dcfe55906c217b86aa411d7a74670185 /src/main/java/com/google/devtools/build/lib/packages | |
parent | f2f8408c4fa242ceb9352b49e50eb09863285dca (diff) |
Add 'provider()' function.
--
MOS_MIGRATED_REVID=129889793
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/packages')
4 files changed, 129 insertions, 9 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkAspect.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkAspect.java index 1a785092b4..be74013e5e 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/SkylarkAspect.java +++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkAspect.java @@ -20,14 +20,12 @@ import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; -import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; import com.google.devtools.build.lib.syntax.BaseFunction; import com.google.devtools.build.lib.syntax.Environment; import com.google.devtools.build.lib.syntax.Printer; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.Pair; import com.google.devtools.build.lib.util.Preconditions; - import javax.annotation.Nullable; /** A Skylark value that is a result of an 'aspect(..)' function call. */ @@ -39,7 +37,7 @@ import javax.annotation.Nullable; + "documentation of the aspect function</a> or the " + "<a href=\"../aspects.md\">introduction to Aspects</a>." ) -public class SkylarkAspect implements SkylarkValue { +public class SkylarkAspect implements SkylarkExportable { private final BaseFunction implementation; private final ImmutableList<String> attributeAspects; private final ImmutableList<Attribute> attributes; @@ -107,6 +105,7 @@ public class SkylarkAspect implements SkylarkValue { return paramAttributes; } + @Override public void export(Label extensionLabel, String name) { Preconditions.checkArgument(!isExported()); this.aspectClass = new SkylarkAspectClass(extensionLabel, name); @@ -137,6 +136,7 @@ public class SkylarkAspect implements SkylarkValue { return builder.build(); } + @Override public boolean isExported() { return aspectClass != null; } diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkClassObject.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkClassObject.java index f5190965b7..5e5183cbc6 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/SkylarkClassObject.java +++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkClassObject.java @@ -124,6 +124,10 @@ public class SkylarkClassObject implements ClassObject, SkylarkValue, Concatable return StructConcatter.INSTANCE; } + public SkylarkClassObjectConstructor getConstructor() { + return constructor; + } + private static class StructConcatter implements Concatter { private static final StructConcatter INSTANCE = new StructConcatter(); @@ -134,6 +138,12 @@ public class SkylarkClassObject implements ClassObject, SkylarkValue, Concatable Concatable left, Concatable right, Location loc) throws EvalException { SkylarkClassObject lval = (SkylarkClassObject) left; SkylarkClassObject rval = (SkylarkClassObject) right; + if (!lval.constructor.equals(rval.constructor)) { + throw new EvalException(loc, + String.format("Cannot concat %s with %s", + lval.constructor.getPrintableName(), + rval.constructor.getPrintableName())); + } SetView<String> commonFields = Sets .intersection(lval.values.keySet(), rval.values.keySet()); if (!commonFields.isEmpty()) { @@ -174,7 +184,7 @@ public class SkylarkClassObject implements ClassObject, SkylarkValue, Concatable @Override public void write(Appendable buffer, char quotationMark) { boolean first = true; - Printer.append(buffer, constructor.getName()); + Printer.append(buffer, constructor.getPrintableName()); Printer.append(buffer, "("); // Sort by key to ensure deterministic output. for (String key : Ordering.natural().sortedCopy(values.keySet())) { diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkClassObjectConstructor.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkClassObjectConstructor.java index b451efe583..d090c950a3 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/SkylarkClassObjectConstructor.java +++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkClassObjectConstructor.java @@ -14,22 +14,29 @@ package com.google.devtools.build.lib.packages; +import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.events.Location; +import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.syntax.BaseFunction; import com.google.devtools.build.lib.syntax.Environment; import com.google.devtools.build.lib.syntax.EvalException; import com.google.devtools.build.lib.syntax.FuncallExpression; import com.google.devtools.build.lib.syntax.FunctionSignature; -import com.google.devtools.build.lib.syntax.FunctionSignature.WithValues; import com.google.devtools.build.lib.syntax.SkylarkType; -import com.google.devtools.build.lib.syntax.Type.ConversionException; +import com.google.devtools.build.lib.util.Preconditions; import java.util.Map; +import java.util.Objects; import javax.annotation.Nullable; /** * A constructor for {@link SkylarkClassObject}. */ -public final class SkylarkClassObjectConstructor extends BaseFunction { +@SkylarkModule(name = "provider", + doc = "A constructor for simple value objects. " + + "See the global <a href=\"globals.html#provider\">provider</a> function " + + "for more details." +) +public final class SkylarkClassObjectConstructor extends BaseFunction implements SkylarkExportable { /** * "struct" function. */ @@ -38,7 +45,10 @@ public final class SkylarkClassObjectConstructor extends BaseFunction { private static final FunctionSignature.WithValues<Object, SkylarkType> SIGNATURE = - WithValues.create(FunctionSignature.KWARGS); + FunctionSignature.WithValues.create(FunctionSignature.KWARGS); + + @Nullable + private Key key; public SkylarkClassObjectConstructor(String name, Location location) { super(name, SIGNATURE, location); @@ -50,7 +60,7 @@ public final class SkylarkClassObjectConstructor extends BaseFunction { @Override protected Object call(Object[] args, @Nullable FuncallExpression ast, @Nullable Environment env) - throws EvalException, ConversionException, InterruptedException { + throws EvalException, InterruptedException { @SuppressWarnings("unchecked") Map<String, Object> kwargs = (Map<String, Object>) args[0]; return new SkylarkClassObject(this, kwargs, ast != null ? ast.getLocation() : Location.BUILTIN); @@ -65,6 +75,26 @@ public final class SkylarkClassObjectConstructor extends BaseFunction { } @Override + public boolean isExported() { + return key != null; + } + + @Nullable + public Key getKey() { + return key; + } + + public String getPrintableName() { + return key != null ? key.exportedName : getName(); + } + + @Override + public void export(Label extensionLabel, String exportedName) { + Preconditions.checkState(!isExported()); + this.key = new Key(extensionLabel, exportedName); + } + + @Override public int hashCode() { return System.identityHashCode(this); } @@ -73,4 +103,46 @@ public final class SkylarkClassObjectConstructor extends BaseFunction { public boolean equals(@Nullable Object other) { return other == this; } + + /** + * A serializable representation of {@link SkylarkClassObjectConstructor} + * that uniquely identifies all {@link SkylarkClassObjectConstructor}s that + * are exposed to SkyFrame. + */ + public static class Key { + private final Label extensionLabel; + private final String exportedName; + + public Key(Label extensionLabel, String exportedName) { + this.extensionLabel = Preconditions.checkNotNull(extensionLabel); + this.exportedName = Preconditions.checkNotNull(exportedName); + } + + public Label getExtensionLabel() { + return extensionLabel; + } + + public String getExportedName() { + return exportedName; + } + + @Override + public int hashCode() { + return Objects.hash(extensionLabel, exportedName); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof Key)) { + return false; + } + Key other = (Key) obj; + return Objects.equals(this.extensionLabel, other.extensionLabel) + && Objects.equals(this.exportedName, other.exportedName); + } + } } diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkExportable.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkExportable.java new file mode 100644 index 0000000000..003baa946d --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkExportable.java @@ -0,0 +1,38 @@ +// 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.packages; + +import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; +import com.google.devtools.build.lib.syntax.EvalException; + +/** + * {@link SkylarkValue}s that need special handling when they are + * exported from an extension file. For example, rule definitions + * receive their name at the end of the execution of the .bzl file. + */ +public interface SkylarkExportable extends SkylarkValue { + + /** + * Is this value already exported? + */ + boolean isExported(); + + /** + * Notify the value that it is exported from {@code extensionLabel} + * extension with name {@code exportedName}. + */ + void export(Label extensionLabel, String exportedName) throws EvalException; +} |