aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/skylarkdebug/server/DebuggerSerialization.java71
-rw-r--r--src/test/java/com/google/devtools/build/lib/skylarkdebug/server/BUILD1
-rw-r--r--src/test/java/com/google/devtools/build/lib/skylarkdebug/server/DebuggerSerializationTest.java58
3 files changed, 108 insertions, 22 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/DebuggerSerialization.java b/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/DebuggerSerialization.java
index 0bc7b6fb01..75d7e00c8f 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/DebuggerSerialization.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/DebuggerSerialization.java
@@ -19,13 +19,16 @@ import com.google.common.collect.Ordering;
import com.google.devtools.build.lib.collect.nestedset.NestedSetView;
import com.google.devtools.build.lib.skylarkdebugging.SkylarkDebuggingProtos;
import com.google.devtools.build.lib.skylarkdebugging.SkylarkDebuggingProtos.Value;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.ClassObject;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.EvalUtils;
+import com.google.devtools.build.lib.syntax.FuncallExpression;
import com.google.devtools.build.lib.syntax.Printer;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
import java.lang.reflect.Array;
import java.util.Map;
+import java.util.Set;
/** Helper class for creating {@link SkylarkDebuggingProtos.Value} from skylark objects. */
final class DebuggerSerialization {
@@ -50,16 +53,7 @@ final class DebuggerSerialization {
return Printer.repr(value);
}
- private static Value errorValue(String errorMessage) {
- return Value.newBuilder().setLabel("Error").setDescription(errorMessage).build();
- }
-
private static boolean hasChildren(Object value) {
- if (value instanceof ClassObject) {
- // assuming ClassObject's have at least one child as a temporary optimization
- // TODO(bazel-team): remove once child-listing logic is moved to SkylarkValue
- return true;
- }
if (value instanceof SkylarkNestedSet) {
return true;
}
@@ -78,15 +72,16 @@ final class DebuggerSerialization {
if (value.getClass().isArray()) {
return Array.getLength(value) > 0;
}
+ if (value instanceof ClassObject || value instanceof SkylarkValue) {
+ // assuming ClassObject's have at least one child as a temporary optimization
+ // TODO(bazel-team): remove once child-listing logic is moved to SkylarkValue
+ return true;
+ }
// fallback to assuming there are no children
return false;
}
static ImmutableList<Value> getChildren(ThreadObjectMap objectMap, Object value) {
- // TODO(bazel-team): move child-listing logic to SkylarkValue where practical
- if (value instanceof ClassObject) {
- return getChildren(objectMap, (ClassObject) value);
- }
if (value instanceof SkylarkNestedSet) {
return getChildren(objectMap, (SkylarkNestedSet) value);
}
@@ -105,6 +100,13 @@ final class DebuggerSerialization {
if (value.getClass().isArray()) {
return getArrayChildren(objectMap, value);
}
+ // TODO(bazel-team): move child-listing logic to SkylarkValue where practical
+ if (value instanceof ClassObject) {
+ return getChildren(objectMap, (ClassObject) value);
+ }
+ if (value instanceof SkylarkValue) {
+ return getChildren(objectMap, (SkylarkValue) value);
+ }
// fallback to assuming there are no children
return ImmutableList.of();
}
@@ -115,26 +117,51 @@ final class DebuggerSerialization {
ImmutableList<String> keys;
try {
keys = Ordering.natural().immutableSortedCopy(classObject.getFieldNames());
- } catch (EvalException e) {
- return ImmutableList.of(errorValue("Error retrieving field names: " + e.getMessage()));
+ } catch (EvalException | IllegalArgumentException e) {
+ // silently return no children
+ return ImmutableList.of();
}
for (String key : keys) {
Object value;
try {
value = classObject.getValue(key);
- } catch (EvalException e) {
- return ImmutableList.of(
- errorValue(
- String.format("Error retrieving value for field '%s': %s", key, e.getMessage())));
- }
- if (value != null) {
- builder.add(getValueProto(objectMap, key, value));
+ if (value != null) {
+ builder.add(getValueProto(objectMap, key, value));
+ }
+ } catch (EvalException | IllegalArgumentException e) {
+ // silently ignore errors
}
}
return builder.build();
}
private static ImmutableList<Value> getChildren(
+ ThreadObjectMap objectMap, SkylarkValue skylarkValue) {
+ Set<String> fieldNames;
+ try {
+ fieldNames = FuncallExpression.getStructFieldNames(skylarkValue.getClass());
+ } catch (IllegalArgumentException e) {
+ // silently return no children
+ return ImmutableList.of();
+ }
+ ImmutableList.Builder<Value> children = ImmutableList.builder();
+ for (String fieldName : fieldNames) {
+ FuncallExpression.MethodDescriptor method =
+ FuncallExpression.getStructField(skylarkValue.getClass(), fieldName);
+ try {
+ children.add(
+ getValueProto(
+ objectMap,
+ fieldName,
+ FuncallExpression.invokeStructField(method, fieldName, skylarkValue)));
+ } catch (EvalException | InterruptedException | IllegalArgumentException e) {
+ // silently ignore errors
+ }
+ }
+ return children.build();
+ }
+
+ private static ImmutableList<Value> getChildren(
ThreadObjectMap objectMap, SkylarkNestedSet nestedSet) {
Class<?> type = nestedSet.getContentType().getType();
return ImmutableList.<Value>builder()
diff --git a/src/test/java/com/google/devtools/build/lib/skylarkdebug/server/BUILD b/src/test/java/com/google/devtools/build/lib/skylarkdebug/server/BUILD
index 9f1ac0fa0b..376471f5f5 100644
--- a/src/test/java/com/google/devtools/build/lib/skylarkdebug/server/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/skylarkdebug/server/BUILD
@@ -63,6 +63,7 @@ java_test(
name = "DebuggerSerializationTest",
srcs = glob(["DebuggerSerializationTest.java"]),
deps = [
+ "//src/main/java/com/google/devtools/build/lib:skylarkinterface",
"//src/main/java/com/google/devtools/build/lib:syntax",
"//src/main/java/com/google/devtools/build/lib/collect/nestedset",
"//src/main/java/com/google/devtools/build/lib/skylarkdebug/proto:skylark_debugging_java_proto",
diff --git a/src/test/java/com/google/devtools/build/lib/skylarkdebug/server/DebuggerSerializationTest.java b/src/test/java/com/google/devtools/build/lib/skylarkdebug/server/DebuggerSerializationTest.java
index 52b208f076..4570ccb54b 100644
--- a/src/test/java/com/google/devtools/build/lib/skylarkdebug/server/DebuggerSerializationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skylarkdebug/server/DebuggerSerializationTest.java
@@ -23,6 +23,9 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.NestedSetView;
import com.google.devtools.build.lib.skylarkdebugging.SkylarkDebuggingProtos.Value;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.Printer;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
@@ -204,6 +207,61 @@ public final class DebuggerSerializationTest {
assertThat(getValueProto("name", new Object()).getHasChildren()).isFalse();
}
+ @Test
+ public void testSkylarkValue() {
+ DummyType dummy = new DummyType();
+
+ Value value = getValueProto("name", dummy);
+ assertTypeAndDescription(dummy, value);
+ assertThat(getChildren(value)).containsExactly(getValueProto("bool", true));
+ }
+
+ private static class DummyType implements SkylarkValue {
+ @Override
+ public void repr(SkylarkPrinter printer) {
+ printer.append("DummyType");
+ }
+
+ @SkylarkCallable(name = "bool", doc = "Returns True", structField = true)
+ public boolean bool() {
+ return true;
+ }
+
+ public boolean anotherMethod() {
+ return false;
+ }
+ }
+
+ @Test
+ public void testSkipSkylarkCallableThrowingException() {
+ DummyTypeWithException dummy = new DummyTypeWithException();
+
+ Value value = getValueProto("name", dummy);
+ assertTypeAndDescription(dummy, value);
+ assertThat(getChildren(value)).containsExactly(getValueProto("bool", true));
+ }
+
+ private static class DummyTypeWithException implements SkylarkValue {
+ @Override
+ public void repr(SkylarkPrinter printer) {
+ printer.append("DummyTypeWithException");
+ }
+
+ @SkylarkCallable(name = "bool", doc = "Returns True", structField = true)
+ public boolean bool() {
+ return true;
+ }
+
+ @SkylarkCallable(name = "invalid", doc = "Throws exception!", structField = true)
+ public boolean invalid() {
+ throw new IllegalArgumentException();
+ }
+
+ public boolean anotherMethod() {
+ return false;
+ }
+ }
+
private static void assertTypeAndDescription(Object object, Value value) {
assertThat(value.getType()).isEqualTo(EvalUtils.getDataTypeName(object));
assertThat(value.getDescription()).isEqualTo(Printer.repr(object));