prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Scala import extraction for inference
  Inference for Scala will require (at a minimum) import extraction from Scala sources. In v1 this was accomplished with https://scalameta.org/, which still seems to be active.
  
  https://scalameta.org/docs/trees/guide.html#parse-trees
  
  </issue>
  <code>
  [start of src/python/pants/backend/scala/dependency_inference/rules.py]
  1 # Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
  2 # Licensed under the Apache License, Version 2.0 (see LICENSE).
  3 from __future__ import annotations
  4 
  5 import logging
  6 
  7 from pants.backend.scala.dependency_inference import scala_parser, symbol_mapper
  8 from pants.backend.scala.dependency_inference.scala_parser import ScalaSourceDependencyAnalysis
  9 from pants.backend.scala.subsystems.scala_infer import ScalaInferSubsystem
  10 from pants.backend.scala.target_types import ScalaSourceField
  11 from pants.build_graph.address import Address
  12 from pants.core.util_rules.source_files import SourceFilesRequest
  13 from pants.engine.internals.selectors import Get, MultiGet
  14 from pants.engine.rules import collect_rules, rule
  15 from pants.engine.target import (
  16     Dependencies,
  17     DependenciesRequest,
  18     ExplicitlyProvidedDependencies,
  19     InferDependenciesRequest,
  20     InferredDependencies,
  21     WrappedTarget,
  22 )
  23 from pants.engine.unions import UnionRule
  24 from pants.jvm.dependency_inference.symbol_mapper import FirstPartySymbolMapping
  25 from pants.util.ordered_set import OrderedSet
  26 
  27 logger = logging.getLogger(__name__)
  28 
  29 
  30 class InferScalaSourceDependencies(InferDependenciesRequest):
  31     infer_from = ScalaSourceField
  32 
  33 
  34 @rule(desc="Inferring Scala dependencies by analyzing sources")
  35 async def infer_scala_dependencies_via_source_analysis(
  36     request: InferScalaSourceDependencies,
  37     scala_infer_subsystem: ScalaInferSubsystem,
  38     first_party_symbol_map: FirstPartySymbolMapping,
  39 ) -> InferredDependencies:
  40     if not scala_infer_subsystem.imports:
  41         return InferredDependencies([])
  42 
  43     address = request.sources_field.address
  44     wrapped_tgt = await Get(WrappedTarget, Address, address)
  45     explicitly_provided_deps, analysis = await MultiGet(
  46         Get(ExplicitlyProvidedDependencies, DependenciesRequest(wrapped_tgt.target[Dependencies])),
  47         Get(ScalaSourceDependencyAnalysis, SourceFilesRequest([request.sources_field])),
  48     )
  49 
  50     symbols: OrderedSet[str] = OrderedSet()
  51     if scala_infer_subsystem.imports:
  52         symbols.update(analysis.all_imports())
  53 
  54     dependencies: OrderedSet[Address] = OrderedSet()
  55     for symbol in symbols:
  56         matches = first_party_symbol_map.symbols.addresses_for_symbol(symbol)
  57         if not matches:
  58             continue
  59 
  60         explicitly_provided_deps.maybe_warn_of_ambiguous_dependency_inference(
  61             matches,
  62             address,
  63             import_reference="type",
  64             context=f"The target {address} imports `{symbol}`",
  65         )
  66 
  67         maybe_disambiguated = explicitly_provided_deps.disambiguated(matches)
  68         if maybe_disambiguated:
  69             dependencies.add(maybe_disambiguated)
  70 
  71     return InferredDependencies(dependencies)
  72 
  73 
  74 def rules():
  75     return [
  76         *collect_rules(),
  77         *scala_parser.rules(),
  78         *symbol_mapper.rules(),
  79         UnionRule(InferDependenciesRequest, InferScalaSourceDependencies),
  80     ]
  81
  [end of src/python/pants/backend/scala/dependency_inference/rules.py]
  [start of src/python/pants/backend/java/subsystems/java_infer.py]
  1 # Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
  2 # Licensed under the Apache License, Version 2.0 (see LICENSE).
  3 from typing import cast
  4 
  5 from pants.option.subsystem import Subsystem
  6 from pants.util.docutil import git_url
  7 
  8 
  9 class JavaInferSubsystem(Subsystem):
  10     options_scope = "java-infer"
  11     help = "Options controlling which dependencies will be inferred for Java targets."
  12 
  13     @classmethod
  14     def register_options(cls, register):
  15         super().register_options(register)
  16         register(
  17             "--imports",
  18             default=True,
  19             type=bool,
  20             help=("Infer a target's dependencies by parsing import statements from sources."),
  21         )
  22         register(
  23             "--consumed-types",
  24             default=True,
  25             type=bool,
  26             help=("Infer a target's dependencies by parsing consumed types from sources."),
  27         )
  28         register(
  29             "--third-party-imports",
  30             default=True,
  31             type=bool,
  32             help="Infer a target's third-party dependencies using Java import statements.",
  33         )
  34         _default_package_mapping_url = git_url(
  35             "src/python/pants/backend/java/dependency_inference/jvm_artifact_mappings.py"
  36         )
  37         register(
  38             "--third-party-import-mapping",
  39             type=dict,
  40             help=(
  41                 "A dictionary mapping a Java package path to a JVM artifact coordinate (GROUP:ARTIFACT) "
  42                 "without the version. The package path may be made recursive to match symbols in subpackages "
  43                 "by adding `.**` to the end of the package path. For example, specify `{'org.junit.**': 'junit:junit'} `"
  44                 "to infer a dependency on junit:junit for any file importing a symbol from org.junit or its "
  45                 f"subpackages. Pants also supplies a default package mapping ({_default_package_mapping_url})."
  46             ),
  47         )
  48 
  49     @property
  50     def imports(self) -> bool:
  51         return cast(bool, self.options.imports)
  52 
  53     @property
  54     def consumed_types(self) -> bool:
  55         return cast(bool, self.options.consumed_types)
  56 
  57     @property
  58     def third_party_imports(self) -> bool:
  59         return cast(bool, self.options.third_party_imports)
  60 
  61     @property
  62     def third_party_import_mapping(self) -> dict:
  63         return cast(dict, self.options.third_party_import_mapping)
  64
  [end of src/python/pants/backend/java/subsystems/java_infer.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/src/python/pants/backend/java/subsystems/java_infer.py b/src/python/pants/backend/java/subsystems/java_infer.py
  --- a/src/python/pants/backend/java/subsystems/java_infer.py
  +++ b/src/python/pants/backend/java/subsystems/java_infer.py
  @@ -34,6 +34,7 @@
           _default_package_mapping_url = git_url(
               "src/python/pants/backend/java/dependency_inference/jvm_artifact_mappings.py"
           )
  +        # TODO: Move to `coursier` or a generic `jvm` subsystem.
           register(
               "--third-party-import-mapping",
               type=dict,
  diff --git a/src/python/pants/backend/scala/dependency_inference/rules.py b/src/python/pants/backend/scala/dependency_inference/rules.py
  --- a/src/python/pants/backend/scala/dependency_inference/rules.py
  +++ b/src/python/pants/backend/scala/dependency_inference/rules.py
  @@ -21,6 +21,12 @@
       WrappedTarget,
   )
   from pants.engine.unions import UnionRule
  +from pants.jvm.dependency_inference import artifact_mapper
  +from pants.jvm.dependency_inference.artifact_mapper import (
  +    AvailableThirdPartyArtifacts,
  +    ThirdPartyPackageToArtifactMapping,
  +    find_artifact_mapping,
  +)
   from pants.jvm.dependency_inference.symbol_mapper import FirstPartySymbolMapping
   from pants.util.ordered_set import OrderedSet
   
  @@ -36,6 +42,8 @@
       request: InferScalaSourceDependencies,
       scala_infer_subsystem: ScalaInferSubsystem,
       first_party_symbol_map: FirstPartySymbolMapping,
  +    third_party_artifact_mapping: ThirdPartyPackageToArtifactMapping,
  +    available_artifacts: AvailableThirdPartyArtifacts,
   ) -> InferredDependencies:
       if not scala_infer_subsystem.imports:
           return InferredDependencies([])
  @@ -53,7 +61,11 @@
   
       dependencies: OrderedSet[Address] = OrderedSet()
       for symbol in symbols:
  -        matches = first_party_symbol_map.symbols.addresses_for_symbol(symbol)
  +        first_party_matches = first_party_symbol_map.symbols.addresses_for_symbol(symbol)
  +        third_party_matches = find_artifact_mapping(
  +            symbol, third_party_artifact_mapping, available_artifacts
  +        )
  +        matches = first_party_matches.union(third_party_matches)
           if not matches:
               continue
   
  @@ -74,6 +86,7 @@
   def rules():
       return [
           *collect_rules(),
  +        *artifact_mapper.rules(),
           *scala_parser.rules(),
           *symbol_mapper.rules(),
           UnionRule(InferDependenciesRequest, InferScalaSourceDependencies),
  
verification_info: {"golden_diff": "diff --git a/src/python/pants/backend/java/subsystems/java_infer.py b/src/python/pants/backend/java/subsystems/java_infer.py\n--- a/src/python/pants/backend/java/subsystems/java_infer.py\n+++ b/src/python/pants/backend/java/subsystems/java_infer.py\n@@ -34,6 +34,7 @@\n         _default_package_mapping_url = git_url(\n             \"src/python/pants/backend/java/dependency_inference/jvm_artifact_mappings.py\"\n         )\n+        # TODO: Move to `coursier` or a generic `jvm` subsystem.\n         register(\n             \"--third-party-import-mapping\",\n             type=dict,\ndiff --git a/src/python/pants/backend/scala/dependency_inference/rules.py b/src/python/pants/backend/scala/dependency_inference/rules.py\n--- a/src/python/pants/backend/scala/dependency_inference/rules.py\n+++ b/src/python/pants/backend/scala/dependency_inference/rules.py\n@@ -21,6 +21,12 @@\n     WrappedTarget,\n )\n from pants.engine.unions import UnionRule\n+from pants.jvm.dependency_inference import artifact_mapper\n+from pants.jvm.dependency_inference.artifact_mapper import (\n+    AvailableThirdPartyArtifacts,\n+    ThirdPartyPackageToArtifactMapping,\n+    find_artifact_mapping,\n+)\n from pants.jvm.dependency_inference.symbol_mapper import FirstPartySymbolMapping\n from pants.util.ordered_set import OrderedSet\n \n@@ -36,6 +42,8 @@\n     request: InferScalaSourceDependencies,\n     scala_infer_subsystem: ScalaInferSubsystem,\n     first_party_symbol_map: FirstPartySymbolMapping,\n+    third_party_artifact_mapping: ThirdPartyPackageToArtifactMapping,\n+    available_artifacts: AvailableThirdPartyArtifacts,\n ) -> InferredDependencies:\n     if not scala_infer_subsystem.imports:\n         return InferredDependencies([])\n@@ -53,7 +61,11 @@\n \n     dependencies: OrderedSet[Address] = OrderedSet()\n     for symbol in symbols:\n-        matches = first_party_symbol_map.symbols.addresses_for_symbol(symbol)\n+        first_party_matches = first_party_symbol_map.symbols.addresses_for_symbol(symbol)\n+        third_party_matches = find_artifact_mapping(\n+            symbol, third_party_artifact_mapping, available_artifacts\n+        )\n+        matches = first_party_matches.union(third_party_matches)\n         if not matches:\n             continue\n \n@@ -74,6 +86,7 @@\n def rules():\n     return [\n         *collect_rules(),\n+        *artifact_mapper.rules(),\n         *scala_parser.rules(),\n         *symbol_mapper.rules(),\n         UnionRule(InferDependenciesRequest, InferScalaSourceDependencies),\n", "issue": "Scala import extraction for inference\nInference for Scala will require (at a minimum) import extraction from Scala sources. In v1 this was accomplished with https://scalameta.org/, which still seems to be active.\r\n\r\nhttps://scalameta.org/docs/trees/guide.html#parse-trees\n", "before_files": [{"content": "# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\nfrom __future__ import annotations\n\nimport logging\n\nfrom pants.backend.scala.dependency_inference import scala_parser, symbol_mapper\nfrom pants.backend.scala.dependency_inference.scala_parser import ScalaSourceDependencyAnalysis\nfrom pants.backend.scala.subsystems.scala_infer import ScalaInferSubsystem\nfrom pants.backend.scala.target_types import ScalaSourceField\nfrom pants.build_graph.address import Address\nfrom pants.core.util_rules.source_files import SourceFilesRequest\nfrom pants.engine.internals.selectors import Get, MultiGet\nfrom pants.engine.rules import collect_rules, rule\nfrom pants.engine.target import (\n    Dependencies,\n    DependenciesRequest,\n    ExplicitlyProvidedDependencies,\n    InferDependenciesRequest,\n    InferredDependencies,\n    WrappedTarget,\n)\nfrom pants.engine.unions import UnionRule\nfrom pants.jvm.dependency_inference.symbol_mapper import FirstPartySymbolMapping\nfrom pants.util.ordered_set import OrderedSet\n\nlogger = logging.getLogger(__name__)\n\n\nclass InferScalaSourceDependencies(InferDependenciesRequest):\n    infer_from = ScalaSourceField\n\n\n@rule(desc=\"Inferring Scala dependencies by analyzing sources\")\nasync def infer_scala_dependencies_via_source_analysis(\n    request: InferScalaSourceDependencies,\n    scala_infer_subsystem: ScalaInferSubsystem,\n    first_party_symbol_map: FirstPartySymbolMapping,\n) -> InferredDependencies:\n    if not scala_infer_subsystem.imports:\n        return InferredDependencies([])\n\n    address = request.sources_field.address\n    wrapped_tgt = await Get(WrappedTarget, Address, address)\n    explicitly_provided_deps, analysis = await MultiGet(\n        Get(ExplicitlyProvidedDependencies, DependenciesRequest(wrapped_tgt.target[Dependencies])),\n        Get(ScalaSourceDependencyAnalysis, SourceFilesRequest([request.sources_field])),\n    )\n\n    symbols: OrderedSet[str] = OrderedSet()\n    if scala_infer_subsystem.imports:\n        symbols.update(analysis.all_imports())\n\n    dependencies: OrderedSet[Address] = OrderedSet()\n    for symbol in symbols:\n        matches = first_party_symbol_map.symbols.addresses_for_symbol(symbol)\n        if not matches:\n            continue\n\n        explicitly_provided_deps.maybe_warn_of_ambiguous_dependency_inference(\n            matches,\n            address,\n            import_reference=\"type\",\n            context=f\"The target {address} imports `{symbol}`\",\n        )\n\n        maybe_disambiguated = explicitly_provided_deps.disambiguated(matches)\n        if maybe_disambiguated:\n            dependencies.add(maybe_disambiguated)\n\n    return InferredDependencies(dependencies)\n\n\ndef rules():\n    return [\n        *collect_rules(),\n        *scala_parser.rules(),\n        *symbol_mapper.rules(),\n        UnionRule(InferDependenciesRequest, InferScalaSourceDependencies),\n    ]\n", "path": "src/python/pants/backend/scala/dependency_inference/rules.py"}, {"content": "# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\nfrom typing import cast\n\nfrom pants.option.subsystem import Subsystem\nfrom pants.util.docutil import git_url\n\n\nclass JavaInferSubsystem(Subsystem):\n    options_scope = \"java-infer\"\n    help = \"Options controlling which dependencies will be inferred for Java targets.\"\n\n    @classmethod\n    def register_options(cls, register):\n        super().register_options(register)\n        register(\n            \"--imports\",\n            default=True,\n            type=bool,\n            help=(\"Infer a target's dependencies by parsing import statements from sources.\"),\n        )\n        register(\n            \"--consumed-types\",\n            default=True,\n            type=bool,\n            help=(\"Infer a target's dependencies by parsing consumed types from sources.\"),\n        )\n        register(\n            \"--third-party-imports\",\n            default=True,\n            type=bool,\n            help=\"Infer a target's third-party dependencies using Java import statements.\",\n        )\n        _default_package_mapping_url = git_url(\n            \"src/python/pants/backend/java/dependency_inference/jvm_artifact_mappings.py\"\n        )\n        register(\n            \"--third-party-import-mapping\",\n            type=dict,\n            help=(\n                \"A dictionary mapping a Java package path to a JVM artifact coordinate (GROUP:ARTIFACT) \"\n                \"without the version. The package path may be made recursive to match symbols in subpackages \"\n                \"by adding `.**` to the end of the package path. For example, specify `{'org.junit.**': 'junit:junit'} `\"\n                \"to infer a dependency on junit:junit for any file importing a symbol from org.junit or its \"\n                f\"subpackages. Pants also supplies a default package mapping ({_default_package_mapping_url}).\"\n            ),\n        )\n\n    @property\n    def imports(self) -> bool:\n        return cast(bool, self.options.imports)\n\n    @property\n    def consumed_types(self) -> bool:\n        return cast(bool, self.options.consumed_types)\n\n    @property\n    def third_party_imports(self) -> bool:\n        return cast(bool, self.options.third_party_imports)\n\n    @property\n    def third_party_import_mapping(self) -> dict:\n        return cast(dict, self.options.third_party_import_mapping)\n", "path": "src/python/pants/backend/java/subsystems/java_infer.py"}]}