1 /*
2 * Copyright 2022 Google LLC
3 * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package com.google.devtools.ksp
19
20 import org.jetbrains.kotlin.compiler.plugin.AbstractCliOption
21 import org.jetbrains.kotlin.config.ApiVersion
22 import org.jetbrains.kotlin.config.LanguageVersion
23 import org.jetbrains.kotlin.config.toKotlinVersion
24 import java.io.File
25
26 class KspOptions(
27 val projectBaseDir: File,
28 val compileClasspath: List<File>,
29 val javaSourceRoots: List<File>,
30
31 val classOutputDir: File,
32 val javaOutputDir: File,
33 val kotlinOutputDir: File,
34 val resourceOutputDir: File,
35
36 val processingClasspath: List<File>,
37 val processors: List<String>,
38
39 val processingOptions: Map<String, String>,
40
41 val knownModified: List<File>,
42 val knownRemoved: List<File>,
43
44 val cachesDir: File,
45 val kspOutputDir: File,
46 val incremental: Boolean,
47 val incrementalLog: Boolean,
48 val allWarningsAsErrors: Boolean,
49 val withCompilation: Boolean,
50 val returnOkOnError: Boolean,
51 val changedClasses: List<String>,
52
53 val languageVersion: KotlinVersion,
54 val apiVersion: KotlinVersion,
55 val compilerVersion: KotlinVersion,
56
57 val commonSources: List<File>,
58
59 val excludedProcessors: Set<String>,
60 val mapAnnotationArgumentsInJava: Boolean,
61 ) {
62 class Builder {
63 var projectBaseDir: File? = null
64 val compileClasspath: MutableList<File> = mutableListOf()
65 val javaSourceRoots: MutableList<File> = mutableListOf()
66
67 var classOutputDir: File? = null
68 var javaOutputDir: File? = null
69 var kotlinOutputDir: File? = null
70 var resourceOutputDir: File? = null
71
72 val processingClasspath: MutableList<File> = mutableListOf()
73 val processors: MutableList<String> = mutableListOf()
74
75 val processingOptions: MutableMap<String, String> = mutableMapOf()
76
77 val knownModified: MutableList<File> = mutableListOf()
78 val knownRemoved: MutableList<File> = mutableListOf()
79
80 var cachesDir: File? = null
81 var kspOutputDir: File? = null
82 var incremental: Boolean = false
83 var incrementalLog: Boolean = false
84 var allWarningsAsErrors: Boolean = false
85 var withCompilation: Boolean = false
86 // Default is false. It can be turned on to workaround KT-30172.
87 var returnOkOnError: Boolean = false
88 var changedClasses: MutableList<String> = mutableListOf()
89
90 var languageVersion: KotlinVersion = LanguageVersion.LATEST_STABLE.toKotlinVersion()
91 var apiVersion: KotlinVersion = ApiVersion.LATEST_STABLE.toKotlinVersion()
92 var compilerVersion: KotlinVersion = KotlinVersion.CURRENT
93
94 var commonSources: MutableList<File> = mutableListOf()
95
96 var excludedProcessors: MutableSet<String> = mutableSetOf()
97 var mapAnnotationArgumentsInJava: Boolean = false
98
buildnull99 fun build(): KspOptions {
100 return KspOptions(
101 requireNotNull(projectBaseDir) { "A non-null projectBaseDir must be provided" },
102 compileClasspath,
103 javaSourceRoots,
104 requireNotNull(classOutputDir) { "A non-null classOutputDir must be provided" },
105 requireNotNull(javaOutputDir) { "A non-null javaOutputDir must be provided" },
106 requireNotNull(kotlinOutputDir) { "A non-null kotlinOutputDir must be provided" },
107 requireNotNull(resourceOutputDir) { "A non-null resourceOutputDir must be provided" },
108 processingClasspath,
109 processors,
110 processingOptions,
111 knownModified,
112 knownRemoved,
113 requireNotNull(cachesDir) { "A non-null cachesDir must be provided" },
114 requireNotNull(kspOutputDir) { "A non-null kspOutputDir must be provided" },
115 incremental,
116 incrementalLog,
117 allWarningsAsErrors,
118 withCompilation,
119 returnOkOnError,
120 changedClasses,
121 languageVersion,
122 apiVersion,
123 compilerVersion,
124 commonSources,
125 excludedProcessors,
126 mapAnnotationArgumentsInJava,
127 )
128 }
129 }
130 }
131
toKotlinVersionnull132 fun String?.toKotlinVersion(): KotlinVersion {
133 if (this == null)
134 return KotlinVersion.CURRENT
135
136 return split('-').first().split('.').map { it.toInt() }.let {
137 when (it.size) {
138 1 -> KotlinVersion(it[0], 0, 0)
139 2 -> KotlinVersion(it[0], it[1], 0)
140 3 -> KotlinVersion(it[0], it[1], it[2])
141 else -> KotlinVersion.CURRENT
142 }
143 }
144 }
145
ApiVersionnull146 fun ApiVersion.toKotlinVersion(): KotlinVersion = version.canonical.toKotlinVersion()
147
148 enum class KspCliOption(
149 override val optionName: String,
150 override val valueDescription: String,
151 override val description: String,
152 override val required: Boolean = false,
153 override val allowMultipleOccurrences: Boolean = false
154 ) : AbstractCliOption {
155 CLASS_OUTPUT_DIR_OPTION(
156 "classOutputDir",
157 "<classOutputDir>",
158 "Dir of generated classes",
159 false
160 ),
161
162 JAVA_OUTPUT_DIR_OPTION(
163 "javaOutputDir",
164 "<javaOutputDir>",
165 "Dir of generated Java sources",
166 false
167 ),
168
169 KOTLIN_OUTPUT_DIR_OPTION(
170 "kotlinOutputDir",
171 "<kotlinOutputDir>",
172 "Dir of generated Kotlin sources",
173 false
174 ),
175
176 RESOURCE_OUTPUT_DIR_OPTION(
177 "resourceOutputDir",
178 "<resourceOutputDir>",
179 "Dir of generated resources",
180 false
181 ),
182
183 CACHES_DIR_OPTION(
184 "cachesDir",
185 "<cachesDir>",
186 "Dir of caches",
187 false
188 ),
189
190 PROJECT_BASE_DIR_OPTION(
191 "projectBaseDir",
192 "<projectBaseDir>",
193 "path to gradle project",
194 false
195 ),
196
197 KSP_OUTPUT_DIR_OPTION(
198 "kspOutputDir",
199 "<kspOutputDir>",
200 "root of ksp output dirs",
201 false
202 ),
203
204 PROCESSING_OPTIONS_OPTION(
205 "apoption",
206 "<apOption>",
207 "processor defined option",
208 false,
209 true
210 ),
211
212 PROCESSOR_CLASSPATH_OPTION(
213 "apclasspath",
214 "<classpath>",
215 "processor classpath",
216 false
217 ),
218
219 PROCESSOR_NAME_OPTION(
220 "processorNames",
221 "<processorNames>",
222 "only executes following processor(s)",
223 false
224 ),
225
226 KNOWN_MODIFIED_OPTION(
227 "knownModified",
228 "<knownModified>",
229 "known modified files",
230 false,
231 false
232 ),
233
234 KNOWN_REMOVED_OPTION(
235 "knownRemoved",
236 "<knownRemoved>",
237 "known removed fiels",
238 false,
239 false
240 ),
241
242 INCREMENTAL_OPTION(
243 "incremental",
244 "<incremental>",
245 "processing incrementally",
246 false,
247 false
248 ),
249
250 INCREMENTAL_LOG_OPTION(
251 "incrementalLog",
252 "<incrementalLog>",
253 "log dirty files",
254 false,
255 false
256 ),
257
258 ALL_WARNINGS_AS_ERRORS_OPTION(
259 "allWarningsAsErrors",
260 "<allWarningsAsErrors>",
261 "treat all warnings as errors",
262 false,
263 false
264 ),
265
266 WITH_COMPILATION_OPTION(
267 "withCompilation",
268 "<withCompilation>",
269 "Run processors and compilation in a single compiler invocation",
270 false,
271 false
272 ),
273
274 CHANGED_CLASSES_OPTION(
275 "changedClasses",
276 "<changedClasses>",
277 "canonical / dot-separated names of dirty classes in classpath",
278 false,
279 false
280 ),
281
282 RETURN_OK_ON_ERROR_OPTION(
283 "returnOkOnError",
284 "<returnOkOnError>",
285 "Return OK even if there are errors",
286 false,
287 false
288 ),
289
290 COMMON_SOURCES_OPTION(
291 "commonSources",
292 "<commonSources>",
293 "common sources",
294 false,
295 true
296 ),
297
298 EXCLUDED_PROCESSORS_OPTION(
299 "excludedProcessors",
300 "<excludedProcessors>",
301 "exclude providers by fqn",
302 false,
303 true
304 ),
305
306 MAP_ANNOTATION_ARGUMENTS_IN_JAVA_OPTION(
307 "mapAnnotationArgumentsInJava",
308 "<mapAnnotationArgumentsInJava>",
309 "Map types in annotation arguments in Java sources",
310 false,
311 false
312 ),
313 }
314
315 @Suppress("IMPLICIT_CAST_TO_ANY")
KspOptionsnull316 fun KspOptions.Builder.processOption(option: KspCliOption, value: String) = when (option) {
317 KspCliOption.PROCESSOR_CLASSPATH_OPTION -> processingClasspath += value.split(File.pathSeparator).map {
318 File(it)
319 }
320 KspCliOption.PROCESSOR_NAME_OPTION -> processors += value.split(File.pathSeparator)
321 KspCliOption.CLASS_OUTPUT_DIR_OPTION -> classOutputDir = File(value)
322 KspCliOption.JAVA_OUTPUT_DIR_OPTION -> javaOutputDir = File(value)
323 KspCliOption.KOTLIN_OUTPUT_DIR_OPTION -> kotlinOutputDir = File(value)
324 KspCliOption.RESOURCE_OUTPUT_DIR_OPTION -> resourceOutputDir = File(value)
325 KspCliOption.CACHES_DIR_OPTION -> cachesDir = File(value)
326 KspCliOption.KSP_OUTPUT_DIR_OPTION -> kspOutputDir = File(value)
327 KspCliOption.PROJECT_BASE_DIR_OPTION -> projectBaseDir = File(value)
328 KspCliOption.PROCESSING_OPTIONS_OPTION -> {
329 val (k, v) = value.split('=', ignoreCase = false, limit = 2)
330 processingOptions.put(k, v)
331 }
332 KspCliOption.KNOWN_MODIFIED_OPTION -> knownModified.addAll(value.split(File.pathSeparator).map { File(it) })
333 KspCliOption.KNOWN_REMOVED_OPTION -> knownRemoved.addAll(value.split(File.pathSeparator).map { File(it) })
334 KspCliOption.INCREMENTAL_OPTION -> incremental = value.toBoolean()
335 KspCliOption.INCREMENTAL_LOG_OPTION -> incrementalLog = value.toBoolean()
336 KspCliOption.ALL_WARNINGS_AS_ERRORS_OPTION -> allWarningsAsErrors = value.toBoolean()
337 KspCliOption.WITH_COMPILATION_OPTION -> withCompilation = value.toBoolean()
338 KspCliOption.CHANGED_CLASSES_OPTION -> changedClasses.addAll(value.split(':'))
339 KspCliOption.RETURN_OK_ON_ERROR_OPTION -> returnOkOnError = value.toBoolean()
340 KspCliOption.COMMON_SOURCES_OPTION -> commonSources.addAll(value.split(File.pathSeparator).map { File(it) })
341 KspCliOption.EXCLUDED_PROCESSORS_OPTION -> excludedProcessors.addAll(value.split(":"))
342 KspCliOption.MAP_ANNOTATION_ARGUMENTS_IN_JAVA_OPTION -> mapAnnotationArgumentsInJava = value.toBoolean()
343 }
344