• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 24637157883

19 Apr 2026 07:23PM UTC coverage: 52.377% (-40.5%) from 92.924%
24637157883

Pull #23274

github

web-flow
Merge b54f275c2 into 0283af69e
Pull Request #23274: rust: upgrade to v1.95.0

31658 of 60443 relevant lines covered (52.38%)

1.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/python/pants/backend/kotlin/compile/kotlinc.py
1
# Copyright 2022 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 itertools
×
6
import logging
×
7

8
from pants.backend.java.target_types import JavaFieldSet, JavaGeneratorFieldSet
×
9
from pants.backend.kotlin.compile.kotlinc_plugins import (
×
10
    KotlincPluginsForTargetRequest,
11
    KotlincPluginsRequest,
12
    fetch_kotlinc_plugins,
13
    resolve_kotlinc_plugins_for_target,
14
)
15
from pants.backend.kotlin.subsystems.kotlin import KotlinSubsystem
×
16
from pants.backend.kotlin.subsystems.kotlinc import KotlincSubsystem
×
17
from pants.backend.kotlin.target_types import (
×
18
    KotlinFieldSet,
19
    KotlinGeneratorFieldSet,
20
    KotlinSourceField,
21
)
22
from pants.core.util_rules.source_files import SourceFilesRequest, determine_source_files
×
23
from pants.engine.internals.native_engine import EMPTY_DIGEST, MergeDigests
×
24
from pants.engine.internals.selectors import concurrently
×
25
from pants.engine.intrinsics import execute_process, merge_digests
×
26
from pants.engine.rules import collect_rules, implicitly, rule
×
27
from pants.engine.target import CoarsenedTarget, SourcesField
×
28
from pants.engine.unions import UnionRule
×
29
from pants.jvm.classpath import Classpath
×
30
from pants.jvm.compile import (
×
31
    ClasspathDependenciesRequest,
32
    ClasspathEntry,
33
    ClasspathEntryRequest,
34
    CompileResult,
35
    FallibleClasspathEntry,
36
    compile_classpath_entries,
37
)
38
from pants.jvm.compile import rules as jvm_compile_rules
×
39
from pants.jvm.jdk_rules import JdkRequest, JvmProcess, prepare_jdk_environment
×
40
from pants.jvm.resolve.common import ArtifactRequirements
×
41
from pants.jvm.resolve.coordinate import Coordinate
×
42
from pants.jvm.resolve.coursier_fetch import ToolClasspathRequest, materialize_classpath_for_tool
×
43
from pants.util.logging import LogLevel
×
44

45
logger = logging.getLogger(__name__)
×
46

47

48
class CompileKotlinSourceRequest(ClasspathEntryRequest):
×
49
    field_sets = (KotlinFieldSet, KotlinGeneratorFieldSet)
×
50
    field_sets_consume_only = (JavaFieldSet, JavaGeneratorFieldSet)
×
51

52

53
def compute_output_jar_filename(ctgt: CoarsenedTarget) -> str:
×
54
    return f"{ctgt.representative.address.path_safe_spec}.kotlin.jar"
×
55

56

57
@rule(desc="Compile with kotlinc")
×
58
async def compile_kotlin_source(
×
59
    kotlin: KotlinSubsystem,
60
    kotlinc: KotlincSubsystem,
61
    request: CompileKotlinSourceRequest,
62
) -> FallibleClasspathEntry:
63
    # Request classpath entries for our direct dependencies.
64
    dependency_cpers = await compile_classpath_entries(
×
65
        **implicitly(ClasspathDependenciesRequest(request))
66
    )
67
    direct_dependency_classpath_entries = dependency_cpers.if_all_succeeded()
×
68

69
    if direct_dependency_classpath_entries is None:
×
70
        return FallibleClasspathEntry(
×
71
            description=str(request.component),
72
            result=CompileResult.DEPENDENCY_FAILED,
73
            output=None,
74
            exit_code=1,
75
        )
76

77
    kotlin_version = kotlin.version_for_resolve(request.resolve.name)
×
78

79
    component_members_with_sources = tuple(
×
80
        t for t in request.component.members if t.has_field(SourcesField)
81
    )
82
    component_members_and_source_files = zip(
×
83
        component_members_with_sources,
84
        await concurrently(
85
            determine_source_files(
86
                SourceFilesRequest(
87
                    (t.get(SourcesField),),
88
                    for_sources_types=(KotlinSourceField,),
89
                    enable_codegen=True,
90
                )
91
            )
92
            for t in component_members_with_sources
93
        ),
94
    )
95

96
    plugins_ = await concurrently(
×
97
        resolve_kotlinc_plugins_for_target(
98
            KotlincPluginsForTargetRequest(target, request.resolve.name), **implicitly()
99
        )
100
        for target in request.component.members
101
    )
102
    plugins_request = KotlincPluginsRequest.from_target_plugins(plugins_, request.resolve)
×
103
    local_plugins = await fetch_kotlinc_plugins(plugins_request)
×
104

105
    component_members_and_kotlin_source_files = [
×
106
        (target, sources)
107
        for target, sources in component_members_and_source_files
108
        if sources.snapshot.digest != EMPTY_DIGEST
109
    ]
110

111
    if not component_members_and_kotlin_source_files:
×
112
        # Is a generator, and so exports all of its direct deps.
113
        exported_digest = await merge_digests(
×
114
            MergeDigests(cpe.digest for cpe in direct_dependency_classpath_entries)
115
        )
116
        classpath_entry = ClasspathEntry.merge(exported_digest, direct_dependency_classpath_entries)
×
117
        return FallibleClasspathEntry(
×
118
            description=str(request.component),
119
            result=CompileResult.SUCCEEDED,
120
            output=classpath_entry,
121
            exit_code=0,
122
        )
123

124
    toolcp_relpath = "__toolcp"
×
125
    local_kotlinc_plugins_relpath = "__localplugincp"
×
126
    usercp = "__cp"
×
127

128
    user_classpath = Classpath(direct_dependency_classpath_entries, request.resolve)
×
129

130
    tool_classpath, sources_digest, jdk = await concurrently(
×
131
        materialize_classpath_for_tool(
132
            ToolClasspathRequest(
133
                artifact_requirements=ArtifactRequirements.from_coordinates(
134
                    [
135
                        Coordinate(
136
                            group="org.jetbrains.kotlin",
137
                            artifact="kotlin-compiler-embeddable",
138
                            version=kotlin_version,
139
                        ),
140
                        Coordinate(
141
                            group="org.jetbrains.kotlin",
142
                            artifact="kotlin-scripting-compiler-embeddable",
143
                            version=kotlin_version,
144
                        ),
145
                    ]
146
                ),
147
            )
148
        ),
149
        merge_digests(
150
            MergeDigests(
151
                (
152
                    sources.snapshot.digest
153
                    for _, sources in component_members_and_kotlin_source_files
154
                )
155
            )
156
        ),
157
        prepare_jdk_environment(**implicitly(JdkRequest.from_target(request.component))),
158
    )
159

160
    extra_immutable_input_digests = {
×
161
        toolcp_relpath: tool_classpath.digest,
162
        local_kotlinc_plugins_relpath: local_plugins.classpath.digest,
163
    }
164
    extra_nailgun_keys = tuple(extra_immutable_input_digests)
×
165
    extra_immutable_input_digests.update(user_classpath.immutable_inputs(prefix=usercp))
×
166

167
    classpath_arg = ":".join(user_classpath.immutable_inputs_args(prefix=usercp))
×
168

169
    output_file = compute_output_jar_filename(request.component)
×
170
    process_result = await execute_process(
×
171
        **implicitly(
172
            JvmProcess(
173
                jdk=jdk,
174
                classpath_entries=tool_classpath.classpath_entries(toolcp_relpath),
175
                argv=[
176
                    "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler",
177
                    *(("-classpath", classpath_arg) if classpath_arg else ()),
178
                    "-d",
179
                    output_file,
180
                    *(local_plugins.args(local_kotlinc_plugins_relpath)),
181
                    *kotlinc.args,
182
                    *sorted(
183
                        itertools.chain.from_iterable(
184
                            sources.snapshot.files
185
                            for _, sources in component_members_and_kotlin_source_files
186
                        )
187
                    ),
188
                ],
189
                input_digest=sources_digest,
190
                extra_immutable_input_digests=extra_immutable_input_digests,
191
                extra_nailgun_keys=extra_nailgun_keys,
192
                output_files=(output_file,),
193
                description=f"Compile {request.component} with kotlinc",
194
                level=LogLevel.DEBUG,
195
            )
196
        )
197
    )
198
    output: ClasspathEntry | None = None
×
199
    if process_result.exit_code == 0:
×
200
        # NB: `kotlinc` produces reproducible JARs by default, so there is no need for an additional
201
        # stripping step.
202
        output = ClasspathEntry(
×
203
            process_result.output_digest, (output_file,), direct_dependency_classpath_entries
204
        )
205

206
    return FallibleClasspathEntry.from_fallible_process_result(
×
207
        str(request.component),
208
        process_result,
209
        output,
210
    )
211

212

213
def rules():
×
214
    return (
×
215
        *collect_rules(),
216
        *jvm_compile_rules(),
217
        UnionRule(ClasspathEntryRequest, CompileKotlinSourceRequest),
218
    )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc