Skip to content

Commit 6777456

Browse files
committed
Allow multiple kt_plugin_cfg
Since multiple plugin configurations can be provided to a simple compilation unit, adding a merge_cfgs hook before finalizing the configurations ensure the plugin author can merge configurations into a format that the compiler plugin can consume. This is a precursor to adding kapt options.
1 parent 18d8be4 commit 6777456

File tree

5 files changed

+172
-37
lines changed

5 files changed

+172
-37
lines changed

kotlin/internal/jvm/compile.bzl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ def _new_plugins_from(targets):
213213
cfg = t[_KtPluginConfiguration]
214214
if cfg.id not in all_plugins:
215215
cfgs_without_plugin.append("%s: %s" % (t.label, cfg.id))
216-
all_plugin_cfgs[cfg.id] = cfg
216+
all_plugin_cfgs.setdefault(cfg.id, []).append(cfg)
217217

218218
if cfgs_without_plugin:
219219
fail("has plugin configurations without corresponding plugins: %s" % cfgs_without_plugin)
@@ -231,7 +231,7 @@ def _new_plugin_from(all_cfgs, plugins_for_phase):
231231
classpath.append(p.classpath)
232232
options.extend(p.options)
233233
if p.id in all_cfgs:
234-
cfg = all_cfgs[p.id]
234+
cfg = p.merge_cfgs(p, all_cfgs[p.id])
235235
classpath.append(cfg.classpath)
236236
data.append(cfg.data)
237237
options.extend(cfg.options)

kotlin/internal/jvm/impl.bzl

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
load("@rules_java//java:defs.bzl", "JavaInfo", "JavaPluginInfo", "java_common")
1616
load(
1717
"//kotlin/internal:defs.bzl",
18-
"KtCompilerPluginOption",
1918
"KtPluginConfiguration",
2019
_KspPluginInfo = "KspPluginInfo",
2120
_KtCompilerPluginInfo = "KtCompilerPluginInfo",
@@ -30,6 +29,7 @@ load(
3029
"//kotlin/internal/utils:utils.bzl",
3130
_utils = "utils",
3231
)
32+
load("//src/main/starlark/core/plugin:common.bzl", "plugin_common")
3333
load("//third_party:jarjar.bzl", "jarjar_action")
3434

3535
# borrowed from skylib to avoid adding that to the release.
@@ -392,37 +392,6 @@ def _reshade_embedded_kotlinc_jars(target, ctx, jars, deps):
392392
],
393393
)
394394

395-
def _resolve_plugin_options(id, string_list_dict, expand_location):
396-
"""
397-
Resolves plugin options from a string dict to a dict of strings.
398-
399-
Args:
400-
id: the plugin id
401-
string_list_dict: a dict of list[string].
402-
Returns:
403-
a dict of strings
404-
"""
405-
options = []
406-
for (k, vs) in string_list_dict.items():
407-
for v in vs:
408-
if "=" in k:
409-
fail("kotlin compiler option keys cannot contain the = symbol")
410-
value = k + "=" + expand_location(v) if v else k
411-
options.append(KtCompilerPluginOption(id = id, value = value))
412-
return options
413-
414-
# This is naive reference implementation for resolving configurations.
415-
# A more complicated plugin will need to provide its own implementation.
416-
def _resolve_plugin_cfg(info, options, deps, expand_location):
417-
ji = java_common.merge([dep[JavaInfo] for dep in deps if JavaInfo in dep])
418-
classpath = depset(ji.runtime_output_jars, transitive = [ji.transitive_runtime_jars])
419-
return KtPluginConfiguration(
420-
id = info.id,
421-
options = _resolve_plugin_options(info.id, options, expand_location),
422-
classpath = classpath,
423-
data = depset(),
424-
)
425-
426395
def kt_compiler_plugin_impl(ctx):
427396
plugin_id = ctx.attr.id
428397

@@ -444,7 +413,7 @@ def kt_compiler_plugin_impl(ctx):
444413
classpath = depset(info.runtime_output_jars, transitive = [info.transitive_runtime_jars])
445414

446415
# TODO(1035): Migrate kt_compiler_plugin.options to string_list_dict
447-
options = _resolve_plugin_options(plugin_id, {k: [v] for (k, v) in ctx.attr.options.items()}, ctx.expand_location)
416+
options = plugin_common.resolve_plugin_options(plugin_id, {k: [v] for (k, v) in ctx.attr.options.items()}, ctx.expand_location)
448417

449418
return [
450419
DefaultInfo(files = classpath),
@@ -454,7 +423,8 @@ def kt_compiler_plugin_impl(ctx):
454423
options = options,
455424
stubs = ctx.attr.stubs_phase,
456425
compile = ctx.attr.compile_phase,
457-
resolve_cfg = _resolve_plugin_cfg,
426+
resolve_cfg = plugin_common.resolve_cfg,
427+
merge_cfgs = plugin_common.merge_cfgs,
458428
),
459429
]
460430

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
load(":providers.bzl", "KtCompilerPluginOption", "KtPluginConfiguration")
2+
3+
# This is naive reference implementation for resolving configurations.
4+
# A more complicated plugin will need to provide its own implementation.
5+
def _resolve_plugin_cfg(info, options, deps, expand_location):
6+
ji = java_common.merge([dep[JavaInfo] for dep in deps if JavaInfo in dep])
7+
classpath = depset(ji.runtime_output_jars, transitive = [ji.transitive_runtime_jars])
8+
data = None
9+
data_runfiles = [d[DefaultInfo].default_runfiles for d in deps if d[DefaultInfo]]
10+
if data_runfiles:
11+
data = data_runfiles[0].merge_all(data_runfiles[1:])
12+
return KtPluginConfiguration(
13+
id = info.id,
14+
options = _resolve_plugin_options(info.id, options, expand_location),
15+
classpath = classpath,
16+
data = data,
17+
)
18+
19+
def _merge_plugin_cfgs(info, cfgs):
20+
classpath = depset(transitive = [cfg.classpath for cfg in cfgs])
21+
options = [o for cfg in cfgs for o in cfg.options]
22+
return KtPluginConfiguration(
23+
id = info.id,
24+
options = options,
25+
classpath = classpath,
26+
data = depset(),
27+
)
28+
29+
def _resolve_plugin_options(id, string_list_dict, expand_location):
30+
"""
31+
Resolves plugin options from a string dict to a dict of strings.
32+
33+
Args:
34+
id: the plugin id
35+
string_list_dict: a dict of list[string].
36+
Returns:
37+
a dict of strings
38+
"""
39+
options = []
40+
for (k, vs) in string_list_dict.items():
41+
for v in vs:
42+
if "=" in k:
43+
fail("kotlin compiler option keys cannot contain the = symbol")
44+
value = k + "=" + expand_location(v) if v else k
45+
options.append(KtCompilerPluginOption(id = id, value = value))
46+
return options
47+
48+
plugin_common = struct(
49+
resolve_cfg = _resolve_plugin_cfg,
50+
merge_cfgs = _merge_plugin_cfgs,
51+
resolve_plugin_options = _resolve_plugin_options,
52+
)

src/main/starlark/core/plugin/providers.bzl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ KtCompilerPluginInfo = provider(
1515
"options": "List of plugin options, represented as KtCompilerPluginOption, to be passed to the compiler",
1616
"resolve_cfg": "A Callable[[KtCompilerPluginInfo, Dict[str,str], List[Target], KtPluginConfiguration]" +
1717
" that resolves an associated plugin configuration.",
18+
"merge_cfgs": "A Callable[[KtCompilerPluginInfo, List[KtPluginConfiguration]]] that merge multiple plugin configurations.",
1819
},
1920
)
2021

@@ -23,7 +24,7 @@ KtPluginConfiguration = provider(
2324
"id": "The id of the compiler plugin associated with this configuration.",
2425
"options": "List of plugin options, represented KtCompilerPluginOption",
2526
"classpath": "Depset of jars to add to the classpath when running the plugin.",
26-
"data": "Depset of files to pass to the plugin as data.",
27+
"data": "runfiles to pass to the plugin.",
2728
},
2829
)
2930

src/test/starlark/core/plugin/test.bzl

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,118 @@ def _test_compile_configuration(test):
188188
},
189189
)
190190

191+
def _test_compile_multiple_configurations(test):
192+
plugin_jar = test.artifact(
193+
name = "plugin.jar",
194+
)
195+
196+
plugin = test.have(
197+
kt_compiler_plugin,
198+
name = "plugin",
199+
id = "test.stub",
200+
options = {
201+
"annotation": "plugin.StubForTesting",
202+
},
203+
deps = [
204+
test.have(
205+
kt_jvm_import,
206+
name = "plugin_jar",
207+
jars = [
208+
plugin_jar,
209+
],
210+
),
211+
],
212+
)
213+
214+
dep_a_jar = test.artifact(
215+
name = "a_dep.jar",
216+
)
217+
dep_b_jar = test.artifact(
218+
name = "b_dep.jar",
219+
)
220+
221+
cfg_a = test.have(
222+
kt_plugin_cfg,
223+
name = "cfg_a",
224+
plugin = plugin,
225+
options = {
226+
"-Dop": ["koo"],
227+
},
228+
deps = [
229+
test.have(
230+
kt_jvm_import,
231+
name = "dep_a_jar",
232+
jars = [
233+
dep_a_jar,
234+
],
235+
),
236+
],
237+
)
238+
239+
cfg_b = test.have(
240+
kt_plugin_cfg,
241+
name = "cfg_b",
242+
plugin = plugin,
243+
options = {
244+
"-Dop": ["zubzub"],
245+
},
246+
deps = [
247+
test.have(
248+
kt_jvm_import,
249+
name = "dep_b_jar",
250+
jars = [
251+
dep_b_jar,
252+
],
253+
),
254+
],
255+
)
256+
257+
got = test.got(
258+
kt_jvm_library,
259+
name = "got_library",
260+
srcs = [
261+
test.artifact(
262+
name = "got_library.kt",
263+
),
264+
],
265+
plugins = [
266+
plugin,
267+
cfg_a,
268+
cfg_b,
269+
],
270+
)
271+
272+
analysis_test(
273+
name = test.name,
274+
impl = _action_test_impl,
275+
target = got,
276+
attr_values = {
277+
"on_action_mnemonic": "KotlinCompile",
278+
"want_flags": {
279+
"--compiler_plugin_options": [
280+
"test.stub:annotation=plugin.StubForTesting",
281+
"test.stub:-Dop=koo",
282+
"test.stub:-Dop=zubzub",
283+
],
284+
"--stubs_plugin_options": [
285+
"test.stub:annotation=plugin.StubForTesting",
286+
"test.stub:-Dop=koo",
287+
"test.stub:-Dop=zubzub",
288+
],
289+
},
290+
"want_inputs": [
291+
plugin_jar,
292+
dep_a_jar,
293+
dep_b_jar,
294+
],
295+
},
296+
attrs = {
297+
"on_action_mnemonic": attr.string(),
298+
"want_flags": attr.string_list_dict(),
299+
"want_inputs": attr.label_list(providers = [DefaultInfo], allow_files = True),
300+
},
301+
)
302+
191303
def _test_compile_configuration_single_phase(test):
192304
stub, stub_jar = plugin_for(
193305
test,

0 commit comments

Comments
 (0)