aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/skylarkdebug
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2018-05-18 06:59:57 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-05-18 07:01:46 -0700
commit72d62bcaf58056db343f357c4591fbfd3baf999f (patch)
tree4aa14fbf696eb431648ee78951466e814831ee3c /src/main/java/com/google/devtools/build/lib/skylarkdebug
parent7a71ce816bc8a67a63c2d147ac953ac451ebd23b (diff)
Skylark debug server: add serialization code
Small self-contained part of the debug server (see unknown commit for the larger picture). PiperOrigin-RevId: 197140094
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/skylarkdebug')
-rw-r--r--src/main/java/com/google/devtools/build/lib/skylarkdebug/server/BUILD20
-rw-r--r--src/main/java/com/google/devtools/build/lib/skylarkdebug/server/DebuggerSerialization.java140
2 files changed, 160 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/BUILD b/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/BUILD
new file mode 100644
index 0000000000..42768bb69d
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/BUILD
@@ -0,0 +1,20 @@
+package(default_visibility = ["//src:__subpackages__"])
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+ visibility = ["//src/main/java/com/google/devtools/build/lib:__pkg__"],
+)
+
+java_library(
+ name = "server",
+ srcs = glob(["*.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",
+ "//third_party:guava",
+ "//third_party:jsr305",
+ ],
+)
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
new file mode 100644
index 0000000000..70d716332a
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/DebuggerSerialization.java
@@ -0,0 +1,140 @@
+// Copyright 2018 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.skylarkdebug.server;
+
+import com.google.common.collect.ImmutableList;
+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.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.Printer;
+import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import java.lang.reflect.Array;
+import java.util.Map;
+
+/** Helper class for creating {@link SkylarkDebuggingProtos.Value} from skylark objects. */
+final class DebuggerSerialization {
+
+ static Value getValueProto(String label, Object value) {
+ // TODO(bazel-team): prune cycles, and provide a way to limit breadth/depth of children reported
+ return Value.newBuilder()
+ .setLabel(label)
+ // TODO(bazel-team): omit type details for non-Skylark values
+ .setType(EvalUtils.getDataTypeName(value))
+ .setDescription(Printer.repr(value))
+ .addAllChild(getChildren(value))
+ .build();
+ }
+
+ private static Value errorValue(String errorMessage) {
+ return Value.newBuilder().setLabel("Error").setDescription(errorMessage).build();
+ }
+
+ private static ImmutableList<Value> getChildren(Object value) {
+ // TODO(bazel-team): move child-listing logic to SkylarkValue where practical
+ if (value instanceof ClassObject) {
+ return getChildren((ClassObject) value);
+ }
+ if (value instanceof SkylarkNestedSet) {
+ return getChildren((SkylarkNestedSet) value);
+ }
+ if (value instanceof NestedSetView) {
+ return getChildren((NestedSetView) value);
+ }
+ if (value instanceof Map) {
+ return getChildren(((Map) value).entrySet());
+ }
+ if (value instanceof Map.Entry) {
+ return getChildren((Map.Entry) value);
+ }
+ if (value instanceof Iterable) {
+ return getChildren((Iterable) value);
+ }
+ if (value.getClass().isArray()) {
+ return getArrayChildren(value);
+ }
+ // fallback to assuming there are no children
+ return ImmutableList.of();
+ }
+
+ private static ImmutableList<Value> getChildren(ClassObject classObject) {
+ ImmutableList.Builder<Value> builder = ImmutableList.builder();
+ ImmutableList<String> keys;
+ try {
+ keys = Ordering.natural().immutableSortedCopy(classObject.getFieldNames());
+ } catch (EvalException e) {
+ return ImmutableList.of(errorValue("Error retrieving field names: " + e.getMessage()));
+ }
+ 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(key, value));
+ }
+ }
+ return builder.build();
+ }
+
+ private static ImmutableList<Value> getChildren(SkylarkNestedSet nestedSet) {
+ Class<?> type = nestedSet.getContentType().getType();
+ return ImmutableList.<Value>builder()
+ .add(
+ Value.newBuilder()
+ .setLabel("order")
+ .setType("Traversal order")
+ .setDescription(nestedSet.getOrder().getSkylarkName())
+ .build())
+ .addAll(getChildren(new NestedSetView<>(nestedSet.getSet(type))))
+ .build();
+ }
+
+ private static ImmutableList<Value> getChildren(NestedSetView<?> nestedSet) {
+ return ImmutableList.of(
+ getValueProto("directs", nestedSet.directs()),
+ getValueProto("transitives", nestedSet.transitives()));
+ }
+
+ private static ImmutableList<Value> getChildren(Map.Entry<?, ?> entry) {
+ return ImmutableList.of(
+ getValueProto("key", entry.getKey()), getValueProto("value", entry.getValue()));
+ }
+
+ private static ImmutableList<Value> getChildren(Iterable<?> iterable) {
+ ImmutableList.Builder<Value> builder = ImmutableList.builder();
+ int index = 0;
+ for (Object value : iterable) {
+ builder.add(getValueProto(String.format("[%d]", index++), value));
+ }
+ return builder.build();
+ }
+
+ private static ImmutableList<Value> getArrayChildren(Object array) {
+ ImmutableList.Builder<Value> builder = ImmutableList.builder();
+ int index = 0;
+ for (int i = 0; i < Array.getLength(array); i++) {
+ builder.add(getValueProto(String.format("[%d]", index++), Array.get(array, i)));
+ }
+ return builder.build();
+ }
+}