Skip to content

Commit 43a1533

Browse files
authored
Allow multiple kt_plugin_cfg (#1353)
* 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. * make buildifier.check match current warnings
1 parent 9423246 commit 43a1533

File tree

6 files changed

+195
-38
lines changed

6 files changed

+195
-38
lines changed

BUILD

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,28 @@ buildifier(
8787
name = "buildifier.check",
8888
exclude_patterns = [
8989
"./.git/*",
90+
"./.ijwb/*",
9091
],
9192
lint_mode = "warn",
93+
lint_warnings = [
94+
"-confusing-name",
95+
"-constant-glob",
96+
"-duplicated-name",
97+
"-function-docstring",
98+
"-function-docstring-args",
99+
"-function-docstring-header",
100+
"-module-docstring",
101+
"-name-conventions",
102+
"-no-effect",
103+
"-constant-glob",
104+
"-provider-params",
105+
"-print",
106+
"-rule-impl-return",
107+
"-bzl-visibility",
108+
"-unnamed-macro",
109+
"-uninitialized",
110+
"-unreachable",
111+
],
92112
mode = "diff",
93113
)
94114

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 & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
load("@rules_java//java:defs.bzl", "JavaInfo", "JavaPluginInfo", "java_common")
1616
load(
1717
"//kotlin/internal:defs.bzl",
18-
"KtCompilerPluginOption",
19-
"KtPluginConfiguration",
2018
_KspPluginInfo = "KspPluginInfo",
2119
_KtCompilerPluginInfo = "KtCompilerPluginInfo",
2220
_KtJvmInfo = "KtJvmInfo",
@@ -30,6 +28,7 @@ load(
3028
"//kotlin/internal/utils:utils.bzl",
3129
_utils = "utils",
3230
)
31+
load("//src/main/starlark/core/plugin:common.bzl", "plugin_common")
3332
load("//third_party:jarjar.bzl", "jarjar_action")
3433

3534
# borrowed from skylib to avoid adding that to the release.
@@ -392,37 +391,6 @@ def _reshade_embedded_kotlinc_jars(target, ctx, jars, deps):
392391
],
393392
)
394393

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-
426394
def kt_compiler_plugin_impl(ctx):
427395
plugin_id = ctx.attr.id
428396

@@ -444,7 +412,7 @@ def kt_compiler_plugin_impl(ctx):
444412
classpath = depset(info.runtime_output_jars, transitive = [info.transitive_runtime_jars])
445413

446414
# 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)
415+
options = plugin_common.resolve_plugin_options(plugin_id, {k: [v] for (k, v) in ctx.attr.options.items()}, ctx.expand_location)
448416

449417
return [
450418
DefaultInfo(files = classpath),
@@ -454,7 +422,8 @@ def kt_compiler_plugin_impl(ctx):
454422
options = options,
455423
stubs = ctx.attr.stubs_phase,
456424
compile = ctx.attr.compile_phase,
457-
resolve_cfg = _resolve_plugin_cfg,
425+
resolve_cfg = plugin_common.resolve_cfg,
426+
merge_cfgs = plugin_common.merge_cfgs,
458427
),
459428
]
460429

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

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: 113 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,
@@ -378,4 +490,5 @@ def test_suite(name):
378490
test_library_multiple_plugins_with_same_id = _test_library_multiple_plugins_with_same_id,
379491
test_compile_configuration_single_phase = _test_compile_configuration_single_phase,
380492
test_cfg_without_plugin = _test_cfg_without_plugin,
493+
test_compile_multiple_configurations = _test_compile_multiple_configurations,
381494
)

0 commit comments

Comments
 (0)