• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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