Repository: pantsbuild/pants

Issue:
Java: Refactor `JavaSourceDependencyAnalysisRequest` to use a `SourceFiles` object rather than `Snapshot`
Per #13603, using `PathGlobs` and `Snapshot` get in the way of code generation, so will need to change at some point. The easiest way to tackle this would be to have `JavaSourceDependencyAnalysisRequest` require a `SourceFiles`, and fix all callsites/dependencies.


Discussion:

Resolving patch:
diff --git a/src/python/pants/backend/java/compile/javac.py b/src/python/pants/backend/java/compile/javac.py
--- a/src/python/pants/backend/java/compile/javac.py
+++ b/src/python/pants/backend/java/compile/javac.py
@@ -83,7 +83,10 @@ async def compile_java_source(
     )
     # Re-request inferred dependencies to get a list of export dependency addresses
     inferred_dependencies = await MultiGet(
-        Get(JavaInferredDependencies, JavaInferredDependenciesAndExportsRequest(tgt.address))
+        Get(
+            JavaInferredDependencies,
+            JavaInferredDependenciesAndExportsRequest(tgt[JavaSourceField]),
+        )
         for tgt in request.component.members
         if JavaFieldSet.is_applicable(tgt)
     )
diff --git a/src/python/pants/backend/java/dependency_inference/java_parser.py b/src/python/pants/backend/java/dependency_inference/java_parser.py
--- a/src/python/pants/backend/java/dependency_inference/java_parser.py
+++ b/src/python/pants/backend/java/dependency_inference/java_parser.py
@@ -15,7 +15,7 @@
 )
 from pants.backend.java.dependency_inference.types import JavaSourceDependencyAnalysis
 from pants.core.util_rules.source_files import SourceFiles
-from pants.engine.fs import AddPrefix, Digest, DigestContents, MergeDigests, Snapshot
+from pants.engine.fs import AddPrefix, Digest, DigestContents, MergeDigests
 from pants.engine.process import BashBinary, FallibleProcessResult, Process, ProcessExecutionFailure
 from pants.engine.rules import Get, MultiGet, collect_rules, rule
 from pants.jvm.jdk_rules import JdkSetup
@@ -28,7 +28,7 @@
 
 @dataclass(frozen=True)
 class JavaSourceDependencyAnalysisRequest:
-    snapshot: Snapshot
+    source_files: SourceFiles
 
 
 @dataclass(frozen=True)
@@ -62,7 +62,7 @@ async def resolve_fallible_result_to_analysis(
 async def make_analysis_request_from_source_files(
     source_files: SourceFiles,
 ) -> JavaSourceDependencyAnalysisRequest:
-    return JavaSourceDependencyAnalysisRequest(snapshot=source_files.snapshot)
+    return JavaSourceDependencyAnalysisRequest(source_files=source_files)
 
 
 @rule(level=LogLevel.DEBUG)
@@ -72,17 +72,17 @@ async def analyze_java_source_dependencies(
     processor_classfiles: JavaParserCompiledClassfiles,
     request: JavaSourceDependencyAnalysisRequest,
 ) -> FallibleJavaSourceDependencyAnalysisResult:
-    snapshot = request.snapshot
-    if len(snapshot.files) > 1:
+    source_files = request.source_files
+    if len(source_files.files) > 1:
         raise ValueError(
-            f"parse_java_package expects sources with exactly 1 source file, but found {len(snapshot.files)}."
+            f"parse_java_package expects sources with exactly 1 source file, but found {len(source_files.files)}."
         )
-    elif len(snapshot.files) == 0:
+    elif len(source_files.files) == 0:
         raise ValueError(
             "parse_java_package expects sources with exactly 1 source file, but found none."
         )
     source_prefix = "__source_to_analyze"
-    source_path = os.path.join(source_prefix, snapshot.files[0])
+    source_path = os.path.join(source_prefix, source_files.files[0])
     processorcp_relpath = "__processorcp"
 
     (
@@ -98,7 +98,7 @@ async def analyze_java_source_dependencies(
             ),
         ),
         Get(Digest, AddPrefix(processor_classfiles.digest, processorcp_relpath)),
-        Get(Digest, AddPrefix(snapshot.digest, source_prefix)),
+        Get(Digest, AddPrefix(source_files.snapshot.digest, source_prefix)),
     )
 
     tool_digest = await Get(
@@ -137,7 +137,7 @@ async def analyze_java_source_dependencies(
             use_nailgun=tool_digest,
             append_only_caches=jdk_setup.append_only_caches,
             env=jdk_setup.env,
-            description=f"Analyzing {snapshot.files[0]}",
+            description=f"Analyzing {source_files.files[0]}",
             level=LogLevel.DEBUG,
         ),
     )
diff --git a/src/python/pants/backend/java/dependency_inference/rules.py b/src/python/pants/backend/java/dependency_inference/rules.py
--- a/src/python/pants/backend/java/dependency_inference/rules.py
+++ b/src/python/pants/backend/java/dependency_inference/rules.py
@@ -12,9 +12,9 @@
 from pants.backend.java.dependency_inference.types import JavaImport, JavaSourceDependencyAnalysis
 from pants.backend.java.subsystems.java_infer import JavaInferSubsystem
 from pants.backend.java.target_types import JavaSourceField
+from pants.core.util_rules.source_files import SourceFiles, SourceFilesRequest
 from pants.core.util_rules.source_files import rules as source_files_rules
 from pants.engine.addresses import Address
-from pants.engine.fs import Digest, PathGlobs, Snapshot
 from pants.engine.rules import Get, MultiGet, collect_rules, rule
 from pants.engine.target import (
     Dependencies,
@@ -22,6 +22,7 @@
     ExplicitlyProvidedDependencies,
     InferDependenciesRequest,
     InferredDependencies,
+    SourcesField,
     WrappedTarget,
 )
 from pants.engine.unions import UnionRule
@@ -48,7 +49,7 @@ class JavaInferredDependencies:
 
 @dataclass(frozen=True)
 class JavaInferredDependenciesAndExportsRequest:
-    address: Address
+    source: SourcesField
 
 
 @rule(desc="Inferring Java dependencies by source analysis")
@@ -58,7 +59,7 @@ async def infer_java_dependencies_via_source_analysis(
 
     jids = await Get(
         JavaInferredDependencies,
-        JavaInferredDependenciesAndExportsRequest(request.sources_field.address),
+        JavaInferredDependenciesAndExportsRequest(request.sources_field),
     )
     return InferredDependencies(dependencies=jids.dependencies)
 
@@ -77,19 +78,17 @@ async def infer_java_dependencies_and_exports_via_source_analysis(
     ):
         return JavaInferredDependencies(FrozenOrderedSet([]), FrozenOrderedSet([]))
 
-    address = request.address
-    if not address.is_file_target:
-        raise Exception(
-            "Java source analysis requires a snapshot with a "
-            f"single Java source file, but was provided with address `{address}`."
-        )
-    a = await Get(Digest, PathGlobs([address.filename]))
-    s = await Get(Snapshot, Digest, a)
+    address = request.source.address
 
     wrapped_tgt = await Get(WrappedTarget, Address, address)
+    source_files = await Get(SourceFiles, SourceFilesRequest([wrapped_tgt.target[JavaSourceField]]))
+
     explicitly_provided_deps, analysis = await MultiGet(
         Get(ExplicitlyProvidedDependencies, DependenciesRequest(wrapped_tgt.target[Dependencies])),
-        Get(JavaSourceDependencyAnalysis, JavaSourceDependencyAnalysisRequest(snapshot=s)),
+        Get(
+            JavaSourceDependencyAnalysis,
+            JavaSourceDependencyAnalysisRequest(source_files=source_files),
+        ),
     )
 
     types: OrderedSet[str] = OrderedSet()


Test patch:
diff --git a/src/python/pants/backend/java/dependency_inference/rules_test.py b/src/python/pants/backend/java/dependency_inference/rules_test.py
--- a/src/python/pants/backend/java/dependency_inference/rules_test.py
+++ b/src/python/pants/backend/java/dependency_inference/rules_test.py
@@ -607,7 +607,7 @@ def test_exports(rule_runner: RuleRunner) -> None:
     # B should depend on C and D, but only export C
     assert rule_runner.request(
         JavaInferredDependencies,
-        [JavaInferredDependenciesAndExportsRequest(target_b[JavaSourceField].address)],
+        [JavaInferredDependenciesAndExportsRequest(target_b[JavaSourceField])],
     ) == JavaInferredDependencies(
         dependencies=FrozenOrderedSet(
             [
@@ -625,7 +625,7 @@ def test_exports(rule_runner: RuleRunner) -> None:
     # A should depend on B, but not B's dependencies or export types
     assert rule_runner.request(
         JavaInferredDependencies,
-        [JavaInferredDependenciesAndExportsRequest(target_a[JavaSourceField].address)],
+        [JavaInferredDependenciesAndExportsRequest(target_a[JavaSourceField])],
     ) == JavaInferredDependencies(
         dependencies=FrozenOrderedSet(
             [