@@ -166,47 +166,72 @@ Here goes all heavy lifting codegen
166
166
167
167
#### Compiler Specific Modules
168
168
169
- > [ !NOTE] Has its drawbacks, maybe we'll redesign later.
170
-
171
169
We have a problem when developing a Kotlin compiler plugin:
172
170
Compiler API is not stable (not won't be for a while). So how can one develop a plugin that works stably?
173
171
174
172
We compile for multiple Kotlin versions at once!
175
173
176
174
We use an in-house ✨technology✨ for this: CSM or Compiler Specific Modules.
177
- The idea is to substitute source sets depending on the current kotlin compiler version
175
+ This is a templating engine, which resolution is based on the current kotlin compiler version
178
176
(` kotlin-compiler ` in [ libs.versions.toml] ( ../versions-root/libs.versions.toml ) ).
179
177
180
- There is always a ` core ` source set (like this: [ core ] ( ../compiler-plugin/compiler-plugin-k2/src/main/core ) )
178
+ There is always a core source set (like this: [ kotlin ] ( ../compiler-plugin/compiler-plugin-k2/src/main/kotlin ) )
181
179
that compiles nicely on all Kotlin versions. It is the majority of the code.
182
- And then we have source sets that are swapped for a specific version
183
- (check other directories in the [ main ] ( ../compiler-plugin/compiler-plugin-k2/src/main ) ).
180
+ And then we have a template set, which is processed before compilation for a specific version.
181
+ ([ templates ] ( ../compiler-plugin/compiler-plugin-k2/src/main/templates ) ).
184
182
185
- The code that swaps them is in [ compiler-specific-module.gradle.kts ] ( ../gradle-conventions/src/main/kotlin/compiler-specific-module.gradle.kts ) .
183
+ The code that swaps them is in [ template.kt ] ( ../gradle-conventions/src/main/kotlin/util/csm/template.kt ) .
186
184
187
185
The rules are the following:
188
- - Check all source sets that start with ` v_ ` (for example, ` v_2_2 ` , ` v_2_1 ` , ` v_2_2_2 ` ).
189
- It matches the most specific like a tree (so for ` 2.2.20 ` it will be ` v_2_2_2 ` , for ` 2.2.10 ` - ` v_2_2 ` and for ` 2.3.0 ` none).
190
- If found one - its taken.
191
- - If none, then check all that start with ` pre_ ` (for example, ` pre_2_0_10 ` , ` pre_2_1_0 ` , ` pre_2_2_0 ` ).
192
- Again, it matches the most specific inclusively, but chronologically
193
- (for ` 2.1.0 ` it will be ` pre_2_1_0 ` , for ` 2.0.0 ` - ` pre_2_0_10 ` , for ` 2.3.0 ` none)
194
- - Take ` latest ` otherwise
195
- - Suffixes don't matter (` 2.2.0 ` and ` 2.2.0-RC ` are considered the same)
196
-
197
- It allows supporting some past and future Kotlin versions
186
+ - We enclose code dependent on a version in ` ##csm ` tags.
187
+ - Every such block must:
188
+ - Start with ` //##csm <block_name> `
189
+ - End with ` //##csm /<block_name> `
190
+ - Specify inside zero of more of the code blocks:
191
+ - ` //##csm default ` + ` //##csm /default `
192
+ - ` //##csm specific=[<version_patten>] ` + ` //##csm /specific `
193
+
194
+ Example code:
195
+ ``` kotlin
196
+ fun functionAvailableInAllVersions () {
197
+
198
+ }
199
+ fun csmFunction () {
200
+ // ##csm my-block
201
+ // ##csm default
202
+ return 1
203
+ // ##csm /default
204
+ // ##csm specific=[2.0.0...2.1.0, 2.1.0-ij-*]
205
+ return 2
206
+ // ##csm /specific
207
+ // ##csm /my-block
208
+ }
209
+ ```
210
+
211
+ Templates matches ` specific ` versions greedy, so with multiple ` specific ` blocks - first one matched will be chosen,
212
+ or ` default ` if none, or nothing if there is no ` default ` .
213
+
214
+ ` <version_pattern> ` works like this:
215
+ - It's a comma-separated array of versions matchers
216
+ - Version matcher is either:
217
+ - Range — consists of ` from ` and ` to ` version separated by ` ... ` .
218
+ ` From ` must be an exact version without a suffix.
219
+ ` To ` must be a version without a suffix, where ` * ` can be used for any part: ` 2.2.* ` , ` 2.* ` but not ` 2.2.2* ` .
220
+ - Prefix matcher — matches a version by prefix: ` 2.2.0-* ` , ` 2.2.2* ` , ` 2.3.0-dev-* `
221
+
222
+ This allows us to support some past and future Kotlin versions
198
223
(including versions for IDE, which are not in the stable list nor generally public) simultaneously.
199
224
200
- Rule for complier API breaking changes:
225
+ Rules for complier API breaking changes:
201
226
- If some function or property changed signature or was replaced by another -
202
- use ` VersionSpecificApi ` interface in ` core ` to declare functionality
203
- and write the implementation in ** all** other source sets
204
- (see [ FirVersionSpecificApi.kt] ( ../compiler-plugin/compiler-plugin-k2/src/main/core/kotlinx/rpc/codegen/FirVersionSpecificApi.kt )
205
- and [ VersionSpecificApi.kt] ( ../compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/VersionSpecificApi.kt ) ).
227
+ use ` VersionSpecificApi ` interface in core to declare functionality
228
+ (see [ FirVersionSpecificApi.kt] ( ../compiler-plugin/compiler-plugin-k2/src/main/kotlin/kotlinx/rpc/codegen/FirVersionSpecificApi.kt )
229
+ and [ VersionSpecificApi.kt] ( ../compiler-plugin/compiler-plugin-backend/src/main/kotlin/kotlinx/rpc/codegen/VersionSpecificApi.kt ) ).
206
230
- If some class differs in signature,
207
- write a proxy in ` core ` and implementation in source sets. FQ name must match exactly
208
- (see [ FirRpcCheckersVS.kt] ( ../compiler-plugin/compiler-plugin-k2/src/main/v_2_3/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt ) )
209
- as an example, and all classes with the same names in other source sets.
231
+ write a proxy in core and implementation in the template.
232
+ FQ name must match exactly.
233
+ (see [ FirRpcCheckersVS.kt] ( ../compiler-plugin/compiler-plugin-k2/src/main/templates/kotlinx/rpc/codegen/checkers/FirRpcCheckersVS.kt )
234
+ as an example)
210
235
211
236
TeamCity is set up to work with multiple Kotlin versions for testing and releases.
212
237
@@ -365,14 +390,14 @@ Here is a 'simple' guide for solving problems:
365
390
- ` Cannot connect to the Docker daemon ` - open ` Docker Desktop `
366
391
- Kotlin/Js or Kotlin/Wasm
367
392
- ` kotlinUpgradePackageLock ` or ` kotlinWasmUpgradePackageLock ` (and also ` kotlinNpmInstall ` or ` kotlinWasmNpmInstall ` )
368
- have a funny tendency to fail sometimes, and you don't know why.
369
- < br />
370
- I'll tell you!
371
- < br />
372
- We use proxy repos, and sometimes dependencies get downloaded from the wrong source.
373
- Make sure ALL urls in ` package-lock.json ` files start with ` https://packages.jetbrains.team/npm/p/krpc/build-deps/ ` .
374
- < br />
375
- If something doesn't work, your steps are:
393
+ have a funny tendency to fail sometimes, and you don't know why.
394
+
395
+ I'll tell you!
396
+
397
+ We use proxy repos, and sometimes dependencies get downloaded from the wrong source.
398
+ Make sure ALL urls in ` package-lock.json ` files start with ` https://packages.jetbrains.team/npm/p/krpc/build-deps/ ` .
399
+
400
+ If something doesn't work, your steps are:
376
401
- Delete ` package-lock.json ` file
377
402
- Delete ` <REPO_ROOT>/build/js ` / ` <REPO_ROOT>/build/wasm `
378
403
- Run ` kotlinUpgradePackageLock ` / ` kotlinWasmUpgradePackageLock `
@@ -384,13 +409,13 @@ If something doesn't work, your steps are:
384
409
- ` always-auth=true `
385
410
- ` save-exact=true `
386
411
- ` //packages.jetbrains.team/npm/p/krpc/build-deps/:_authToken=<your_auth_token> ` ,
387
- where ` <your_auth_token> ` is from the [ proxy-repositories.md] ( proxy-repositories.md ) guide.
412
+ where ` <your_auth_token> ` is from the [ proxy-repositories.md] ( proxy-repositories.md ) guide.
388
413
- Check that ` <USER_HOME>/.npmrc ` / ` <USER_HOME>/.yarnrc ` don't interfere
389
- command to debug. Replace versions of tools if needed.
414
+ command to debug. Replace versions of tools if needed.
390
415
- When you get the following error — ` puppeteer ` failed to run the installation script.
391
- Reasons vary, try updating the version to a newer one,
392
- check the [ .puppeteerrc.cjs] ( ../.puppeteerrc.cjs ) and [ chrome_bin.js] ( ../karma/chrome_bin.js ) files if they are valid js.
393
-
416
+ Reasons vary, try updating the version to a newer one,
417
+ check the [ .puppeteerrc.cjs] ( ../.puppeteerrc.cjs ) and [ chrome_bin.js] ( ../karma/chrome_bin.js ) files if they are valid js.
418
+
394
419
For (2), check out our guide on configuring puppeteer at https://pptr.dev/guides/configuration.
395
420
at ChromeLauncher.resolveExecutablePath (/rpc/build/js/packages/kotlinx-rpc-utils-test/node_modules/puppeteer-core/lib/cjs/puppeteer/node/ProductLauncher.js:295:27)
396
421
@@ -410,27 +435,33 @@ check the [.puppeteerrc.cjs](../.puppeteerrc.cjs) and [chrome_bin.js](../karma/c
410
435
}
411
436
}
412
437
This means the ` puppeteer ` failed to locate Chrome.
413
- Either the cache dir is wrong (check [ .puppeteerrc.cjs] ( ../.puppeteerrc.cjs ) file) or it really isn't there.
414
- <br />
415
- Reasons again vary.
416
- When ` npm ` installs ` puppeteer ` , it should execute script to install the browser too
417
- (On CI to the ` <ROOT_DIR>/.puppeteer/browsers ` directory).
418
- This absence may be caused by the ` --ignore-scripts ` flag.
419
- Check the clean installation (` rm -rf build && ./gradlew clean cleanJsBrowserTest ` ) with ` --debug ` flag.
420
- (Something like ` ./gradlew jsBrowserTest --debug ` ).
421
- ** IMPORTANT: run in docker with ` TEAMCITY_VERSION ` env var set, if you are chasing a CI fail** .
422
- <br />
423
- The property is set in [ npm.kt] ( ../gradle-conventions/src/main/kotlin/util/tasks/npm.kt ) , see ` ignoreScripts ` ,
424
- it should be ` false ` .
425
- <br />
426
- If this is not the case, check the debug log for other ` node ` -related issues.
427
- Try installing browsers manually: ` ~/.gradle/nodejs/node-v22.0.0-linux-x64/bin/node build/js/node_modules/puppeteer/install.mjs `
428
- If this works — problem is somewhere in KGP and probably your configs.
429
- Check that your config (like ones with ` ignoreScript ` ) are actually applied,
430
- as they use on demand execution and may target wrong plugin or extension and never be executed.
431
- <br />
432
- ** Bonus** : it may not be installed, because npm install doesn't do this.
433
- See the long comment in [ npm.kt] ( ../gradle-conventions/src/main/kotlin/util/tasks/npm.kt ) .
438
+ Either the cache dir is wrong (check [ .puppeteerrc.cjs] ( ../.puppeteerrc.cjs ) file) or it really isn't there.
439
+
440
+ Reasons again vary.
441
+
442
+ - When ` npm ` installs ` puppeteer ` , it should execute script to install the browser too
443
+ (On CI to the ` <ROOT_DIR>/.puppeteer/browsers ` directory).
444
+ This absence may be caused by the ` --ignore-scripts ` flag.
445
+
446
+ Check the clean installation (` rm -rf build && ./gradlew clean cleanJsBrowserTest ` ) with ` --debug ` flag.
447
+ (Something like ` ./gradlew jsBrowserTest --debug ` ).
448
+
449
+ The property is set in [ npm.kt] ( ../gradle-conventions/src/main/kotlin/util/tasks/npm.kt ) , see ` ignoreScripts ` ,
450
+ it should be ` false ` .
451
+
452
+ ** IMPORTANT: run in docker with ` TEAMCITY_VERSION ` env var set, if you are chasing a CI fail** .
453
+
454
+ - If this is not the case, check the debug log for other ` node ` -related issues.
455
+ Try installing browsers manually:
456
+
457
+ ~ /.gradle/nodejs/node-v22.0.0-linux-x64/bin/node build/js/node_modules/puppeteer/install.mjs
458
+
459
+ If this works — problem is somewhere in KGP and probably your configs.
460
+ Check that your config (like ones with ` ignoreScript ` ) are actually applied,
461
+ as they use on demand execution and may target wrong plugin or extension and never be executed.
462
+
463
+ ** Bonus** : it may not be installed, because npm install doesn't do this.
464
+ See the long comment in [ npm.kt] ( ../gradle-conventions/src/main/kotlin/util/tasks/npm.kt ) .
434
465
435
466
Something doesn't work, and you are sure it's not your fault? Report it appropriately! Don't be lazy.
436
467
0 commit comments