Add `java_path`, `java_root`, and `full_classname` to `java_helper`

Factor `_java_segment_index` out of `_java_segments` in `java_helper.bzl` and expose `java_path`, `java_root`, and `full_classname` on `helper`.

PiperOrigin-RevId: 1001414882
Change-Id: I21b207bbbb437fe411700812092106100fb69bdf
diff --git a/java/common/rules/BUILD b/java/common/rules/BUILD
index 4c24d07..fa181d2 100644
--- a/java/common/rules/BUILD
+++ b/java/common/rules/BUILD
@@ -92,6 +92,7 @@
     srcs = [
         "BUILD",
         ":core_rules",
+        ":java_helper_bzl",
         ":java_single_jar_bzl",
         ":toolchain_rules",
         "//java/common/rules/impl:for_bazel_tests",
diff --git a/java/common/rules/impl/java_helper.bzl b/java/common/rules/impl/java_helper.bzl
index 5f89a8f..c7fb869 100644
--- a/java/common/rules/impl/java_helper.bzl
+++ b/java/common/rules/impl/java_helper.bzl
@@ -89,14 +89,14 @@
     return main_class
 
 def _canonical_class_from_target_name(ctx):
-    return _full_classname(helper.get_relative(ctx.label.package, ctx.label.name))
+    return _loading_phase_helper.full_classname(helper.get_relative(ctx.label.package, ctx.label.name))
 
 def _primary_class(ctx):
     if ctx.attr.srcs:
         main = ctx.label.name + ".java"
         for src in _test_srcs(ctx):
             if src.basename == main:
-                return _full_classname(_strip_extension(src))
+                return _loading_phase_helper.full_classname(_strip_extension(src))
     return _canonical_class_from_target_name(ctx)
 
 def _test_srcs(ctx):
@@ -111,11 +111,6 @@
         file.basename[:-(1 + len(file.extension))] if file.extension else file.basename
     )
 
-# TODO(b/465048589): once out of builtins, create a canonical implementation and remove duplicates in depot
-def _full_classname(path):
-    java_segments = _loading_phase_helper.java_segments(path)
-    return ".".join(java_segments) if java_segments != None else None
-
 def _test_classes(ctx):
     has_test_class = hasattr(ctx.attr, "test_class") and bool(ctx.attr.test_class)
     has_test_classes = hasattr(ctx.attr, "test_classes") and bool(ctx.attr.test_classes)
@@ -129,7 +124,7 @@
         classes = []
         for src in _test_srcs(ctx):
             if src.extension == "java":
-                cls = _full_classname(_strip_extension(src))
+                cls = _loading_phase_helper.full_classname(_strip_extension(src))
                 if cls == None:
                     return []
                 classes.append(cls)
@@ -310,4 +305,8 @@
     get_build_info = _get_build_info,
     get_relative = _loading_phase_helper.get_relative,
     has_target_constraints = _loading_phase_helper.has_target_constraints,
+    java_segments = _loading_phase_helper.java_segments,
+    java_path = _loading_phase_helper.java_path,
+    java_root = _loading_phase_helper.java_root,
+    full_classname = _loading_phase_helper.full_classname,
 )
diff --git a/java/common/rules/java_helper.bzl b/java/common/rules/java_helper.bzl
index 412292c..0c36be1 100644
--- a/java/common/rules/java_helper.bzl
+++ b/java/common/rules/java_helper.bzl
@@ -19,27 +19,27 @@
 
 # copybara: rules_java visibility
 
-def _java_segments(path):
+def _java_segment_index(path):
     if path.startswith("/"):
         fail("path must not be absolute: '%s'" % path)
+    segments = path.split("/")
     if path.startswith("third_party/java/"):
         # For third_party/java, try skipping past the first two segments and looking for a nested
         # source root, to relativize e.g. third_party/java/foo/java/resource into 'resource',
         # not 'foo/java/resource'.
-        segments = _java_segments_impl(path[len("third_party/java/"):])
-        if segments != None:
-            return segments
-    return _java_segments_impl(path)
+        idx = _java_segment_index_impl(segments[2:])
+        if idx >= 0:
+            return idx + 2
+    return _java_segment_index_impl(segments)
 
-def _java_segments_impl(path):
-    segments = path.split("/")
+def _java_segment_index_impl(segments):
     root_idx = -1
     for idx, segment in enumerate(segments):
         if segment in ["java", "javatests", "src", "testsrc"]:
             root_idx = idx
             break
     if root_idx < 0:
-        return None
+        return -1
     is_src = "src" == segments[root_idx]
     check_mvn_idx = root_idx if is_src else -1
     if (root_idx == 0 or is_src):
@@ -59,7 +59,23 @@
             next = segments[check_mvn_idx + 2]
             if next in ["java", "resources"]:
                 root_idx = check_mvn_idx + 2
-    return segments[(root_idx + 1):]
+    return root_idx
+
+def _java_segments(path):
+    idx = _java_segment_index(path)
+    return path.split("/")[(idx + 1):] if idx >= 0 else None
+
+def _java_path(path):
+    java_segments = _java_segments(path)
+    return "/".join(java_segments) if java_segments != None else None
+
+def _java_root(path):
+    idx = _java_segment_index(path)
+    return "/".join(path.split("/")[:(idx + 1)]) if idx >= 0 else None
+
+def _full_classname(path):
+    java_segments = _java_segments(path)
+    return ".".join(java_segments) if java_segments != None else None
 
 def _has_target_constraints(ctx, constraints):
     # Constraints is a label_list.
@@ -219,4 +235,7 @@
     get_relative = _get_relative,
     has_target_constraints = _has_target_constraints,
     java_segments = _java_segments,
+    java_path = _java_path,
+    java_root = _java_root,
+    full_classname = _full_classname,
 )
diff --git a/test/java/common/rules/java_helper_tests.bzl b/test/java/common/rules/java_helper_tests.bzl
index 5fdbbb6..89a44d2 100644
--- a/test/java/common/rules/java_helper_tests.bzl
+++ b/test/java/common/rules/java_helper_tests.bzl
@@ -60,6 +60,64 @@
         helper.java_segments("foo/bar/Baz"),
     )
 
+    asserts.equals(
+        env,
+        "com/google/foo/Foo",
+        helper.java_path("java/com/google/foo/Foo"),
+    )
+    asserts.equals(
+        env,
+        "com/google/foo/Foo",
+        helper.java_path("third_party/java/foo/java/com/google/foo/Foo"),
+    )
+    asserts.equals(
+        env,
+        None,
+        helper.java_path("foo/bar/Baz"),
+    )
+
+    asserts.equals(
+        env,
+        "java",
+        helper.java_root("java/com/google/foo/Foo"),
+    )
+    asserts.equals(
+        env,
+        "javatests",
+        helper.java_root("javatests/com/google/foo/FooTest"),
+    )
+    asserts.equals(
+        env,
+        "foo/java",
+        helper.java_root("foo/java/com/google/foo/Foo"),
+    )
+    asserts.equals(
+        env,
+        "third_party/java/foo/java",
+        helper.java_root("third_party/java/foo/java/com/google/foo/Foo"),
+    )
+    asserts.equals(
+        env,
+        None,
+        helper.java_root("foo/bar/Baz"),
+    )
+
+    asserts.equals(
+        env,
+        "com.google.foo.Foo",
+        helper.full_classname("java/com/google/foo/Foo"),
+    )
+    asserts.equals(
+        env,
+        "com.google.foo.Foo",
+        helper.full_classname("third_party/java/foo/java/com/google/foo/Foo"),
+    )
+    asserts.equals(
+        env,
+        None,
+        helper.full_classname("foo/bar/Baz"),
+    )
+
     return unittest.end(env)
 
 java_segments_test = unittest.make(_java_segments_test_impl)