aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar cparsons <cparsons@google.com>2018-02-16 14:21:10 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2018-02-16 14:23:13 -0800
commit7ec3f21cad07c4b6726bf1ee89e808298e4959c9 (patch)
treebde139bf283b75f4dd023ae4896be23faec7c20e
parent50efbeb1a59a17ef23dd125540492518860971ff (diff)
Change Skylark's print() on a rule target to print the Skylark-exposed provider keys.
This change only affects printing a rule target directly -- it intentionally does not affect the behavior of str(target), as we want to avoid skylark code being able to parse potentially-private provider keys. RELNOTES: In skylark, print(target) now shows the provider keys of a target, as debug information. PiperOrigin-RevId: 186046226
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java19
-rw-r--r--src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkPrintable.java20
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java13
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/Printer.java22
-rw-r--r--src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java40
5 files changed, 107 insertions, 7 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java
index 9c7ec8fb36..89881c4d6c 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/configuredtargets/RuleConfiguredTarget.java
@@ -13,7 +13,9 @@
// limitations under the License.
package com.google.devtools.build.lib.analysis.configuredtargets;
+import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Interner;
@@ -171,4 +173,21 @@ public final class RuleConfiguredTarget extends AbstractConfiguredTarget {
public void repr(SkylarkPrinter printer) {
printer.append("<target " + getLabel() + ">");
}
+
+ @Override
+ public void debugPrint(SkylarkPrinter printer) {
+ // Show the names of the provider keys that this target propagates.
+ // Provider key names might potentially be *private* information, and thus a comprehensive
+ // list of provider keys should not be exposed in any way other than for debug information.
+ printer.append("<target " + getLabel() + ", keys:[");
+ ImmutableList.Builder<String> skylarkProviderKeyStrings = ImmutableList.builder();
+ for (int providerIndex = 0; providerIndex < providers.getProviderCount(); providerIndex++) {
+ Object providerKey = providers.getProviderKeyAt(providerIndex);
+ if (providerKey instanceof Provider.Key) {
+ skylarkProviderKeyStrings.add(providerKey.toString());
+ }
+ }
+ printer.append(Joiner.on(", ").join(skylarkProviderKeyStrings.build()));
+ printer.append("]>");
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkPrintable.java b/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkPrintable.java
index 39760c4108..8edfbd58ec 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkPrintable.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkPrintable.java
@@ -21,7 +21,7 @@ package com.google.devtools.build.lib.skylarkinterface;
public interface SkylarkPrintable {
/**
- * Print an official representation of object x.
+ * Prints an official representation of object x.
*
* <p>For regular data structures, the value should be parsable back into an equal data structure.
*
@@ -30,7 +30,7 @@ public interface SkylarkPrintable {
void repr(SkylarkPrinter printer);
/**
- * Print an informal, human-readable representation of the value.
+ * Prints an informal, human-readable representation of the value.
*
* <p>By default dispatches to the {@code repr} method.
*
@@ -39,4 +39,20 @@ public interface SkylarkPrintable {
default void str(SkylarkPrinter printer) {
repr(printer);
}
+
+ /**
+ * Prints an informal debug representation of the value.
+ *
+ * <p>This debug representation is only ever printed to the terminal or to another out-of-band
+ * channel, and is never accessible to Skylark code. Therefore, it is safe for the debug
+ * representation to reveal properties of the value that are usually hidden for the sake of
+ * performance, determinism, or forward-compatibility.
+ *
+ * <p>By default dispatches to the {@code str} method.
+ *
+ * @param printer a printer to be used for formatting nested values.
+ */
+ default void debugPrint(SkylarkPrinter printer) {
+ str(printer);
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
index f3c0d5f3c1..b782926eb6 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
@@ -2113,12 +2113,15 @@ public class MethodLibrary {
name = "print",
returnType = Runtime.NoneType.class,
doc =
- "Prints <code>args</code> as output. It will be prefixed with the string <code>"
- + "\"DEBUG\"</code> and the location (file and line number) of this call. It can be "
- + "used for debugging."
+ "Prints <code>args</code> as debug output. It will be prefixed with the string <code>"
+ + "\"DEBUG\"</code> and the location (file and line number) of this call. The "
+ + "exact way in which the arguments are converted to strings is unspecified and may "
+ + "change at any time. In particular, it may be different from (and more detailed "
+ + "than) the formatting done by <a href='#str'><code>str()</code></a> and <a "
+ + "href='#repr'><code>repr()</code></a>."
+ "<p>Using <code>print</code> in production code is discouraged due to the spam it "
+ "creates for users. For deprecations, prefer a hard error using <a href=\"#fail\">"
- + "fail()</a> when possible.",
+ + "<code>fail()</code></a> whenever possible.",
parameters = {
@Param(
name = "sep",
@@ -2139,7 +2142,7 @@ public class MethodLibrary {
public Runtime.NoneType invoke(
String sep, SkylarkList<?> starargs, Location loc, Environment env)
throws EvalException {
- String msg = starargs.stream().map(Printer::str).collect(joining(sep));
+ String msg = starargs.stream().map(Printer::debugPrint).collect(joining(sep));
// As part of the integration test "skylark_flag_test.sh", if the
// "--internal_skylark_flag_test_canary" flag is enabled, append an extra marker string to
// the output.
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Printer.java b/src/main/java/com/google/devtools/build/lib/syntax/Printer.java
index 69b16fefc9..b2248f8940 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Printer.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Printer.java
@@ -73,6 +73,13 @@ public class Printer {
// These static methods proxy to the similar methods of BasePrinter
/**
+ * Format an object with Skylark's {@code debugPrint}.
+ */
+ public static String debugPrint(Object x) {
+ return getPrinter().debugPrint(x).toString();
+ }
+
+ /**
* Format an object with Skylark's {@code str}.
*/
public static String str(Object x) {
@@ -283,6 +290,21 @@ public class Printer {
}
/**
+ * Print an informal debug-only representation of object x.
+ *
+ * @param o the object
+ * @return the buffer, in fluent style
+ */
+ public BasePrinter debugPrint(Object o) {
+ if (o instanceof SkylarkValue) {
+ ((SkylarkValue) o).debugPrint(this);
+ return this;
+ }
+
+ return this.str(o);
+ }
+
+ /**
* Print an informal representation of object x. Currently only differs from repr in the
* behavior for strings and labels at top-level, that are returned as is rather than quoted.
*
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
index 6f8e3843b0..8764ac499e 100644
--- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkIntegrationTest.java
@@ -916,6 +916,46 @@ public class SkylarkIntegrationTest extends BuildViewTestCase {
}
@Test
+ public void testPrintProviderCollection() throws Exception {
+ scratch.file(
+ "test/skylark/rules.bzl",
+ "",
+ "FooInfo = provider()",
+ "BarInfo = provider()",
+ "",
+ "def _top_level_rule_impl(ctx):",
+ " print('My Dep Providers:', ctx.attr.my_dep)",
+ "",
+ "def _dep_rule_impl(name):",
+ " providers = [",
+ " FooInfo(),",
+ " BarInfo(),",
+ " ]",
+ " return providers",
+ "",
+ "top_level_rule = rule(",
+ " implementation=_top_level_rule_impl,",
+ " attrs={'my_dep':attr.label()}",
+ ")",
+ "",
+ "dep_rule = rule(",
+ " implementation=_dep_rule_impl,",
+ ")");
+
+ scratch.file(
+ "test/skylark/BUILD",
+ "load('//test/skylark:rules.bzl', 'top_level_rule', 'dep_rule')",
+ "",
+ "top_level_rule(name = 'tl', my_dep=':d')",
+ "",
+ "dep_rule(name = 'd')");
+
+ getConfiguredTarget("//test/skylark:tl");
+ assertContainsEvent(
+ "My Dep Providers: <target //test/skylark:d, keys:[FooInfo, BarInfo, OutputGroupInfo]>");
+ }
+
+ @Test
public void testRuleClassImplicitOutputFunctionPrints() throws Exception {
scratch.file(
"test/skylark/extension.bzl",