aboutsummaryrefslogtreecommitdiff
path: root/kotlin-analysis-api
diff options
context:
space:
mode:
authorJiaxiang Chen <jiaxiang@google.com>2021-10-26 13:13:58 -0700
committerJiaxiang Chen <roaringacw@gmail.com>2022-03-10 15:09:18 -0800
commit1eb4436dff88e21dda692a147c04fd83c2b128a7 (patch)
tree23c7a2ec677d5a6ad117c8f5785c2ca635cd99b9 /kotlin-analysis-api
parent6cac3e09c1761f4c952cc28d7a0bcfac6c6bb6cf (diff)
downloadksp-1eb4436dff88e21dda692a147c04fd83c2b128a7.tar.gz
* Implement skeleton service providers
* Add unit test for analysis API * Remove dependency on prebuilt binaries
Diffstat (limited to 'kotlin-analysis-api')
-rw-r--r--kotlin-analysis-api/build.gradle.kts76
-rw-r--r--kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/DeclarationProviderImpl.kt87
-rw-r--r--kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/FirSealedClassInheritorsProcessorFactoryImpl.kt19
-rw-r--r--kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/HackPomModel.kt21
-rw-r--r--kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinOutOfBlockModificationTrackerFactoryImpl.kt31
-rw-r--r--kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinPackageProviderImpl.kt23
-rw-r--r--kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt180
-rw-r--r--kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KtModuleScopeProviderImpl.kt12
-rw-r--r--kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ProjectStructureProviderImpl.kt41
-rw-r--r--kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/RegisterComponentService.java10
-rw-r--r--kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/impl/test/KotlinAnalysisAPITest.kt12
-rw-r--r--kotlin-analysis-api/testData/api/hello.kt12
12 files changed, 519 insertions, 5 deletions
diff --git a/kotlin-analysis-api/build.gradle.kts b/kotlin-analysis-api/build.gradle.kts
index 2c7dd330..356af147 100644
--- a/kotlin-analysis-api/build.gradle.kts
+++ b/kotlin-analysis-api/build.gradle.kts
@@ -1,8 +1,10 @@
description = "Kotlin Symbol Processing implementation using Kotlin Analysis API"
val intellijVersion: String by project
-val kotlinBaseVersion: String by project
val junitVersion: String by project
+val kotlinVersionFir = "1.6.20-dev-2497"
+val analysisAPIVersion = "1.6.20-dev-3387"
+val libsForTesting by configurations.creating
plugins {
kotlin("jvm")
@@ -25,16 +27,80 @@ fun ModuleDependency.includeJars(vararg names: String) {
}
dependencies {
- implementation(kotlin("stdlib", kotlinBaseVersion))
- implementation("org.jetbrains.kotlin:high-level-api-for-ide:1.6.255")
- implementation("org.jetbrains.kotlin:kotlin-compiler:$kotlinBaseVersion")
+ implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm:0.3.1")
+ implementation(kotlin("stdlib", kotlinVersionFir))
+ implementation("org.jetbrains.kotlin:kotlin-compiler:$kotlinVersionFir")
+
+ implementation("org.jetbrains.kotlin:high-level-api-fir-for-ide:$analysisAPIVersion") {
+ isTransitive = false
+ }
+ implementation("org.jetbrains.kotlin:high-level-api-for-ide:$analysisAPIVersion") {
+ isTransitive = false
+ }
+ implementation("org.jetbrains.kotlin:low-level-api-fir-for-ide:$analysisAPIVersion") {
+ isTransitive = false
+ }
+ implementation("org.jetbrains.kotlin:analysis-api-providers-for-ide:$analysisAPIVersion") {
+ isTransitive = false
+ }
+ implementation("org.jetbrains.kotlin:analysis-project-structure-for-ide:$analysisAPIVersion") {
+ isTransitive = false
+ }
implementation(project(":api"))
+
+ libsForTesting(kotlin("stdlib", kotlinVersionFir))
+ libsForTesting(kotlin("test", kotlinVersionFir))
+ libsForTesting(kotlin("script-runtime", kotlinVersionFir))
+}
+
+tasks.register<Copy>("CopyLibsForTesting") {
+ from(configurations.get("libsForTesting"))
+ into("dist/kotlinc/lib")
+ val escaped = Regex.escape(kotlinVersionFir)
+ rename("(.+)-$escaped\\.jar", "$1.jar")
+}
+
+sourceSets.main {
+ java.srcDirs("src/main/kotlin")
}
+
+fun Project.javaPluginConvention(): JavaPluginConvention = the()
+val JavaPluginConvention.testSourceSet: SourceSet
+ get() = sourceSets.getByName("test")
+val Project.testSourceSet: SourceSet
+ get() = javaPluginConvention().testSourceSet
+
+tasks.test {
+ dependsOn("CopyLibsForTesting")
+ maxHeapSize = "2g"
+
+ systemProperty("idea.is.unit.test", "true")
+ systemProperty("idea.home.path", buildDir)
+ systemProperty("java.awt.headless", "true")
+ environment("NO_FS_ROOTS_ACCESS_CHECK", "true")
+ environment("PROJECT_CLASSES_DIRS", testSourceSet.output.classesDirs.asPath)
+ environment("PROJECT_BUILD_DIR", buildDir)
+ testLogging {
+ events("passed", "skipped", "failed")
+ }
+
+ var tempTestDir: File? = null
+ doFirst {
+ tempTestDir = createTempDir()
+ systemProperty("java.io.tmpdir", tempTestDir.toString())
+ }
+
+ doLast {
+ tempTestDir?.let { delete(it) }
+ }
+}
+
repositories {
flatDir {
dirs("${project.rootDir}/third_party/prebuilt/repo/")
}
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap/")
- maven("https://www.jetbrains.com/intellij-repository/snapshots")
+ maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-ide-plugin-dependencies")
+ maven("https://www.jetbrains.com/intellij-repository/releases")
}
diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/DeclarationProviderImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/DeclarationProviderImpl.kt
new file mode 100644
index 00000000..e94c03fc
--- /dev/null
+++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/DeclarationProviderImpl.kt
@@ -0,0 +1,87 @@
+package com.google.devtools.ksp.impl
+
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProvider
+import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
+import org.jetbrains.kotlin.name.CallableId
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
+
+class DeclarationProviderImpl(
+ val searchScope: GlobalSearchScope,
+ ktFiles: Collection<KtFile>
+) : KotlinDeclarationProvider() {
+
+ private val filesInScope = ktFiles.filter { searchScope.contains(it.virtualFile) }
+
+ private fun filesByPackage(packageFqName: FqName) =
+ filesInScope.asSequence()
+ .filter { it.packageFqName == packageFqName }
+
+ override fun getClassesByClassId(classId: ClassId): Collection<KtClassOrObject> =
+ filesByPackage(classId.packageFqName).flatMap { file ->
+ file.collectDescendantsOfType<KtClassOrObject> { ktClass ->
+ ktClass.getClassId() == classId
+ }
+ }.toList()
+
+ override fun getTypeAliasesByClassId(classId: ClassId): Collection<KtTypeAlias> =
+ filesByPackage(classId.packageFqName).flatMap { file ->
+ file.collectDescendantsOfType<KtTypeAlias> { typeAlias ->
+ typeAlias.getClassId() == classId
+ }
+ }.toList()
+
+ override fun getTypeAliasNamesInPackage(packageFqName: FqName): Set<Name> =
+ filesByPackage(packageFqName)
+ .flatMap { it.declarations }
+ .filterIsInstance<KtTypeAlias>()
+ .mapNotNullTo(mutableSetOf()) { it.nameAsName }
+
+ override fun getPropertyNamesInPackage(packageFqName: FqName): Set<Name> =
+ filesByPackage(packageFqName)
+ .flatMap { it.declarations }
+ .filterIsInstance<KtProperty>()
+ .mapNotNullTo(mutableSetOf()) { it.nameAsName }
+
+ override fun getFunctionsNamesInPackage(packageFqName: FqName): Set<Name> =
+ filesByPackage(packageFqName)
+ .flatMap { it.declarations }
+ .filterIsInstance<KtNamedFunction>()
+ .mapNotNullTo(mutableSetOf()) { it.nameAsName }
+
+ override fun getFacadeFilesInPackage(packageFqName: FqName): Collection<KtFile> =
+ filesByPackage(packageFqName)
+ .filter { file -> file.hasTopLevelCallables() }
+ .toSet()
+
+ override fun findFilesForFacade(facadeFqName: FqName): Collection<KtFile> {
+ if (facadeFqName.shortNameOrSpecial().isSpecial) return emptyList()
+ return getFacadeFilesInPackage(facadeFqName.parent())
+ .filter { it.javaFileFacadeFqName == facadeFqName }
+ }
+
+ override fun getTopLevelProperties(callableId: CallableId): Collection<KtProperty> =
+ filesByPackage(callableId.packageName)
+ .flatMap { it.declarations }
+ .filterIsInstance<KtProperty>()
+ .filter { it.nameAsName == callableId.callableName }
+ .toList()
+
+ override fun getTopLevelFunctions(callableId: CallableId): Collection<KtNamedFunction> =
+ filesByPackage(callableId.packageName)
+ .flatMap { it.declarations }
+ .filterIsInstance<KtNamedFunction>()
+ .filter { it.nameAsName == callableId.callableName }
+ .toList()
+
+
+ override fun getClassNamesInPackage(packageFqName: FqName): Set<Name> =
+ filesByPackage(packageFqName)
+ .flatMap { it.declarations }
+ .filterIsInstance<KtClassOrObject>()
+ .mapNotNullTo(mutableSetOf()) { it.nameAsName }
+}
diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/FirSealedClassInheritorsProcessorFactoryImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/FirSealedClassInheritorsProcessorFactoryImpl.kt
new file mode 100644
index 00000000..fa5dd3ea
--- /dev/null
+++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/FirSealedClassInheritorsProcessorFactoryImpl.kt
@@ -0,0 +1,19 @@
+package com.google.devtools.ksp.impl
+
+import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory
+import org.jetbrains.kotlin.fir.declarations.FirRegularClass
+import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider
+import org.jetbrains.kotlin.name.ClassId
+
+class FirSealedClassInheritorsProcessorFactoryImpl: FirSealedClassInheritorsProcessorFactory() {
+ override fun createSealedClassInheritorsProvider(): SealedClassInheritorsProvider {
+ return SealedClassInheritorProviderImpl()
+ }
+}
+
+class SealedClassInheritorProviderImpl: SealedClassInheritorsProvider() {
+ override fun getSealedClassInheritors(firClass: FirRegularClass): List<ClassId> {
+ return emptyList()
+ }
+
+}
diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/HackPomModel.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/HackPomModel.kt
new file mode 100644
index 00000000..36a006a9
--- /dev/null
+++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/HackPomModel.kt
@@ -0,0 +1,21 @@
+package com.google.devtools.ksp.impl
+
+import com.intellij.openapi.project.Project
+import com.intellij.pom.PomModelAspect
+import com.intellij.pom.core.impl.PomModelImpl
+import com.intellij.pom.event.PomModelEvent
+import com.intellij.psi.impl.source.PostprocessReformattingAspect
+
+class HackPomModel(project: Project) : PomModelImpl(project) {
+
+ var myAspect = PostprocessReformattingAspect(project)
+
+ override fun <T : PomModelAspect> getModelAspect(aClass: Class<T>): T {
+ return if (myAspect.javaClass == aClass) myAspect as T else super.getModelAspect<T>(aClass)
+ }
+
+ override fun updateDependentAspects(event: PomModelEvent?) {
+ super.updateDependentAspects(event)
+ myAspect.update(event!!)
+ }
+}
diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinOutOfBlockModificationTrackerFactoryImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinOutOfBlockModificationTrackerFactoryImpl.kt
new file mode 100644
index 00000000..c547214d
--- /dev/null
+++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinOutOfBlockModificationTrackerFactoryImpl.kt
@@ -0,0 +1,31 @@
+package com.google.devtools.ksp.impl
+
+import com.intellij.openapi.util.ModificationTracker
+import com.intellij.openapi.util.SimpleModificationTracker
+import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
+import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory
+import org.jetbrains.kotlin.analyzer.ModuleSourceInfoBase
+
+class KotlinOutOfBlockModificationTrackerFactoryImpl : KotlinModificationTrackerFactory() {
+ private val projectWide = SimpleModificationTracker()
+ private val library = SimpleModificationTracker()
+ private val forModule = mutableMapOf<KtSourceModule, SimpleModificationTracker>()
+
+ override fun createProjectWideOutOfBlockModificationTracker(): ModificationTracker {
+ return projectWide
+ }
+
+ override fun createLibrariesModificationTracker(): ModificationTracker {
+ return library
+ }
+
+ override fun createModuleWithoutDependenciesOutOfBlockModificationTracker(module: KtSourceModule): ModificationTracker {
+ return forModule.getOrPut(module) { SimpleModificationTracker() }
+ }
+
+ override fun incrementModificationsCount() {
+ projectWide.incModificationCount()
+ library.incModificationCount()
+ forModule.values.forEach { it.incModificationCount() }
+ }
+}
diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinPackageProviderImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinPackageProviderImpl.kt
new file mode 100644
index 00000000..95a0a931
--- /dev/null
+++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinPackageProviderImpl.kt
@@ -0,0 +1,23 @@
+package com.google.devtools.ksp.impl
+
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.kotlin.analysis.providers.KotlinPackageProvider
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.psi.KtFile
+
+class KotlinPackageProviderImpl(
+ scope: GlobalSearchScope,
+ files: Collection<KtFile>
+) : KotlinPackageProvider() {
+ private val filesInScope = files.filter { scope.contains(it.virtualFile) }
+
+
+ override fun doKotlinPackageExists(packageFqName: FqName): Boolean {
+ return filesInScope.any { it.packageFqName == packageFqName }
+ }
+
+ override fun getKotlinSubPackageFqNames(packageFqName: FqName): Set<Name> {
+ TODO("Not yet implemented")
+ }
+}
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 2987cb5e..5e8bfc85 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,4 +1,184 @@
package com.google.devtools.ksp.impl
+import com.intellij.core.CoreApplicationEnvironment
+import com.intellij.formatting.Formatter
+import com.intellij.formatting.FormatterImpl
+import com.intellij.mock.MockApplication
+import com.intellij.mock.MockProject
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.application.AsyncExecutionService
+import com.intellij.openapi.application.impl.AsyncExecutionServiceImpl
+import com.intellij.openapi.editor.impl.DocumentWriteAccessGuard
+import com.intellij.openapi.extensions.Extensions
+import com.intellij.openapi.fileEditor.impl.FileEditorPsiTreeChangeListener
+import com.intellij.openapi.util.Disposer
+import com.intellij.openapi.util.io.FileUtil
+import com.intellij.openapi.util.text.StringUtilRt
+import com.intellij.openapi.vfs.CharsetToolkit
+import com.intellij.pom.PomModel
+import com.intellij.pom.tree.TreeAspect
+import com.intellij.psi.PsiTreeChangeListener
+import com.intellij.psi.codeStyle.CodeStyleManager
+import com.intellij.psi.impl.DocumentCommitProcessor
+import com.intellij.psi.impl.DocumentCommitThread
+import com.intellij.psi.impl.PsiFileFactoryImpl
+import com.intellij.psi.impl.source.codeStyle.CodeStyleManagerImpl
+import com.intellij.psi.search.GlobalSearchScope
+import com.intellij.testFramework.LightVirtualFile
+import org.jetbrains.kotlin.analysis.api.InvalidWayOfUsingAnalysisSession
+import org.jetbrains.kotlin.analysis.api.KtAnalysisSessionProvider
+import org.jetbrains.kotlin.analysis.api.analyseWithReadAction
+import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSessionProvider
+import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory
+import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.PackagePartProviderFactory
+import org.jetbrains.kotlin.analysis.project.structure.KtModuleScopeProvider
+import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
+import org.jetbrains.kotlin.analysis.providers.*
+import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
+import org.jetbrains.kotlin.cli.common.messages.MessageCollector
+import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
+import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
+import org.jetbrains.kotlin.config.CompilerConfiguration
+import org.jetbrains.kotlin.idea.KotlinLanguage
+import org.jetbrains.kotlin.idea.references.*
+import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.serialization.deserialization.ClassData
+import java.io.File
+
+@OptIn(InvalidWayOfUsingAnalysisSession::class)
+fun registerComponents(project: MockProject, environment: KotlinCoreEnvironment, ktFiles: List<KtFile>) {
+
+ project.picoContainer.registerComponentInstance(
+ KtAnalysisSessionProvider::class.qualifiedName,
+ KtFirAnalysisSessionProvider(project)
+ )
+
+ project.picoContainer.registerComponentInstance(
+ ProjectStructureProvider::class.qualifiedName,
+ ProjectStructureProviderImpl()
+ )
+
+ project.picoContainer.registerComponentInstance(
+ KotlinModificationTrackerFactory::class.qualifiedName,
+ KotlinOutOfBlockModificationTrackerFactoryImpl()
+ )
+
+ RegisterComponentService.registerFirIdeResolveStateService(project)
+
+ project.picoContainer.registerComponentInstance(
+ KotlinDeclarationProviderFactory::class.qualifiedName,
+ object : KotlinDeclarationProviderFactory() {
+ override fun createDeclarationProvider(searchScope: GlobalSearchScope): KotlinDeclarationProvider {
+ return DeclarationProviderImpl(searchScope, ktFiles.filter { searchScope.contains(it.virtualFile) })
+ }
+ }
+ )
+
+ project.picoContainer.registerComponentInstance(
+ KotlinPackageProviderFactory::class.qualifiedName,
+ object : KotlinPackageProviderFactory() {
+ override fun createPackageProvider(searchScope: GlobalSearchScope): KotlinPackageProvider {
+ return KotlinPackageProviderImpl(searchScope, ktFiles.filter { searchScope.contains(it.virtualFile) })
+ }
+ }
+ )
+
+ project.picoContainer.registerComponentInstance(
+ FirSealedClassInheritorsProcessorFactory::class.qualifiedName,
+ FirSealedClassInheritorsProcessorFactoryImpl()
+ )
+ project.picoContainer.registerComponentInstance(
+ PackagePartProviderFactory::class.qualifiedName,
+ object : PackagePartProviderFactory() {
+ override fun createPackagePartProviderForLibrary(scope: GlobalSearchScope): PackagePartProvider {
+ return object : PackagePartProvider {
+ override fun findPackageParts(packageFqName: String): List<String> {
+ return emptyList()
+ }
+
+ override fun getAllOptionalAnnotationClasses(): List<ClassData> {
+ return emptyList()
+ }
+
+ override fun getAnnotationsOnBinaryModule(moduleName: String): List<ClassId> {
+ return emptyList()
+ }
+ }
+ }
+ }
+ )
+
+ val application = ApplicationManager.getApplication() as MockApplication
+ KotlinCoreEnvironment.underApplicationLock {
+ application.registerService(
+ KotlinReferenceProviderContributor::class.java, KotlinFirReferenceContributor::class.java
+ )
+ application.registerService(DocumentCommitProcessor::class.java, DocumentCommitThread::class.java)
+ application.registerService(AsyncExecutionService::class.java, AsyncExecutionServiceImpl::class.java)
+ application.registerService(Formatter::class.java, FormatterImpl::class.java)
+ }
+
+ project.picoContainer.registerComponentInstance(
+ CodeStyleManager::class.qualifiedName,
+ CodeStyleManagerImpl(project)
+ )
+ project.picoContainer.registerComponentInstance(
+ TreeAspect::class.qualifiedName,
+ TreeAspect()
+ )
+ project.picoContainer.registerComponentInstance(
+ PomModel::class.qualifiedName,
+ HackPomModel(project)
+ )
+
+ project.picoContainer.registerComponentInstance(
+ KtModuleScopeProvider::class.qualifiedName,
+ KtModuleScopeProviderImpl()
+ )
+
+ CoreApplicationEnvironment.registerExtensionPoint(
+ Extensions.getRootArea(),
+ DocumentWriteAccessGuard.EP_NAME,
+ DocumentWriteAccessGuard::class.java
+ )
+ CoreApplicationEnvironment.registerExtensionPoint(
+ project.extensionArea,
+ PsiTreeChangeListener.EP,
+ FileEditorPsiTreeChangeListener::class.java
+ )
+}
+fun findSomeReference(ktFile: KtFile): KtReference? {
+ for (i in 1..300) {
+ val reference = ktFile.findReferenceAt(i)
+ if (reference != null && reference is KtReference)
+ return reference
+ }
+
+ return null
+}
+
fun main() {
+ val compilerConfiguration = CompilerConfiguration()
+ compilerConfiguration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
+ val env = KotlinCoreEnvironment.createForProduction(
+ Disposer.newDisposable(), compilerConfiguration,
+ EnvironmentConfigFiles.JVM_CONFIG_FILES
+ )
+
+ val project = env.project as MockProject
+ val factory = PsiFileFactoryImpl(project)
+
+ val file = File("testData/api/hello.kt")
+ val text = FileUtil.loadFile(file, CharsetToolkit.UTF8, true).trim { it <= ' ' }
+
+ val virtualFile = LightVirtualFile("a.kt", KotlinLanguage.INSTANCE, StringUtilRt.convertLineSeparators(text))
+ val ktFile = factory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile
+ registerComponents(project, env, listOf(ktFile))
+ analyseWithReadAction(ktFile) {
+ val mainRef = ktFile.mainReference
+ val reference = findSomeReference(ktFile)
+ reference?.resolveToSymbol()
+ }
}
diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KtModuleScopeProviderImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KtModuleScopeProviderImpl.kt
new file mode 100644
index 00000000..6f0b1136
--- /dev/null
+++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KtModuleScopeProviderImpl.kt
@@ -0,0 +1,12 @@
+package com.google.devtools.ksp.impl
+
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.kotlin.analysis.project.structure.KtModuleScopeProvider
+import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
+
+class KtModuleScopeProviderImpl: KtModuleScopeProvider() {
+ override fun getModuleLibrariesScope(sourceModule: KtSourceModule): GlobalSearchScope {
+ return GlobalSearchScope.filesScope(sourceModule.project, emptyList())
+ }
+
+}
diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ProjectStructureProviderImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ProjectStructureProviderImpl.kt
new file mode 100644
index 00000000..a9e072ae
--- /dev/null
+++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ProjectStructureProviderImpl.kt
@@ -0,0 +1,41 @@
+package com.google.devtools.ksp.impl
+
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiElement
+import com.intellij.psi.search.GlobalSearchScope
+import org.jetbrains.kotlin.analysis.project.structure.KtModule
+import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
+import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
+import org.jetbrains.kotlin.config.*
+import org.jetbrains.kotlin.platform.TargetPlatform
+import org.jetbrains.kotlin.platform.jvm.JdkPlatform
+import org.jetbrains.kotlin.platform.jvm.JvmPlatform
+import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
+import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
+import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
+
+class ProjectStructureProviderImpl : ProjectStructureProvider() {
+ override fun getKtModuleForKtElement(element: PsiElement): KtModule {
+ return object: KtSourceModule {
+ override val analyzerServices: PlatformDependentAnalyzerServices
+ get() = JvmPlatformAnalyzerServices
+ override val contentScope: GlobalSearchScope
+ get() = GlobalSearchScope.EMPTY_SCOPE
+ override val directFriendDependencies: List<KtModule>
+ get() = emptyList()
+ override val directRefinementDependencies: List<KtModule>
+ get() = emptyList()
+ override val directRegularDependencies: List<KtModule>
+ get() = emptyList()
+ override val languageVersionSettings: LanguageVersionSettings
+ get() = LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST)
+ override val moduleName: String
+ get() = "main"
+ override val platform: TargetPlatform
+ get() = TargetPlatform(setOf(JdkPlatform(JvmTarget.DEFAULT)))
+ override val project: Project
+ get() = element.project
+
+ }
+ }
+}
diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/RegisterComponentService.java b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/RegisterComponentService.java
new file mode 100644
index 00000000..54bfcbcb
--- /dev/null
+++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/RegisterComponentService.java
@@ -0,0 +1,10 @@
+package com.google.devtools.ksp.impl;
+
+import com.intellij.mock.MockProject;
+import org.jetbrains.kotlin.analysis.low.level.api.fir.FirIdeResolveStateService;
+
+public class RegisterComponentService {
+ public static void registerFirIdeResolveStateService(MockProject project) {
+ project.getPicoContainer().registerComponentInstance(FirIdeResolveStateService.class.getName(), new FirIdeResolveStateService(project));
+ }
+}
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
new file mode 100644
index 00000000..de4d8dfc
--- /dev/null
+++ b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/impl/test/KotlinAnalysisAPITest.kt
@@ -0,0 +1,12 @@
+package com.google.devtools.ksp.impl.test
+
+import com.google.devtools.ksp.impl.main
+import org.junit.Test
+
+class KotlinAnalysisAPITest {
+
+ @Test
+ fun testHello() {
+ main()
+ }
+}
diff --git a/kotlin-analysis-api/testData/api/hello.kt b/kotlin-analysis-api/testData/api/hello.kt
new file mode 100644
index 00000000..6a33984c
--- /dev/null
+++ b/kotlin-analysis-api/testData/api/hello.kt
@@ -0,0 +1,12 @@
+package test
+annotation class Anno
+
+@Anno
+class Foo() {
+ val k = "123"
+ var a : String = "123"
+ val aaa : (Int) -> Int = { a -> 1 }
+ fun bar(): Int {
+ return 3
+ }
+}