aboutsummaryrefslogtreecommitdiff
path: root/kotlin-analysis-api
diff options
context:
space:
mode:
authorJiaxiang Chen <jiaxiang@google.com>2022-03-21 22:41:44 -0700
committerJiaxiang Chen <roaringacw@gmail.com>2022-03-28 19:06:44 -0700
commit6c906beef9720a431343914c523d700af9c510a6 (patch)
tree8e6cabc439b3466232d5dba625eae94bc5b14d7d /kotlin-analysis-api
parentd6f2b6eef0b466a35fc4b8e1e14ee8ef05cf03e6 (diff)
downloadksp-6c906beef9720a431343914c523d700af9c510a6.tar.gz
* Extract CodeGeneratorImpl, PlatformInfoImpl into common-util module, add copyright to common-util module classes.
* Add KSP Command line processor and logger. * Implement KSP main execution and initialization logic.
Diffstat (limited to 'kotlin-analysis-api')
-rw-r--r--kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/CommandLineKSPLogger.kt45
-rw-r--r--kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KSPCommandLineProcessor.kt57
-rw-r--r--kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt143
-rw-r--r--kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/impl/test/AbstractKSPAATest.kt32
-rw-r--r--kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/impl/test/KotlinAnalysisAPITest.kt12
5 files changed, 227 insertions, 62 deletions
diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/CommandLineKSPLogger.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/CommandLineKSPLogger.kt
new file mode 100644
index 00000000..223e2db2
--- /dev/null
+++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/CommandLineKSPLogger.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2022 Google LLC
+ * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.devtools.ksp.impl
+
+import com.google.devtools.ksp.processing.KSPLogger
+import com.google.devtools.ksp.symbol.KSNode
+
+class CommandLineKSPLogger : KSPLogger {
+ // TODO: support logging level.
+ val messager = System.err
+ override fun logging(message: String, symbol: KSNode?) {
+ messager.println(message)
+ }
+
+ override fun info(message: String, symbol: KSNode?) {
+ messager.println(message)
+ }
+
+ override fun warn(message: String, symbol: KSNode?) {
+ messager.println(message)
+ }
+
+ override fun error(message: String, symbol: KSNode?) {
+ messager.println(message)
+ }
+
+ override fun exception(e: Throwable) {
+ messager.println(e.message)
+ }
+}
diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KSPCommandLineProcessor.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KSPCommandLineProcessor.kt
new file mode 100644
index 00000000..6b8676fd
--- /dev/null
+++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KSPCommandLineProcessor.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2022 Google LLC
+ * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.devtools.ksp.impl
+
+import com.google.devtools.ksp.KspOptions
+import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
+import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots
+import org.jetbrains.kotlin.cli.common.messages.MessageCollector
+import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoots
+import org.jetbrains.kotlin.config.CompilerConfiguration
+import java.io.File
+import java.nio.file.Files
+
+class KSPCommandLineProcessor(val args: Array<String>) {
+ val compilerConfiguration = CompilerConfiguration()
+ // TODO: support KSP options
+ val sources = args.toList()
+ lateinit var kspOptions: KspOptions
+
+ val ktFiles = sources
+ .map { File(it) }
+ .sortedBy { Files.isSymbolicLink(it.toPath()) } // Get non-symbolic paths first
+ .flatMap { root -> root.walk().filter { it.isFile && it.extension == "kt" }.toList() }
+ .sortedBy { Files.isSymbolicLink(it.toPath()) }
+ .distinctBy { it.canonicalPath }
+
+ val javaFiles = sources
+ .map { File(it) }
+ .sortedBy { Files.isSymbolicLink(it.toPath()) } // Get non-symbolic paths first
+ .flatMap { root -> root.walk().filter { it.isFile && it.extension == "java" }.toList() }
+ .sortedBy { Files.isSymbolicLink(it.toPath()) }
+ .distinctBy { it.canonicalPath }
+
+ init {
+ compilerConfiguration.addKotlinSourceRoots(ktFiles.map { it.absolutePath })
+ compilerConfiguration.addJavaSourceRoots(javaFiles)
+ compilerConfiguration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
+
+ val kspOptionsBuilder = KspOptions.Builder()
+ kspOptions = kspOptionsBuilder.build()
+ }
+}
diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt
index 2045102f..38f60eb2 100644
--- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt
+++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt
@@ -1,5 +1,12 @@
package com.google.devtools.ksp.impl
+import com.google.devtools.ksp.AnyChanges
+import com.google.devtools.ksp.KspOptions
+import com.google.devtools.ksp.impl.symbol.kotlin.KSFileImpl
+import com.google.devtools.ksp.processing.*
+import com.google.devtools.ksp.processing.impl.CodeGeneratorImpl
+import com.google.devtools.ksp.processing.impl.JvmPlatformInfoImpl
+import com.google.devtools.ksp.symbol.KSAnnotated
import com.intellij.mock.MockApplication
import com.intellij.mock.MockProject
import com.intellij.openapi.application.ApplicationManager
@@ -8,66 +15,112 @@ import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
import com.intellij.psi.PsiManager
-import org.jetbrains.kotlin.analysis.api.analyseWithReadAction
import org.jetbrains.kotlin.analysis.api.standalone.configureApplicationEnvironment
import org.jetbrains.kotlin.analysis.api.standalone.configureProjectEnvironment
-import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
-import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
-import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots
-import org.jetbrains.kotlin.cli.common.messages.MessageCollector
+import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
+import org.jetbrains.kotlin.cli.jvm.plugins.ServiceLoaderLite
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.psi.KtFile
-import java.io.File
-import java.nio.file.Files
+import java.net.URLClassLoader
-internal fun convertFilesToKtFiles(project: Project, files: List<File>): List<KtFile> {
- val fs = StandardFileSystems.local()
- val psiManager = PsiManager.getInstance(project)
- val ktFiles = mutableListOf<KtFile>()
- for (file in files) {
- val vFile = fs.findFileByPath(file.absolutePath) ?: continue
- val ktFile = psiManager.findFile(vFile) as? KtFile ?: continue
- ktFiles.add(ktFile)
- }
- return ktFiles
-}
+class KotlinSymbolProcessing(
+ val compilerConfiguration: CompilerConfiguration,
+ val options: KspOptions,
+ val logger: KSPLogger,
+ val testProcessor: SymbolProcessorProvider? = null
+) {
-fun main(args: Array<String>) {
- val kotlinSourceRoots = args.toList().map { File(it) }
- val compilerConfiguration = CompilerConfiguration()
- compilerConfiguration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
- val env = KotlinCoreEnvironment.createForProduction(
+ val providers: List<SymbolProcessorProvider>
+ val env: KotlinCoreEnvironment = KotlinCoreEnvironment.createForProduction(
Disposer.newDisposable(), compilerConfiguration,
EnvironmentConfigFiles.JVM_CONFIG_FILES
)
+ val project = env.project as MockProject
+ val kspCoreEnvironment = KSPCoreEnvironment(project)
- val application = ApplicationManager.getApplication() as MockApplication
- configureApplicationEnvironment(application)
+ var finished = false
+ val deferredSymbols = mutableMapOf<SymbolProcessor, List<KSAnnotated>>()
+ val ktFiles = convertFilesToKtFiles(project, compilerConfiguration.kotlinSourceRoots.map { it.path })
+ val codeGenerator: CodeGeneratorImpl
+ val processors: List<SymbolProcessor>
- val files = kotlinSourceRoots
- .sortedBy { Files.isSymbolicLink(it.toPath()) } // Get non-symbolic paths first
- .flatMap { root -> root.walk().filter { it.isFile && it.extension == "kt" }.toList() }
- .sortedBy { Files.isSymbolicLink(it.toPath()) } // This time is for .java files
- .distinctBy { it.canonicalPath }
- compilerConfiguration.addKotlinSourceRoots(files.map { it.absolutePath })
+ init {
+ configureProjectEnvironment(
+ project,
+ compilerConfiguration,
+ env::createPackagePartProvider,
+ env.projectEnvironment.environment.jarFileSystem as CoreJarFileSystem
+ )
- val project = env.project as MockProject
- val ktFiles = convertFilesToKtFiles(project, files)
- configureProjectEnvironment(
- project,
- compilerConfiguration,
- env::createPackagePartProvider,
- env.projectEnvironment.environment.jarFileSystem as CoreJarFileSystem
- )
- val kspCoreEnvironment = KSPCoreEnvironment(project)
+ val ksFiles = ktFiles.map { KSFileImpl(it) }
+ val anyChangesWildcard = AnyChanges(options.projectBaseDir)
+ codeGenerator = CodeGeneratorImpl(
+ options.classOutputDir,
+ options.javaOutputDir,
+ options.kotlinOutputDir,
+ options.resourceOutputDir,
+ options.projectBaseDir,
+ anyChangesWildcard,
+ ksFiles,
+ options.incremental
+ )
+ val application = ApplicationManager.getApplication() as MockApplication
+ configureApplicationEnvironment(application)
+ providers = if (testProcessor != null) {
+ listOf(testProcessor)
+ } else {
+ val processingClasspath = options.processingClasspath
+ val classLoader =
+ URLClassLoader(processingClasspath.map { it.toURI().toURL() }.toTypedArray(), javaClass.classLoader)
+
+ ServiceLoaderLite.loadImplementations(SymbolProcessorProvider::class.java, classLoader)
+ }
- for (ktFile in ktFiles) {
- analyseWithReadAction(ktFile) {
- val fileSymbol = ktFile.getFileSymbol()
- val members = fileSymbol.getFileScope().getAllSymbols()
- members.filterIsInstance<KtFunctionSymbol>()
+ processors = providers.mapNotNull { provider ->
+ var processor: SymbolProcessor? = null
+ processor = provider.create(
+ SymbolProcessorEnvironment(
+ options.processingOptions,
+ options.languageVersion,
+ codeGenerator,
+ logger,
+ options.apiVersion,
+ options.compilerVersion,
+ // TODO: fix platform info
+ listOf(JvmPlatformInfoImpl("JVM", "1.8"))
+ )
+ )
+ processor.also { deferredSymbols[it] = mutableListOf() }
}
}
+
+ fun execute() {
+ val resolver = ResolverAAImpl(ktFiles)
+ processors.forEach { it.process(resolver) }
+ }
+
+ private fun convertFilesToKtFiles(project: Project, filePaths: List<String>): List<KtFile> {
+ val fs = StandardFileSystems.local()
+ val psiManager = PsiManager.getInstance(project)
+ val ktFiles = mutableListOf<KtFile>()
+ for (path in filePaths) {
+ val vFile = fs.findFileByPath(path) ?: continue
+ val ktFile = psiManager.findFile(vFile) as? KtFile ?: continue
+ ktFiles.add(ktFile)
+ }
+ return ktFiles
+ }
+}
+
+fun main(args: Array<String>) {
+ val commandLineProcessor = KSPCommandLineProcessor(args)
+ val logger = CommandLineKSPLogger()
+ val kotlinSymbolProcessing = KotlinSymbolProcessing(
+ commandLineProcessor.compilerConfiguration,
+ commandLineProcessor.kspOptions,
+ logger
+ )
+ kotlinSymbolProcessing.execute()
}
diff --git a/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/impl/test/AbstractKSPAATest.kt b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/impl/test/AbstractKSPAATest.kt
index 0cf16047..889b2229 100644
--- a/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/impl/test/AbstractKSPAATest.kt
+++ b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/impl/test/AbstractKSPAATest.kt
@@ -18,8 +18,9 @@
package com.google.devtools.ksp.impl.test
import com.google.devtools.ksp.DualLookupTracker
-import com.google.devtools.ksp.impl.ResolverAAImpl
-import com.google.devtools.ksp.impl.convertFilesToKtFiles
+import com.google.devtools.ksp.KspOptions
+import com.google.devtools.ksp.impl.CommandLineKSPLogger
+import com.google.devtools.ksp.impl.KotlinSymbolProcessing
import com.google.devtools.ksp.processor.AbstractTestProcessor
import com.google.devtools.ksp.testutils.AbstractKSPTest
import com.intellij.mock.MockApplication
@@ -29,6 +30,7 @@ import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
import org.jetbrains.kotlin.analysis.api.standalone.configureApplicationEnvironment
import org.jetbrains.kotlin.analysis.api.standalone.configureProjectEnvironment
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot
+import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoot
@@ -40,6 +42,7 @@ import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
import org.jetbrains.kotlin.test.services.isKtFile
import org.jetbrains.kotlin.test.services.javaFiles
import java.io.File
+import java.nio.file.Files
abstract class AbstractKSPAATest : AbstractKSPTest(FrontendKinds.FIR) {
val TestModule.kotlinSrc
@@ -85,7 +88,12 @@ abstract class AbstractKSPAATest : AbstractKSPTest(FrontendKinds.FIR) {
val kotlinSourceFiles = mainModule.files.filter { it.isKtFile }.map {
File(mainModule.kotlinSrc, it.relativePath)
}
- val ktFiles = convertFilesToKtFiles(kotlinCoreEnvironment.project, kotlinSourceFiles)
+ val ktFiles = kotlinSourceFiles
+ .sortedBy { Files.isSymbolicLink(it.toPath()) } // Get non-symbolic paths first
+ .flatMap { root -> root.walk().filter { it.isFile && it.extension == "kt" }.toList() }
+ .sortedBy { Files.isSymbolicLink(it.toPath()) }
+ .distinctBy { it.canonicalPath }
+ compilerConfiguration.addKotlinSourceRoots(ktFiles.map { it.absolutePath })
configureProjectEnvironment(
kotlinCoreEnvironment.project as MockProject,
@@ -94,8 +102,22 @@ abstract class AbstractKSPAATest : AbstractKSPTest(FrontendKinds.FIR) {
kotlinCoreEnvironment.projectEnvironment.environment.jarFileSystem as CoreJarFileSystem
)
- val resolver = ResolverAAImpl(ktFiles)
- testProcessor.process(resolver)
+ val testRoot = mainModule.testRoot
+
+ val kspOptions = KspOptions.Builder().apply {
+ if (!mainModule.javaFiles.isEmpty()) {
+ javaSourceRoots.add(mainModule.javaDir)
+ }
+ classOutputDir = File(testRoot, "kspTest/classes/main")
+ javaOutputDir = File(testRoot, "kspTest/src/main/java")
+ kotlinOutputDir = File(testRoot, "kspTest/src/main/kotlin")
+ resourceOutputDir = File(testRoot, "kspTest/src/main/resources")
+ projectBaseDir = testRoot
+ cachesDir = File(testRoot, "kspTest/kspCaches")
+ kspOutputDir = File(testRoot, "kspTest")
+ }.build()
+ val ksp = KotlinSymbolProcessing(compilerConfiguration, kspOptions, CommandLineKSPLogger(), testProcessor)
+ ksp.execute()
return testProcessor.toResult()
}
diff --git a/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/impl/test/KotlinAnalysisAPITest.kt b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/impl/test/KotlinAnalysisAPITest.kt
deleted file mode 100644
index b149570b..00000000
--- a/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/impl/test/KotlinAnalysisAPITest.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.google.devtools.ksp.impl.test
-
-import com.google.devtools.ksp.impl.main
-import org.junit.jupiter.api.Test
-
-class KotlinAnalysisAPITest {
-
- @Test
- fun testHello() {
- main(arrayOf("testData/api"))
- }
-}