Repository: kythe/kythe
Pull request #4707 (2020-10-09 22:46:22)

feat(common): add kytheuri CorpusPath helpers


Patch:
diff --git a/kythe/go/util/kytheuri/BUILD b/kythe/go/util/kytheuri/BUILD
index 81ae17fdc..bb0dd4cf2 100644
--- a/kythe/go/util/kytheuri/BUILD
+++ b/kythe/go/util/kytheuri/BUILD
@@ -10,7 +10,10 @@ go_library(
         "escape.go",
         ":uri.go",
     ],
-    deps = ["//kythe/proto:storage_go_proto"],
+    deps = [
+        "//kythe/proto:common_go_proto",
+        "//kythe/proto:storage_go_proto",
+    ],
 )
 
 go_test(
diff --git a/kythe/go/util/kytheuri/uri.go b/kythe/go/util/kytheuri/uri.go
index c6c1866a7..15870b832 100644
--- a/kythe/go/util/kytheuri/uri.go
+++ b/kythe/go/util/kytheuri/uri.go
@@ -25,6 +25,7 @@ import (
 	"path"
 	"strings"
 
+	cpb "kythe.io/kythe/proto/common_go_proto"
 	spb "kythe.io/kythe/proto/storage_go_proto"
 )
 
@@ -154,6 +155,18 @@ func FromVName(v *spb.VName) *URI {
 	}
 }
 
+// FromCorpusPath returns a Kythe URI for the given Kythe VName protobuf message.
+func FromCorpusPath(cp *cpb.CorpusPath) *URI {
+	if cp == nil {
+		return &URI{}
+	}
+	return &URI{
+		Corpus: cp.Corpus,
+		Root:   cp.Root,
+		Path:   cp.Path,
+	}
+}
+
 // cleanPath is as path.Clean, but leaves "" alone.
 func cleanPath(s string) string {
 	if s == "" {
diff --git a/kythe/java/com/google/devtools/kythe/util/BUILD b/kythe/java/com/google/devtools/kythe/util/BUILD
index 5ffa6a3f0..79f64eef8 100644
--- a/kythe/java/com/google/devtools/kythe/util/BUILD
+++ b/kythe/java/com/google/devtools/kythe/util/BUILD
@@ -31,6 +31,7 @@ java_library(
     srcs = ["KytheURI.java"],
     visibility = ["//kythe:proto_visibility"],
     deps = [
+        "//kythe/proto:common_java_proto",
         "//kythe/proto:storage_java_proto",
         "//third_party/guava",
         "@com_google_protobuf//:protobuf_java",
diff --git a/kythe/java/com/google/devtools/kythe/util/KytheURI.java b/kythe/java/com/google/devtools/kythe/util/KytheURI.java
index b80b664df..5f4984690 100644
--- a/kythe/java/com/google/devtools/kythe/util/KytheURI.java
+++ b/kythe/java/com/google/devtools/kythe/util/KytheURI.java
@@ -25,6 +25,7 @@ import com.google.common.base.Joiner;
 import com.google.common.base.Splitter;
 import com.google.common.escape.Escaper;
 import com.google.common.net.PercentEscaper;
+import com.google.devtools.kythe.proto.CorpusPath;
 import com.google.devtools.kythe.proto.Storage.VName;
 import java.io.Serializable;
 import java.net.URLDecoder;
@@ -76,6 +77,16 @@ public class KytheURI implements Serializable {
     this.vName = vName;
   }
 
+  /** Unpacks a {@link CorpusPath} into a new {@link KytheURI}. */
+  public KytheURI(CorpusPath cp) {
+    this(
+        VName.newBuilder()
+            .setCorpus(cp.getCorpus())
+            .setRoot(cp.getRoot())
+            .setPath(cp.getPath())
+            .build());
+  }
+
   /** Returns the {@link KytheURI}'s signature. */
   public String getSignature() {
     return vName.getSignature();
@@ -147,6 +158,11 @@ public class KytheURI implements Serializable {
     return new KytheURI(vName).toString();
   }
 
+  /** Returns an equivalent Kythe ticket for the given {@link CorpusPath}. */
+  public static String asString(CorpusPath cp) {
+    return new KytheURI(cp).toString();
+  }
+
   /** Parses the given string to produce a new {@link KytheURI}. */
   public static KytheURI parse(String str) {
     checkNotNull(str, "str must be non-null");


Test patch:
diff --git a/kythe/go/util/kytheuri/uri_test.go b/kythe/go/util/kytheuri/uri_test.go
index ceab35927..534262480 100644
--- a/kythe/go/util/kytheuri/uri_test.go
+++ b/kythe/go/util/kytheuri/uri_test.go
@@ -22,6 +22,7 @@ import (
 
 	"google.golang.org/protobuf/proto"
 
+	cpb "kythe.io/kythe/proto/common_go_proto"
 	spb "kythe.io/kythe/proto/storage_go_proto"
 )
 
@@ -211,6 +212,28 @@ func TestToString(t *testing.T) {
 	}
 }
 
+func TestCorpusPath(t *testing.T) {
+	tests := []struct {
+		CorpusPath *cpb.CorpusPath
+		Expected   string
+	}{
+		{&cpb.CorpusPath{Corpus: "c", Root: "r", Path: "p"}, "kythe://c?path=p?root=r"},
+		{&cpb.CorpusPath{Corpus: "", Root: "r", Path: "p"}, "kythe:?path=p?root=r"},
+		{&cpb.CorpusPath{Corpus: "", Root: "", Path: "p"}, "kythe:?path=p"},
+		{&cpb.CorpusPath{Corpus: "", Root: "", Path: ""}, "kythe:"},
+		{&cpb.CorpusPath{Corpus: "c", Root: "r", Path: ""}, "kythe://c?root=r"},
+		{&cpb.CorpusPath{Corpus: "c", Root: "", Path: ""}, "kythe://c"},
+		{&cpb.CorpusPath{Corpus: "", Root: "r", Path: ""}, "kythe:?root=r"},
+		{&cpb.CorpusPath{Corpus: "c", Root: "", Path: "p"}, "kythe://c?path=p"},
+	}
+
+	for _, test := range tests {
+		if found := FromCorpusPath(test.CorpusPath).String(); found != test.Expected {
+			t.Errorf("kytheuri.FromCorpusPath(%+v): found %q, want %q", test.CorpusPath, found, test.Expected)
+		}
+	}
+}
+
 func TestRoundTripVName(t *testing.T) {
 	// Verify that converting a VName to a Kythe URI and then back preserves
 	// equivalence.
diff --git a/kythe/javatests/com/google/devtools/kythe/util/BUILD b/kythe/javatests/com/google/devtools/kythe/util/BUILD
index a0c7992b5..1e545f6dc 100644
--- a/kythe/javatests/com/google/devtools/kythe/util/BUILD
+++ b/kythe/javatests/com/google/devtools/kythe/util/BUILD
@@ -40,6 +40,7 @@ java_test(
     test_class = "com.google.devtools.kythe.util.KytheURITest",
     deps = [
         "//kythe/java/com/google/devtools/kythe/util:kythe_uri",
+        "//kythe/proto:common_java_proto",
         "//kythe/proto:storage_java_proto",
         "//third_party/truth",
         "@com_google_protobuf//:protobuf_java",
diff --git a/kythe/javatests/com/google/devtools/kythe/util/KytheURITest.java b/kythe/javatests/com/google/devtools/kythe/util/KytheURITest.java
index f085c87a8..7975a5fa4 100644
--- a/kythe/javatests/com/google/devtools/kythe/util/KytheURITest.java
+++ b/kythe/javatests/com/google/devtools/kythe/util/KytheURITest.java
@@ -19,6 +19,7 @@ package com.google.devtools.kythe.util;
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import com.google.devtools.kythe.proto.CorpusPath;
 import com.google.devtools.kythe.proto.Storage.VName;
 import java.net.URISyntaxException;
 import junit.framework.TestCase;
@@ -108,6 +109,16 @@ public class KytheURITest extends TestCase {
         "kythe://a?path=c#sig", "kythe://a?path=b/../c#sig", "kythe://a?path=./d/.././c#sig");
   }
 
+  public void testCorpusPath() {
+    assertThat(KytheURI.asString(cp("", "", ""))).isEqualTo("kythe:");
+    assertThat(KytheURI.asString(cp("c", "", ""))).isEqualTo("kythe://c");
+    assertThat(KytheURI.asString(cp("c", "r", ""))).isEqualTo("kythe://c?root=r");
+    assertThat(KytheURI.asString(cp("c", "r", "p"))).isEqualTo("kythe://c?path=p?root=r");
+    assertThat(KytheURI.asString(cp("c", "", "p"))).isEqualTo("kythe://c?path=p");
+    assertThat(KytheURI.asString(cp("", "r", "p"))).isEqualTo("kythe:?path=p?root=r");
+    assertThat(KytheURI.asString(cp("", "", "p"))).isEqualTo("kythe:?path=p");
+  }
+
   public void testToStringGoCompatibility() {
     // Test cases added when an incompatibility with Go's kytheuri library is found.
     assertThat(builder().setSignature("a=").build().toString()).isEqualTo("kythe:#a%3D");
@@ -185,4 +196,8 @@ public class KytheURITest extends TestCase {
   private static KytheURI parse(String str) throws URISyntaxException {
     return KytheURI.parse(str);
   }
+
+  private static CorpusPath cp(String corpus, String root, String path) {
+    return CorpusPath.newBuilder().setCorpus(corpus).setRoot(root).setPath(path).build();
+  }
 }