├── .gitignore
├── .idea
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── gradle.xml
├── inspectionProfiles
│ └── Project_Default.xml
└── saveactions_settings.xml
├── LICENSE
├── README.md
├── build.gradle.kts
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── resources-jvm
└── META-INF
│ └── services
│ └── org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
├── settings.gradle.kts
└── sources-jvm
├── compiler
├── CompilationMessage.kt
├── CompilationResult.kt
├── GeneratedFile.kt
├── InMemoryMessageCollector.kt
├── KotlinCompiler.kt
└── KotlinJvmTarget.kt
├── kapt
├── KaptComponentRegistrar.kt
├── KaptConfiguration.kt
└── KaptExtension.kt
└── utility
├── Any.kt
├── ClassLoader.kt
└── KaptOptions.kt
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea/**
2 | !/.idea/codeStyles/
3 | !/.idea/codeStyles/**
4 | !/.idea/inspectionProfiles/
5 | !/.idea/inspectionProfiles/**
6 | !/.idea/runConfigurations/
7 | !/.idea/runConfigurations/**
8 | !/.idea/gradle.xml
9 | !/.idea/saveactions_settings.xml
10 | .DS_Store
11 | .gradle
12 | build
13 | out
14 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
--------------------------------------------------------------------------------
/.idea/saveactions_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | Copyright 2019-today by Marc Knaup (marc@knaup.io)
179 |
180 | Licensed under the Apache License, Version 2.0 (the "License");
181 | you may not use this file except in compliance with the License.
182 | You may obtain a copy of the License at
183 |
184 | http://www.apache.org/licenses/LICENSE-2.0
185 |
186 | Unless required by applicable law or agreed to in writing, software
187 | distributed under the License is distributed on an "AS IS" BASIS,
188 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
189 | See the License for the specific language governing permissions and
190 | limitations under the License.
191 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | fluid-compiler
2 | ==============
3 |
4 | [](https://search.maven.org/artifact/io.fluidsonic.compiler/fluid-compiler)
5 | [](https://github.com/JetBrains/kotlin/releases/v1.8.22)
6 | [](https://kotlinlang.slack.com/messages/C7UDFSVT2/)
7 |
8 | Compile Kotlin code and run Kapt annotation processing directly from Kotlin, for example to unit test your annotation processors!
9 |
10 |
11 |
12 | Installation
13 | ------------
14 |
15 | `build.gradle.kts`:
16 |
17 | ```kotlin
18 | dependencies {
19 | implementation("io.fluidsonic.compiler:fluid-compiler:0.13.0")
20 | }
21 | ```
22 |
23 | Example
24 | -------
25 |
26 | ```kotlin
27 | import io.fluidsonic.compiler.*
28 |
29 | val result = KotlinCompiler()
30 | .includesCurrentClasspath()
31 | .jvmTarget(KotlinJvmTarget.v1_8)
32 | .processors(MyAnnotationProcessor())
33 | .sources("sources", "more-sources/Example.kt")
34 | .compile()
35 |
36 | // result.exitCode contains the exit code of the compiler
37 | // result.messages contains all messages printed during compilation and annotation processing
38 | // result.generatedFiles contains all files generated by annotation processors
39 | ```
40 |
41 | ### Additional configuration
42 |
43 | ```kotlin
44 | .destination("output")
45 | .kotlinHome("/path/to/kotlin/home")
46 | .moduleName("my-module")
47 | ```
48 |
49 | ### Manually setting compiler arguments
50 |
51 | ```kotlin
52 | .arguments {
53 | apiVersion = "1.4"
54 | languageVersion = "1.6"
55 | newInference = true
56 | }
57 | ```
58 |
59 | For a complete list of all compiler arguments check out
60 | [K2JVMCompilerArguments](https://github.com/JetBrains/kotlin/blob/master/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt)
61 | .
62 |
63 | ### Manually setting Kapt options
64 |
65 | ```kotlin
66 | .kaptOptions {
67 | flags += KaptFlag.CORRECT_ERROR_TYPES
68 | mode = AptMode.STUBS_AND_APT
69 | }
70 | ```
71 |
72 | For a complete list of all Kapt options check out
73 | [KaptOptions](https://github.com/JetBrains/kotlin/blob/master/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/KaptOptions.kt).
74 |
75 |
76 |
77 | License
78 | -------
79 |
80 | Apache 2.0
81 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import io.fluidsonic.gradle.*
2 |
3 | plugins {
4 | id("io.fluidsonic.gradle") version "1.3.1"
5 | }
6 |
7 | fluidLibrary(name = "compiler", version = "0.13.0")
8 |
9 | fluidLibraryModule(description = "Compile Kotlin code and run Kapt annotation processing directly from Kotlin") {
10 | targets {
11 | jvm {
12 | dependencies {
13 | api(kotlin("compiler-embeddable"))
14 | api(kotlin("annotation-processing-embeddable"))
15 | }
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluidsonic/fluid-compiler/08db992fe36d0d5638dbec1826d1f164ff1e38c4/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-all.zip
4 | networkTimeout=10000
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | # This is normally unused
84 | # shellcheck disable=SC2034
85 | APP_BASE_NAME=${0##*/}
86 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
87 |
88 | # Use the maximum available, or set MAX_FD != -1 to use that value.
89 | MAX_FD=maximum
90 |
91 | warn () {
92 | echo "$*"
93 | } >&2
94 |
95 | die () {
96 | echo
97 | echo "$*"
98 | echo
99 | exit 1
100 | } >&2
101 |
102 | # OS specific support (must be 'true' or 'false').
103 | cygwin=false
104 | msys=false
105 | darwin=false
106 | nonstop=false
107 | case "$( uname )" in #(
108 | CYGWIN* ) cygwin=true ;; #(
109 | Darwin* ) darwin=true ;; #(
110 | MSYS* | MINGW* ) msys=true ;; #(
111 | NONSTOP* ) nonstop=true ;;
112 | esac
113 |
114 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
115 |
116 |
117 | # Determine the Java command to use to start the JVM.
118 | if [ -n "$JAVA_HOME" ] ; then
119 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
120 | # IBM's JDK on AIX uses strange locations for the executables
121 | JAVACMD=$JAVA_HOME/jre/sh/java
122 | else
123 | JAVACMD=$JAVA_HOME/bin/java
124 | fi
125 | if [ ! -x "$JAVACMD" ] ; then
126 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
127 |
128 | Please set the JAVA_HOME variable in your environment to match the
129 | location of your Java installation."
130 | fi
131 | else
132 | JAVACMD=java
133 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
134 |
135 | Please set the JAVA_HOME variable in your environment to match the
136 | location of your Java installation."
137 | fi
138 |
139 | # Increase the maximum file descriptors if we can.
140 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
141 | case $MAX_FD in #(
142 | max*)
143 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
144 | # shellcheck disable=SC3045
145 | MAX_FD=$( ulimit -H -n ) ||
146 | warn "Could not query maximum file descriptor limit"
147 | esac
148 | case $MAX_FD in #(
149 | '' | soft) :;; #(
150 | *)
151 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
152 | # shellcheck disable=SC3045
153 | ulimit -n "$MAX_FD" ||
154 | warn "Could not set maximum file descriptor limit to $MAX_FD"
155 | esac
156 | fi
157 |
158 | # Collect all arguments for the java command, stacking in reverse order:
159 | # * args from the command line
160 | # * the main class name
161 | # * -classpath
162 | # * -D...appname settings
163 | # * --module-path (only if needed)
164 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
165 |
166 | # For Cygwin or MSYS, switch paths to Windows format before running java
167 | if "$cygwin" || "$msys" ; then
168 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
169 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
170 |
171 | JAVACMD=$( cygpath --unix "$JAVACMD" )
172 |
173 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
174 | for arg do
175 | if
176 | case $arg in #(
177 | -*) false ;; # don't mess with options #(
178 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
179 | [ -e "$t" ] ;; #(
180 | *) false ;;
181 | esac
182 | then
183 | arg=$( cygpath --path --ignore --mixed "$arg" )
184 | fi
185 | # Roll the args list around exactly as many times as the number of
186 | # args, so each arg winds up back in the position where it started, but
187 | # possibly modified.
188 | #
189 | # NB: a `for` loop captures its iteration list before it begins, so
190 | # changing the positional parameters here affects neither the number of
191 | # iterations, nor the values presented in `arg`.
192 | shift # remove old arg
193 | set -- "$@" "$arg" # push replacement arg
194 | done
195 | fi
196 |
197 |
198 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
199 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
200 |
201 | # Collect all arguments for the java command;
202 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
203 | # shell script including quotes and variable substitutions, so put them in
204 | # double quotes to make sure that they get re-expanded; and
205 | # * put everything else in single quotes, so that it's not re-expanded.
206 |
207 | set -- \
208 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
209 | -classpath "$CLASSPATH" \
210 | org.gradle.wrapper.GradleWrapperMain \
211 | "$@"
212 |
213 | # Stop when "xargs" is not available.
214 | if ! command -v xargs >/dev/null 2>&1
215 | then
216 | die "xargs is not available"
217 | fi
218 |
219 | # Use "xargs" to parse quoted args.
220 | #
221 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
222 | #
223 | # In Bash we could simply go:
224 | #
225 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
226 | # set -- "${ARGS[@]}" "$@"
227 | #
228 | # but POSIX shell has neither arrays nor command substitution, so instead we
229 | # post-process each arg (as a line of input to sed) to backslash-escape any
230 | # character that might be a shell metacharacter, then use eval to reverse
231 | # that process (while maintaining the separation between arguments), and wrap
232 | # the whole thing up as a single "set" statement.
233 | #
234 | # This will of course break if any of these variables contains a newline or
235 | # an unmatched quote.
236 | #
237 |
238 | eval "set -- $(
239 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
240 | xargs -n1 |
241 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
242 | tr '\n' ' '
243 | )" '"$@"'
244 |
245 | exec "$JAVACMD" "$@"
246 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | @rem This is normally unused
30 | set APP_BASE_NAME=%~n0
31 | set APP_HOME=%DIRNAME%
32 |
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35 |
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38 |
39 | @rem Find java.exe
40 | if defined JAVA_HOME goto findJavaFromJavaHome
41 |
42 | set JAVA_EXE=java.exe
43 | %JAVA_EXE% -version >NUL 2>&1
44 | if %ERRORLEVEL% equ 0 goto execute
45 |
46 | echo.
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48 | echo.
49 | echo Please set the JAVA_HOME variable in your environment to match the
50 | echo location of your Java installation.
51 |
52 | goto fail
53 |
54 | :findJavaFromJavaHome
55 | set JAVA_HOME=%JAVA_HOME:"=%
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57 |
58 | if exist "%JAVA_EXE%" goto execute
59 |
60 | echo.
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62 | echo.
63 | echo Please set the JAVA_HOME variable in your environment to match the
64 | echo location of your Java installation.
65 |
66 | goto fail
67 |
68 | :execute
69 | @rem Setup the command line
70 |
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72 |
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if %ERRORLEVEL% equ 0 goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | set EXIT_CODE=%ERRORLEVEL%
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87 | exit /b %EXIT_CODE%
88 |
89 | :mainEnd
90 | if "%OS%"=="Windows_NT" endlocal
91 |
92 | :omega
93 |
--------------------------------------------------------------------------------
/resources-jvm/META-INF/services/org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar:
--------------------------------------------------------------------------------
1 | io.fluidsonic.compiler.KaptComponentRegistrar
2 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | rootProject.name = "fluid-compiler"
2 |
--------------------------------------------------------------------------------
/sources-jvm/compiler/CompilationMessage.kt:
--------------------------------------------------------------------------------
1 | package io.fluidsonic.compiler
2 |
3 | import org.jetbrains.kotlin.cli.common.messages.*
4 |
5 |
6 | public data class CompilationMessage(
7 | val location: CompilerMessageSourceLocation?,
8 | val message: String,
9 | val severity: CompilerMessageSeverity
10 | ) {
11 |
12 | override fun toString(): String = buildString {
13 | append(severity.presentableName)
14 |
15 | if (location != null) {
16 | append(" [at ")
17 | append(location)
18 | append("]")
19 | }
20 |
21 | append(": ")
22 | append(message)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/sources-jvm/compiler/CompilationResult.kt:
--------------------------------------------------------------------------------
1 | package io.fluidsonic.compiler
2 |
3 | import org.jetbrains.kotlin.cli.common.*
4 |
5 |
6 | public data class CompilationResult(
7 | val exitCode: ExitCode,
8 | val generatedFiles: Collection,
9 | val messages: List
10 | )
11 |
--------------------------------------------------------------------------------
/sources-jvm/compiler/GeneratedFile.kt:
--------------------------------------------------------------------------------
1 | package io.fluidsonic.compiler
2 |
3 | import java.io.*
4 |
5 |
6 | public data class GeneratedFile(
7 | val content: String,
8 | val path: File
9 | )
10 |
--------------------------------------------------------------------------------
/sources-jvm/compiler/InMemoryMessageCollector.kt:
--------------------------------------------------------------------------------
1 | package io.fluidsonic.compiler
2 |
3 | import org.jetbrains.kotlin.cli.common.messages.*
4 |
5 |
6 | internal class InMemoryMessageCollector : MessageCollector {
7 |
8 | private var hasErrors = false
9 | private val _messages = mutableListOf()
10 |
11 |
12 | override fun clear() {
13 | _messages.clear()
14 | }
15 |
16 |
17 | override fun hasErrors() =
18 | hasErrors
19 |
20 |
21 | val messages
22 | get() = _messages.toList()
23 |
24 |
25 | override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) {
26 | if (severity.isError)
27 | hasErrors = true
28 |
29 | _messages += CompilationMessage(location = location, message = message, severity = severity)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/sources-jvm/compiler/KotlinCompiler.kt:
--------------------------------------------------------------------------------
1 | package io.fluidsonic.compiler
2 |
3 | import org.jetbrains.kotlin.base.kapt3.*
4 | import org.jetbrains.kotlin.cli.common.arguments.*
5 | import org.jetbrains.kotlin.cli.common.messages.*
6 | import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
7 | import org.jetbrains.kotlin.cli.jvm.*
8 | import org.jetbrains.kotlin.com.intellij.ide.highlighter.*
9 | import org.jetbrains.kotlin.com.intellij.openapi.application.*
10 | import org.jetbrains.kotlin.config.*
11 | import org.jetbrains.kotlin.idea.*
12 | import java.io.*
13 | import javax.annotation.processing.*
14 | import kotlin.io.path.*
15 |
16 |
17 | public class KotlinCompiler {
18 |
19 | @PublishedApi
20 | internal val arguments: K2JVMCompilerArguments = K2JVMCompilerArguments().apply {
21 | compileJava = true
22 | useJavac = true
23 | }
24 |
25 | private var includesCurrentClasspath = false
26 |
27 | @PublishedApi
28 | internal val kaptOptions: KaptOptions.Builder = KaptOptions.Builder()
29 |
30 | @PublishedApi
31 | internal var kaptOptionsModified: Boolean = false
32 |
33 | internal val processors = mutableListOf()
34 |
35 |
36 | public fun compile(): CompilationResult {
37 | // TODO lots of backup here unless we make K2JVMCompilerArguments copyable - but then we have to update the copy method with every compiler update…
38 | val initialClasspath = arguments.classpath
39 | val initialNoStdlib = arguments.noStdlib
40 | val initialPluginClasspaths = arguments.pluginClasspaths
41 | val initialFreeArgs = arguments.freeArgs
42 |
43 | val usesKapt = processors.isNotEmpty()
44 | val needsDummyKotlinFile = arguments.buildFile == null && !arguments.script && hasOnlyJavaSources(arguments.freeArgs)
45 |
46 | val temporaryOutputDirectory = arguments.destination.isNullOrEmpty().thenTake {
47 | createTempDirectory().also { arguments.destination = it.toString() }
48 | }
49 | val temporaryGeneratedSourcesDirectory = (usesKapt && kaptOptions.sourcesOutputDir == null).thenTake {
50 | createTempDirectory().also { kaptOptions.sourcesOutputDir = it.toFile() }
51 | }
52 | val temporaryGeneratedClassesDirectory = (usesKapt && kaptOptions.classesOutputDir == null).thenTake {
53 | createTempDirectory().also { kaptOptions.classesOutputDir = it.toFile() }
54 | }
55 | val temporaryGeneratedStubsDirectory = (usesKapt && kaptOptions.stubsOutputDir == null).thenTake {
56 | createTempDirectory().also { kaptOptions.stubsOutputDir = it.toFile() }
57 | }
58 | val dummyKotlinFile = needsDummyKotlinFile.thenTake {
59 | createTempFile(suffix = ".kt").normalize().also { arguments.freeArgs += it.toString() }
60 | }
61 |
62 | try {
63 | if (!loadToolsJarIfNeeded())
64 | error("tools.jar is missing in the current classpath and cannot be found in JAVA HOME. Please add it manually to your project.")
65 |
66 | arguments.pluginClasspaths = (arguments.pluginClasspaths.orEmpty()
67 | .filter { it != servicesPath } + servicesPath).toTypedArray()
68 |
69 | if (includesCurrentClasspath) {
70 | arguments.classpath = arguments.classpath
71 | ?.split(':')
72 | ?.toSet()
73 | .orEmpty()
74 | .let { it + currentClasspath }
75 | .joinToString(":")
76 |
77 | if (arguments.kotlinHome.isNullOrEmpty())
78 | arguments.noStdlib = true
79 | }
80 |
81 | val messageCollector = InMemoryMessageCollector()
82 | val kaptConfiguration = usesKapt.thenTake {
83 | KaptConfiguration(
84 | options = try {
85 | kaptOptions.build()
86 | }
87 | catch (e: Exception) {
88 | throw IllegalStateException("Kapt configured incorrectly: ${e.message}", e)
89 | },
90 | processors = processors
91 | )
92 | }
93 |
94 | val exitCode = withKaptConfiguration(kaptConfiguration) {
95 | K2JVMCompiler().exec(
96 | messageCollector = FilteringMessageCollector(messageCollector, VERBOSE::contains),
97 | services = Services.EMPTY,
98 | arguments = arguments
99 | )
100 | }
101 |
102 | val generatedFiles = temporaryGeneratedSourcesDirectory?.toFile()?.walkTopDown()
103 | ?.filter { it.isFile }
104 | ?.map { file ->
105 | GeneratedFile(
106 | content = file.readText(),
107 | path = file.relativeTo(temporaryGeneratedSourcesDirectory.toFile())
108 | )
109 | }
110 | ?.toList()
111 | .orEmpty()
112 |
113 | return CompilationResult(
114 | exitCode = exitCode,
115 | generatedFiles = generatedFiles,
116 | messages = messageCollector.messages
117 | )
118 | }
119 | finally {
120 | arguments.classpath = initialClasspath
121 | arguments.freeArgs = initialFreeArgs
122 | arguments.noStdlib = initialNoStdlib
123 | arguments.pluginClasspaths = initialPluginClasspaths
124 |
125 | try {
126 | if (temporaryOutputDirectory != null) {
127 | temporaryOutputDirectory.toFile().deleteRecursively()
128 | arguments.destination = null
129 | }
130 | if (temporaryGeneratedSourcesDirectory != null) {
131 | temporaryGeneratedSourcesDirectory.toFile().deleteRecursively()
132 | kaptOptions.sourcesOutputDir = null
133 | }
134 | if (temporaryGeneratedClassesDirectory != null) {
135 | temporaryGeneratedClassesDirectory.toFile().deleteRecursively()
136 | kaptOptions.classesOutputDir = null
137 | }
138 | if (temporaryGeneratedStubsDirectory != null) {
139 | temporaryGeneratedStubsDirectory.toFile().deleteRecursively()
140 | kaptOptions.stubsOutputDir = null
141 | }
142 |
143 | dummyKotlinFile?.deleteIfExists()
144 | }
145 | catch (e: Exception) {
146 | println("Failed deleting temporary file or directory: $e")
147 | }
148 | }
149 | }
150 |
151 |
152 | public inline fun arguments(block: K2JVMCompilerArguments.() -> Unit): KotlinCompiler = apply {
153 | arguments.block()
154 | }
155 |
156 |
157 | public fun destination(destination: File): KotlinCompiler = apply {
158 | arguments.destination = destination.canonicalPath
159 | }
160 |
161 |
162 | public fun destination(destination: String): KotlinCompiler =
163 | destination(File(destination))
164 |
165 |
166 | public fun includesCurrentClasspath(includesCurrentClasspath: Boolean = true): KotlinCompiler = apply {
167 | this.includesCurrentClasspath = includesCurrentClasspath
168 | }
169 |
170 |
171 | public fun jvmTarget(jvmTarget: KotlinJvmTarget): KotlinCompiler = apply {
172 | arguments.jvmTarget = jvmTarget.string
173 | }
174 |
175 |
176 | public inline fun kaptOptions(block: KaptOptions.Builder.() -> Unit): KotlinCompiler = apply {
177 | kaptOptionsModified = true
178 | kaptOptions.block()
179 | }
180 |
181 |
182 | public fun kotlinHome(kotlinHome: File): KotlinCompiler = apply {
183 | arguments.kotlinHome = kotlinHome.canonicalPath
184 | }
185 |
186 |
187 | public fun kotlinHome(kotlinHome: String): KotlinCompiler =
188 | kotlinHome(File(kotlinHome))
189 |
190 |
191 | public fun moduleName(moduleName: String): KotlinCompiler = apply {
192 | arguments.moduleName = moduleName
193 | }
194 |
195 |
196 | public fun processors(vararg processors: Processor): KotlinCompiler =
197 | processors(processors.toList())
198 |
199 |
200 | public fun processors(processors: Iterable): KotlinCompiler = apply {
201 | this.processors += processors
202 | }
203 |
204 |
205 | public fun sources(vararg sources: File): KotlinCompiler =
206 | sources(sources.toList())
207 |
208 |
209 | public fun sources(sourceFiles: Iterable): KotlinCompiler = apply {
210 | arguments.freeArgs += sourceFiles.map { it.canonicalPath }
211 | }
212 |
213 |
214 | public fun sources(vararg sources: String): KotlinCompiler =
215 | sources(sources.map(::File))
216 |
217 |
218 | @JvmName("sourcesAsString")
219 | public fun sources(sources: Iterable): KotlinCompiler =
220 | sources(sources.map(::File))
221 |
222 |
223 | public companion object {
224 |
225 | private val currentClasspath = findAllClasspathEntries().filter(File::exists).toSet()
226 |
227 |
228 | private val servicesPath = KotlinCompiler::class.java.let { clazz ->
229 | PathManager.getResourceRoot(clazz, "/" + clazz.name.replace('.', '/') + ".class")
230 | ?.let { File(it).absoluteFile }
231 | ?.let { file ->
232 | if (file.isFile) file // in JAR
233 | else file.parentFile.resolve("resources") // run from IntelliJ IDEA
234 | }?.canonicalPath
235 | } ?: File("resources").canonicalPath // fall back to working directory = project path
236 | }
237 | }
238 |
239 |
240 | private fun hasOnlyJavaSources(paths: Collection): Boolean {
241 | var hasJavaSources = false
242 |
243 | for (path in paths)
244 | for (file in File(path).walkTopDown().filter(File::isFile))
245 | when (file.extension) {
246 | JavaFileType.INSTANCE.defaultExtension -> hasJavaSources = true
247 | KotlinFileType.EXTENSION, "kts" -> return false
248 | }
249 |
250 | return hasJavaSources
251 | }
252 |
--------------------------------------------------------------------------------
/sources-jvm/compiler/KotlinJvmTarget.kt:
--------------------------------------------------------------------------------
1 | package io.fluidsonic.compiler
2 |
3 |
4 | @Suppress("EnumEntryName")
5 | public enum class KotlinJvmTarget(internal val string: String) {
6 |
7 | v1_6("1.6"),
8 | v1_8("1.8"),
9 | v9("9"),
10 | v10("10"),
11 | v11("11"),
12 | v12("12"),
13 | v13("13"),
14 | v14("14"),
15 | v15("15"),
16 | v16("16"),
17 | v17("17"),
18 | ;
19 |
20 |
21 | override fun toString(): String = string
22 | }
23 |
--------------------------------------------------------------------------------
/sources-jvm/kapt/KaptComponentRegistrar.kt:
--------------------------------------------------------------------------------
1 | package io.fluidsonic.compiler
2 |
3 | import org.jetbrains.kotlin.analyzer.*
4 | import org.jetbrains.kotlin.base.kapt3.*
5 | import org.jetbrains.kotlin.cli.common.*
6 | import org.jetbrains.kotlin.cli.common.messages.*
7 | import org.jetbrains.kotlin.cli.jvm.config.*
8 | import org.jetbrains.kotlin.com.intellij.mock.*
9 | import org.jetbrains.kotlin.com.intellij.openapi.project.*
10 | import org.jetbrains.kotlin.compiler.plugin.*
11 | import org.jetbrains.kotlin.config.*
12 | import org.jetbrains.kotlin.container.*
13 | import org.jetbrains.kotlin.context.*
14 | import org.jetbrains.kotlin.descriptors.*
15 | import org.jetbrains.kotlin.extensions.*
16 | import org.jetbrains.kotlin.kapt3.*
17 | import org.jetbrains.kotlin.kapt3.base.*
18 | import org.jetbrains.kotlin.kapt3.base.incremental.*
19 | import org.jetbrains.kotlin.kapt3.base.util.*
20 | import org.jetbrains.kotlin.kapt3.util.*
21 | import org.jetbrains.kotlin.psi.*
22 | import org.jetbrains.kotlin.resolve.*
23 | import org.jetbrains.kotlin.resolve.jvm.extensions.*
24 | import java.io.*
25 | import kotlin.collections.set
26 |
27 |
28 | private val kaptConfiguration = ThreadLocal()
29 |
30 |
31 | @OptIn(ExperimentalCompilerApi::class)
32 | internal class KaptComponentRegistrar : ComponentRegistrar {
33 |
34 | // https://github.com/JetBrains/kotlin/blob/d6459e6c49227be11323ce59310407b17005c117/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt#L150
35 | override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
36 | val kaptConfiguration = kaptConfiguration.get() ?: return
37 | if (kaptConfiguration.processors.isEmpty()) return
38 |
39 | val contentRoots = configuration[CLIConfigurationKeys.CONTENT_ROOTS] ?: emptyList()
40 |
41 | val optionsBuilder = kaptConfiguration.options.toBuilder().apply {
42 | projectBaseDir = project.basePath?.let(::File)
43 | compileClasspath.addAll(contentRoots.filterIsInstance().map { it.file })
44 | javaSourceRoots.addAll(contentRoots.filterIsInstance().map { it.file })
45 | classesOutputDir = classesOutputDir ?: configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)
46 | }
47 |
48 | val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
49 | ?: PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, optionsBuilder.flags.contains(KaptFlag.VERBOSE))
50 |
51 | val logger = MessageCollectorBackedKaptLogger(
52 | optionsBuilder.flags.contains(KaptFlag.VERBOSE),
53 | optionsBuilder.flags.contains(KaptFlag.INFO_AS_WARNINGS),
54 | messageCollector
55 | )
56 |
57 | if (!optionsBuilder.checkOptions(project, logger, configuration)) {
58 | return
59 | }
60 |
61 | if (!optionsBuilder.processingOptions.containsKey(ProcessingOptions.kotlinSourcesOutputDirectory)) {
62 | optionsBuilder.processingOptions[ProcessingOptions.kotlinSourcesOutputDirectory] = optionsBuilder.sourcesOutputDir?.absolutePath
63 | ?: error("sourcesOutputDir should be set at this point")
64 | }
65 |
66 | val options = optionsBuilder.build()
67 |
68 | options.sourcesOutputDir.mkdirs()
69 |
70 | if (options[KaptFlag.VERBOSE]) {
71 | logger.info(options.logString())
72 | }
73 |
74 | val kapt3AnalysisCompletedHandlerExtension = KaptExtension(
75 | compilerConfiguration = configuration,
76 | logger = logger,
77 | options = options,
78 | processors = kaptConfiguration.processors.map { processor ->
79 | IncrementalProcessor(
80 | processor = processor,
81 | kind = DeclaredProcType.NON_INCREMENTAL,
82 | logger = logger
83 | )
84 | }
85 | )
86 |
87 | AnalysisHandlerExtension.registerExtension(project, kapt3AnalysisCompletedHandlerExtension)
88 | StorageComponentContainerContributor.registerExtension(project, Kapt3ComponentRegistrar.KaptComponentContributor(kapt3AnalysisCompletedHandlerExtension))
89 | }
90 |
91 |
92 | private object ProcessingOptions {
93 |
94 | const val kotlinSourcesOutputDirectory = "kapt.kotlin.generated"
95 | }
96 |
97 |
98 | // https://github.com/JetBrains/kotlin/blob/d6459e6c49227be11323ce59310407b17005c117/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt#L186
99 | private fun KaptOptions.Builder.checkOptions(project: MockProject, logger: KaptLogger, configuration: CompilerConfiguration): Boolean {
100 | fun abortAnalysis() = AnalysisHandlerExtension.registerExtension(project, AbortAnalysisHandlerExtension())
101 |
102 | if (classesOutputDir == null) {
103 | if (configuration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) {
104 | logger.error("Kapt does not support specifying JAR file outputs. Please specify the classes output directory explicitly.")
105 | abortAnalysis()
106 | return false
107 | }
108 | else {
109 | classesOutputDir = configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)
110 | }
111 | }
112 |
113 | // not used as we pass Processor instances directly
114 | // if (processingClasspath.isEmpty()) {
115 | // // Skip annotation processing if no annotation processors were provided
116 | // if (mode != AptMode.WITH_COMPILATION) {
117 | // abortAnalysis()
118 | // }
119 | // return false
120 | // }
121 |
122 | if (sourcesOutputDir == null || classesOutputDir == null || stubsOutputDir == null) {
123 | if (mode != AptMode.WITH_COMPILATION) {
124 | val nonExistentOptionName = when {
125 | sourcesOutputDir == null -> "Sources output directory"
126 | classesOutputDir == null -> "Classes output directory"
127 | stubsOutputDir == null -> "Stubs output directory"
128 | else -> throw IllegalStateException()
129 | }
130 | val moduleName = configuration.get(CommonConfigurationKeys.MODULE_NAME)
131 | ?: configuration.get(JVMConfigurationKeys.MODULES).orEmpty().joinToString()
132 |
133 | logger.warn("$nonExistentOptionName is not specified for $moduleName, skipping annotation processing")
134 | abortAnalysis()
135 | }
136 | return false
137 | }
138 |
139 | if (!Kapt.checkJavacComponentsAccess(logger)) {
140 | abortAnalysis()
141 | return false
142 | }
143 |
144 | return true
145 | }
146 |
147 |
148 | // https://github.com/JetBrains/kotlin/blob/d6459e6c49227be11323ce59310407b17005c117/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/Kapt3Plugin.kt#L243
149 | /* This extension simply disables both code analysis and code generation.
150 | * When aptOnly is true, and any of required kapt options was not passed, we just abort compilation by providing this extension.
151 | * */
152 | private class AbortAnalysisHandlerExtension : AnalysisHandlerExtension {
153 | override fun doAnalysis(
154 | project: Project,
155 | module: ModuleDescriptor,
156 | projectContext: ProjectContext,
157 | files: Collection,
158 | bindingTrace: BindingTrace,
159 | componentProvider: ComponentProvider
160 | ): AnalysisResult {
161 | return AnalysisResult.success(bindingTrace.bindingContext, module, shouldGenerateCode = false)
162 | }
163 |
164 | override fun analysisCompleted(
165 | project: Project,
166 | module: ModuleDescriptor,
167 | bindingTrace: BindingTrace,
168 | files: Collection
169 | ): AnalysisResult {
170 | return AnalysisResult.success(bindingTrace.bindingContext, module, shouldGenerateCode = false)
171 | }
172 | }
173 | }
174 |
175 |
176 | internal inline fun withKaptConfiguration(configuration: KaptConfiguration?, block: () -> R): R {
177 | configuration ?: return block()
178 |
179 | val previousConfiguration = kaptConfiguration.get()
180 | kaptConfiguration.set(configuration)
181 |
182 | try {
183 | return block()
184 | }
185 | finally {
186 | kaptConfiguration.set(previousConfiguration)
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/sources-jvm/kapt/KaptConfiguration.kt:
--------------------------------------------------------------------------------
1 | package io.fluidsonic.compiler
2 |
3 | import org.jetbrains.kotlin.base.kapt3.*
4 | import javax.annotation.processing.*
5 |
6 |
7 | internal class KaptConfiguration(
8 | val options: KaptOptions,
9 | val processors: Collection
10 | )
11 |
--------------------------------------------------------------------------------
/sources-jvm/kapt/KaptExtension.kt:
--------------------------------------------------------------------------------
1 | package io.fluidsonic.compiler
2 |
3 | import org.jetbrains.kotlin.base.kapt3.*
4 | import org.jetbrains.kotlin.config.*
5 | import org.jetbrains.kotlin.kapt3.*
6 | import org.jetbrains.kotlin.kapt3.base.*
7 | import org.jetbrains.kotlin.kapt3.base.incremental.*
8 | import org.jetbrains.kotlin.kapt3.util.*
9 |
10 |
11 | internal class KaptExtension(
12 | compilerConfiguration: CompilerConfiguration,
13 | logger: MessageCollectorBackedKaptLogger,
14 | options: KaptOptions,
15 | processors: Collection
16 | ) : AbstractKapt3Extension(
17 | compilerConfiguration = compilerConfiguration,
18 | logger = logger,
19 | options = options
20 | ) {
21 |
22 | private val processors = LoadedProcessors(
23 | processors = processors.toList(),
24 | classLoader = this::class.java.classLoader
25 | )
26 |
27 |
28 | override fun loadProcessors() =
29 | processors
30 | }
31 |
--------------------------------------------------------------------------------
/sources-jvm/utility/Any.kt:
--------------------------------------------------------------------------------
1 | package io.fluidsonic.compiler
2 |
3 |
4 | internal inline fun Boolean.thenTake(block: () -> Result): Result? =
5 | if (this) block() else null
6 |
--------------------------------------------------------------------------------
/sources-jvm/utility/ClassLoader.kt:
--------------------------------------------------------------------------------
1 | package io.fluidsonic.compiler
2 |
3 | import java.io.*
4 | import java.net.*
5 |
6 |
7 | private const val appClassLoaderName = "jdk.internal.loader.ClassLoaders\$AppClassLoader"
8 |
9 |
10 | private fun ClassLoader.addUrl(url: URL): Boolean {
11 | try {
12 | val classPath = urlClassPath ?: return false
13 | val addUrl = classPath::class.java.getDeclaredMethod("addURL", URL::class.java) ?: return false
14 | addUrl.invoke(classPath, url)
15 |
16 | return true
17 | }
18 | catch (e: Exception) {
19 | return false
20 | }
21 | }
22 |
23 |
24 | private val ClassLoader.urlClassPath: Any?
25 | get() = try {
26 | (this is URLClassLoader || this::class.java.name == appClassLoaderName).thenTake {
27 | this::class.java.getDeclaredField("ucp")
28 | .also { it.isAccessible = true }
29 | .get(this)
30 | }
31 | }
32 | catch (e: Exception) {
33 | null
34 | }
35 |
36 |
37 | @Suppress("UNCHECKED_CAST")
38 | private val ClassLoader.urls: Collection?
39 | get() = when {
40 | this is URLClassLoader ->
41 | urLs.toList()
42 |
43 | this::class.java.name == appClassLoaderName ->
44 | try {
45 | urlClassPath?.let { urlClassPath ->
46 | urlClassPath::class.java.getDeclaredMethod("getURLs")
47 | .invoke(urlClassPath)
48 | ?.let { it as? Array }
49 | ?.toList()
50 | }
51 | }
52 | catch (e: Exception) {
53 | null
54 | }
55 |
56 | else ->
57 | null
58 | }
59 |
60 |
61 | internal fun findAllClasspathEntries(): Set =
62 | (findSystemPropertyClasspathEntries() +
63 | findSystemClassLoaderClasspathEntries() +
64 | findClasspathEntriesUsingManifest())
65 | .map { it.absoluteFile }
66 | .toSet()
67 |
68 |
69 | private fun findSystemClassLoaderClasspathEntries(): Collection =
70 | ClassLoader.getSystemClassLoader().findAllClasspathEntries()
71 |
72 |
73 | private fun findClasspathEntriesUsingManifest(): Collection =
74 | ClassLoader.getSystemClassLoader().getResources("META-INF/MANIFEST.MF")
75 | .toList()
76 | .filter { it.protocol == "jar" }
77 | .map { File(it.path.removePrefix("file:").substringBeforeLast('!')) }
78 |
79 |
80 | private fun findSystemPropertyClasspathEntries(): Collection =
81 | System.getProperty("java.class.path").split(':').map(::File)
82 |
83 |
84 | private fun ClassLoader.findAllClasspathEntries(): Collection =
85 | urls?.map { File(it.toURI()) }.orEmpty() + parent?.findAllClasspathEntries().orEmpty()
86 |
87 |
88 | internal fun loadToolsJarIfNeeded(): Boolean {
89 | try {
90 | Class.forName("com.sun.tools.javac.util.Context")
91 | return true
92 | }
93 | catch (e: ClassNotFoundException) {
94 | // not loaded
95 | }
96 |
97 | val toolsJar = findToolsJar() ?: return false
98 | ClassLoader.getSystemClassLoader().addUrl(toolsJar.toURI().toURL())
99 |
100 | return try {
101 | Class.forName("com.sun.tools.javac.util.Context")
102 | true
103 | }
104 | catch (e: ClassNotFoundException) {
105 | false
106 | }
107 | }
108 |
109 |
110 | private fun findToolsJar(): File? =
111 | System.getProperty("java.home").ifEmpty { null }?.let(::File)?.let(::findToolsJar)
112 | ?: System.getenv("JAVA_HOME").ifEmpty { null }?.let(::File)?.let(::findToolsJar)
113 |
114 |
115 | private fun findToolsJar(javaHome: File): File? {
116 | javaHome.resolve("lib/tools.jar").takeIf(File::exists)?.let { return it }
117 |
118 | if (javaHome.name.equals("jre", ignoreCase = true))
119 | findToolsJar(javaHome.parentFile)?.let { return it }
120 |
121 | if (javaHome.name.matches(Regex("jre\\d+")) || javaHome.name == "jre${System.getProperty("java.version")}")
122 | findToolsJar(javaHome.parentFile.resolve("jdk" + javaHome.name.removePrefix("jre")))
123 |
124 | return null
125 | }
126 |
--------------------------------------------------------------------------------
/sources-jvm/utility/KaptOptions.kt:
--------------------------------------------------------------------------------
1 | package io.fluidsonic.compiler
2 |
3 | import org.jetbrains.kotlin.base.kapt3.*
4 |
5 |
6 | public fun KaptOptions.toBuilder(): KaptOptions.Builder = let { options ->
7 | KaptOptions.Builder().apply {
8 | classesOutputDir = options.classesOutputDir
9 | compileClasspath += options.compileClasspath
10 | detectMemoryLeaks = options.detectMemoryLeaks
11 | incrementalDataOutputDir = options.incrementalDataOutputDir
12 | javaSourceRoots += options.javaSourceRoots
13 | javacOptions += options.javacOptions
14 | mode = options.mode
15 | processingClasspath += options.processingClasspath
16 | processingOptions += options.processingOptions
17 | processors += options.processors
18 | projectBaseDir = options.projectBaseDir
19 | sourcesOutputDir = options.sourcesOutputDir
20 | stubsOutputDir = options.stubsOutputDir
21 |
22 | for (flag in KaptFlag.values())
23 | if (options[flag])
24 | flags += flag
25 | else
26 | flags -= flag
27 | }
28 | }
29 |
--------------------------------------------------------------------------------