Analysis LC: introduce Symbol LC tests

This commit is contained in:
Ilya Kirillov
2021-12-22 13:45:53 +03:00
parent abf7a4c5ac
commit 40fdb26569
34 changed files with 817 additions and 56 deletions
+13 -1
View File
@@ -14,9 +14,21 @@ dependencies {
implementation(project(":analysis:project-structure"))
implementation(project(":analysis:decompiled:light-classes-for-decompiled"))
implementation(intellijCore())
testImplementation(project(":analysis:decompiled:decompiler-to-file-stubs"))
testImplementation(projectTests(":analysis:analysis-api-impl-base"))
testImplementation(projectTests(":analysis:analysis-api-fir"))
}
sourceSets {
"main" { projectDefault() }
"test" { none() }
"test" { projectDefault() }
}
projectTest(jUnitMode = JUnitMode.JUnit5) {
dependsOn(":dist")
workingDir = rootDir
useJUnitPlatform()
}
testsJar()
@@ -0,0 +1,13 @@
package org.jetbrains.annotations;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
public @interface NotNull {
String value() default "";
Class<? extends Exception> exception() default Exception.class;
}
@@ -0,0 +1,10 @@
package org.jetbrains.annotations;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
public @interface Nullable {
@NonNls String value() default "";
}
@@ -0,0 +1,42 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.base
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.renderClass
import org.jetbrains.kotlin.light.classes.symbol.base.service.withExtendedTypeRenderer
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.model.TestModule
import java.nio.file.Path
abstract class AbstractSymbolLightClassesFacadeTest(
configurator: FrontendApiTestConfiguratorService,
override val currentExtension: String,
override val stopIfCompilationErrorDirectivePresent: Boolean,
) : AbstractSymbolLightClassesTestBase(configurator) {
override fun getRenderResult(ktFile: KtFile, testDataFile: Path, module: TestModule, project: Project): String {
val lightClasses = getFacades(project)
return withExtendedTypeRenderer((testDataFile)) {
lightClasses.joinToString("\n\n") { it.renderClass() }
}
}
private fun getFacades(
project: Project
): List<KtLightClass> {
val kotlinAsJavaSupport = KotlinAsJavaSupport.getInstance(project)
val scope = GlobalSearchScope.allScope(project)
val facades = kotlinAsJavaSupport.getFacadeNames(FqName.ROOT, scope).sorted()
return facades
.flatMap { facadeName -> kotlinAsJavaSupport.getFacadeClasses(FqName(facadeName), scope) }
.filterIsInstance<KtLightClass>()
}
}
@@ -0,0 +1,41 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.base
import com.intellij.openapi.project.Project
import com.intellij.psi.SyntaxTraverser
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.renderClass
import org.jetbrains.kotlin.light.classes.symbol.base.service.withExtendedTypeRenderer
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.model.TestModule
import java.nio.file.Path
abstract class AbstractSymbolLightClassesLoadingTest(
configurator: FrontendApiTestConfiguratorService,
override val currentExtension: String,
override val stopIfCompilationErrorDirectivePresent: Boolean,
) : AbstractSymbolLightClassesTestBase(configurator) {
override fun getRenderResult(ktFile: KtFile, testDataFile: Path, module: TestModule, project: Project): String {
val lightClasses = getLightClassesFromFile(ktFile, project)
return withExtendedTypeRenderer(testDataFile) {
lightClasses.joinToString("\n\n") { it.renderClass() }
}
}
private fun getLightClassesFromFile(
ktFile: KtFile,
project: Project
): List<KtLightClass> {
val ktClasses = SyntaxTraverser.psiTraverser(ktFile).filter(KtClassOrObject::class.java).toList()
val kotlinAsJavaSupport = KotlinAsJavaSupport.getInstance(project)
return ktClasses.mapNotNull(kotlinAsJavaSupport::getLightClass)
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.base
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiClass
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.asJava.LightClassTestCommon
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.model.TestModule
import java.nio.file.Path
abstract class AbstractSymbolLightClassesTest(
configurator: FrontendApiTestConfiguratorService,
override val currentExtension: String,
override val stopIfCompilationErrorDirectivePresent: Boolean,
) : AbstractSymbolLightClassesTestBase(configurator) {
override fun getRenderResult(ktFile: KtFile, testDataFile: Path, module: TestModule, project: Project): String {
return LightClassTestCommon.getActualLightClassText(
testDataFile.toFile(),
{ fqName -> findLightClass(fqName, project) },
LightClassTestCommon::removeEmptyDefaultImpls
)
}
private fun findLightClass(fqname: String, project: Project): PsiClass? {
return JavaElementFinder
.getInstance(project)
.findClass(fqname, GlobalSearchScope.allScope(project))
}
}
@@ -0,0 +1,147 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.base
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiClass
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.base.test.test.framework.AbstractHLApiSingleModuleTest
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.light.classes.symbol.base.service.NullabilityAnnotationSourceProvider
import org.jetbrains.kotlin.light.classes.symbol.decompiled.service.CompilerExecutor
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.directives.model.DirectiveApplicability
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestModuleStructure
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.assertions
import org.jetbrains.kotlin.test.utils.FirIdenticalCheckerHelper
import java.io.File
import java.nio.file.Path
import kotlin.io.path.exists
import kotlin.io.path.nameWithoutExtension
abstract class AbstractSymbolLightClassesTestBase(
configurator: FrontendApiTestConfiguratorService
) : AbstractHLApiSingleModuleTest(configurator) {
override val enableTestInDependedMode: Boolean get() = false
override fun configureTest(builder: TestConfigurationBuilder) {
super.configureTest(builder)
with(builder) {
useDirectives(Directives, CompilerExecutor.Directives)
useAdditionalSourceProviders(::NullabilityAnnotationSourceProvider)
}
}
override fun handleInitializationError(exception: Throwable, moduleStructure: TestModuleStructure): InitializationErrorAction {
return if (Directives.IGNORE_FIR in moduleStructure.allDirectives) InitializationErrorAction.IGNORE
else InitializationErrorAction.THROW
}
override fun doTestByFileStructure(ktFiles: List<KtFile>, module: TestModule, testServices: TestServices) {
if (stopIfCompilationErrorDirectivePresent && CompilerExecutor.Directives.COMPILATION_ERRORS in module.directives) {
return
}
val testDataFile = module.files.first { it.name.endsWith(".kt") }.originalFile.toPath()
val project = ktFiles.first().project
ignoreExceptionIfIgnoreFirPresent(module) {
val actual = getRenderResult(ktFiles.first(), testDataFile, module, project)
compareResults(testServices, actual)
removeIgnoreFir(module)
removeDuplicatedFirJava(testServices)
}
}
protected abstract fun getRenderResult(
ktFile: KtFile,
testDataFile: Path,
module: TestModule,
project: Project
): String
private inline fun ignoreExceptionIfIgnoreFirPresent(module: TestModule, action: () -> Unit) {
try {
action()
} catch (e: Throwable) {
if (Directives.IGNORE_FIR in module.directives) {
return
}
throw e
}
}
private fun compareResults(
testServices: TestServices,
actual: String,
) {
if (currentResultPath().exists()) {
testServices.assertions.assertEqualsToFile(currentResultPath(), actual)
} else {
testServices.assertions.assertEqualsToFile(javaPath(), actual)
}
}
private fun removeIgnoreFir(module: TestModule) {
if (Directives.IGNORE_FIR in module.directives) {
error("Test is passing. Please, remove `// ${Directives.IGNORE_FIR.name}` directive")
}
}
private fun findLightClass(fqname: String, project: Project): PsiClass? {
return JavaElementFinder
.getInstance(project)
.findClass(fqname, GlobalSearchScope.allScope(project))
}
private fun removeDuplicatedFirJava(testServices: TestServices) {
val java = javaPath()
val firJava = currentResultPath()
if (!firJava.exists()) return
val identicalCheckerHelper = IdenticalCheckerHelper(testServices)
if (identicalCheckerHelper.contentsAreEquals(java.toFile(), firJava.toFile(), trimLines = true)) {
identicalCheckerHelper.deleteFirFile(java.toFile())
}
}
private inner class IdenticalCheckerHelper(testServices: TestServices) : FirIdenticalCheckerHelper(testServices) {
override fun getClassicFileToCompare(testDataFile: File): File {
return if (testDataFile.name.endsWith(EXTENSIONS.FIR_JAVA))
testDataFile.resolveSibling(testDataFile.name.removeSuffix(currentExtension) + EXTENSIONS.JAVA)
else testDataFile
}
override fun getFirFileToCompare(testDataFile: File): File {
return if (testDataFile.name.endsWith(EXTENSIONS.FIR_JAVA))
testDataFile
else testDataFile.resolveSibling(testDataFile.name.removeSuffix(EXTENSIONS.JAVA) + currentExtension)
}
}
private fun javaPath() = testDataPath.resolveSibling(testDataPath.nameWithoutExtension + EXTENSIONS.JAVA)
private fun currentResultPath() = testDataPath.resolveSibling(testDataPath.nameWithoutExtension + currentExtension)
protected abstract val currentExtension: String
protected abstract val stopIfCompilationErrorDirectivePresent: Boolean
object EXTENSIONS {
const val JAVA = ".java"
const val FIR_JAVA = ".fir.java"
const val LIB_JAVA = ".lib.java"
}
private object Directives : SimpleDirectivesContainer() {
val IGNORE_FIR by directive(
description = "Ignore the test for Symbol FIR-based implementation of LC",
applicability = DirectiveApplicability.Global
)
}
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.base.service
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
import org.jetbrains.kotlin.test.model.TestFile
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.AdditionalSourceProvider
import org.jetbrains.kotlin.test.services.TestServices
import java.io.File
class NullabilityAnnotationSourceProvider(testServices: TestServices) : AdditionalSourceProvider(testServices) {
override fun produceAdditionalFiles(globalDirectives: RegisteredDirectives, module: TestModule): List<TestFile> {
return listOf(
"analysis/symbol-light-classes/testdata/additionalFiles/NotNull.java",
"analysis/symbol-light-classes/testdata/additionalFiles/Nullable.java",
).map { path ->
File(path).toTestFile(relativePath = "org/jetbrains/annotations")
}
}
}
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.base.service
import org.jetbrains.kotlin.asJava.PsiClassRenderer
import java.nio.file.Path
internal inline fun <R> withExtendedTypeRenderer(testDataFile: Path, action: () -> R): R {
val extendedTypeRendererOld = PsiClassRenderer.extendedTypeRenderer
return try {
PsiClassRenderer.extendedTypeRenderer = testDataFile.toString().endsWith("typeAnnotations.kt")
action()
} finally {
PsiClassRenderer.extendedTypeRenderer = extendedTypeRendererOld
}
}
@@ -0,0 +1,18 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.decompiled
import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesFacadeTest
import org.jetbrains.kotlin.light.classes.symbol.decompiled.service.SymbolLightClassesForLibraryFrontendApiTestConfiguratorService
import org.junit.jupiter.api.parallel.Execution
import org.junit.jupiter.api.parallel.ExecutionMode
abstract class AbstractSymbolLightClassesFacadeForLibraryTest :
AbstractSymbolLightClassesFacadeTest(
SymbolLightClassesForLibraryFrontendApiTestConfiguratorService,
EXTENSIONS.LIB_JAVA,
stopIfCompilationErrorDirectivePresent = true
)
@@ -0,0 +1,18 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.decompiled
import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesTest
import org.jetbrains.kotlin.light.classes.symbol.decompiled.service.SymbolLightClassesForLibraryFrontendApiTestConfiguratorService
import org.junit.jupiter.api.parallel.Execution
import org.junit.jupiter.api.parallel.ExecutionMode
abstract class AbstractSymbolLightClassesForLibraryTest :
AbstractSymbolLightClassesTest(
SymbolLightClassesForLibraryFrontendApiTestConfiguratorService,
EXTENSIONS.LIB_JAVA,
stopIfCompilationErrorDirectivePresent = true
)
@@ -0,0 +1,18 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.decompiled
import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesLoadingTest
import org.jetbrains.kotlin.light.classes.symbol.decompiled.service.SymbolLightClassesForLibraryFrontendApiTestConfiguratorService
import org.junit.jupiter.api.parallel.Execution
import org.junit.jupiter.api.parallel.ExecutionMode
abstract class AbstractSymbolLightClassesLoadingForLibraryTest :
AbstractSymbolLightClassesLoadingTest(
SymbolLightClassesForLibraryFrontendApiTestConfiguratorService,
EXTENSIONS.LIB_JAVA,
stopIfCompilationErrorDirectivePresent = true
)
@@ -0,0 +1,59 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.decompiled.service
import org.jetbrains.kotlin.test.MockLibraryUtil
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives
import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
import org.jetbrains.kotlin.test.model.TestModule
import java.nio.file.Path
import kotlin.io.path.absolutePathString
import kotlin.io.path.div
import kotlin.io.path.exists
import kotlin.io.path.notExists
object CompilerExecutor {
fun compileLibrary(sourcesPath: Path, options: List<String>, compilationErrorExpected: Boolean): Path? {
val library = sourcesPath / "library.jar"
val sourceFiles = sourcesPath.toFile().walkBottomUp()
val commands = buildList {
sourceFiles.mapTo(this) { it.absolutePath }
addAll(options)
add("-d")
add(library.absolutePathString())
}
try {
MockLibraryUtil.runJvmCompiler(commands)
} catch (e: Throwable) {
if (!compilationErrorExpected) {
throw IllegalStateException("Unexpected compilation error while compiling library", e)
}
}
if (library.exists() && compilationErrorExpected) {
error("Compilation error expected but, code was compiled successfully")
}
return library.takeIf(Path::exists)
}
fun parseCompilerOptionsFromTestdata(module: TestModule): List<String> = buildList {
module.directives[LanguageSettingsDirectives.API_VERSION].firstOrNull()?.let { apiVersion ->
addAll(listOf("-api-version", apiVersion.versionString))
}
module.directives[JvmEnvironmentConfigurationDirectives.JVM_TARGET].firstOrNull()?.let { jvmTarget ->
addAll(listOf("-jvm-target", jvmTarget.description))
}
addAll(module.directives[Directives.COMPILER_ARGUMENTS])
}
object Directives : SimpleDirectivesContainer() {
val COMPILER_ARGUMENTS by stringDirective("List of additional compiler arguments")
val COMPILATION_ERRORS by directive("Is compilation errors expected in the file")
}
}
@@ -0,0 +1,79 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.decompiled.service
import com.intellij.mock.MockProject
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.TestKtLibraryModule
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.projectModuleProvider
import org.jetbrains.kotlin.analysis.decompiler.psi.file.KtClsFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.registerTestServices
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.util.KtTestUtil
import java.nio.file.Path
import kotlin.io.path.absolutePathString
import kotlin.io.path.createFile
import kotlin.io.path.div
import kotlin.io.path.writeText
class LibraryModuleRegistrarPreAnalysisHandler(
testServices: TestServices
) : PreAnalysisHandler(testServices) {
private val moduleInfoProvider = testServices.projectModuleProvider
override fun preprocessModuleStructure(moduleStructure: TestModuleStructure) {
val testModule = moduleStructure.modules.single()
val project = testServices.compilerConfigurationProvider.getProject(testModule)
val decompiledKtFiles = getDecompiledVirtualFilesFromLibrary(testModule, project)
moduleInfoProvider.registerModuleInfo(testModule, TestKtLibraryModule(project, testModule, decompiledKtFiles, testServices))
(project as MockProject).registerTestServices(testModule, decompiledKtFiles, testServices)
}
private fun getDecompiledVirtualFilesFromLibrary(module: TestModule, project: Project): List<KtClsFile> {
val tmpDir = KtTestUtil.tmpDir("testSourcesToCompile").toPath()
for (testFile in module.files) {
val text = testServices.sourceFileProvider.getContentOfSourceFile(testFile)
val tmpSourceFile = (tmpDir / testFile.name).createFile()
tmpSourceFile.writeText(text)
}
val library = CompilerExecutor.compileLibrary(
tmpDir,
CompilerExecutor.parseCompilerOptionsFromTestdata(module),
compilationErrorExpected = CompilerExecutor.Directives.COMPILATION_ERRORS in module.directives
) ?: return emptyList()
val virtualFiles = getAllVirtualFilesFromLibrary(library)
return virtualFiles.mapNotNull { virtualFile ->
PsiManager.getInstance(project).findFile(virtualFile) as? KtClsFile
}
}
private fun getAllVirtualFilesFromLibrary(library: Path): Collection<VirtualFile> {
val jarFileSystem = CoreJarFileSystem()
val root = jarFileSystem.refreshAndFindFileByPath(library.absolutePathString() + "!/")!!
val files = mutableSetOf<VirtualFile>()
VfsUtilCore.iterateChildrenRecursively(
root,
/*filter=*/{ true },
/*iterator=*/{ virtualFile ->
if (!virtualFile.isDirectory) {
files.add(virtualFile)
}
true
}
)
return files
}
}
@@ -0,0 +1,68 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.decompiled.service
import com.intellij.ide.highlighter.JavaClassFileType
import com.intellij.mock.MockApplication
import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable
import com.intellij.openapi.extensions.LoadingOrder
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.ClassFileViewProviderFactory
import com.intellij.psi.FileTypeFileViewProviders
import com.intellij.psi.compiled.ClassFileDecompilers
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.api.impl.barebone.test.FrontendApiTestConfiguratorService
import org.jetbrains.kotlin.analysis.decompiled.light.classes.ClsJavaStubByVirtualFileCache
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInDecompiler
import org.jetbrains.kotlin.analysis.decompiler.psi.KotlinClassFileDecompiler
import org.jetbrains.kotlin.analysis.decompiler.stub.file.CachedAttributeData
import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache
import org.jetbrains.kotlin.analysis.decompiler.stub.file.FileAttributeService
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import java.io.DataInput
import java.io.DataOutput
object SymbolLightClassesForLibraryFrontendApiTestConfiguratorService : FrontendApiTestConfiguratorService {
override fun TestConfigurationBuilder.configureTest(disposable: Disposable) {
usePreAnalysisHandlers(::LibraryModuleRegistrarPreAnalysisHandler)
}
override fun registerProjectServices(project: MockProject) {
project.registerService(ClsJavaStubByVirtualFileCache::class.java)
}
override fun registerApplicationServices(application: MockApplication) {
FirFrontendApiTestConfiguratorService.registerApplicationServices(application)
if (application.getServiceIfCreated(ClsKotlinBinaryClassCache::class.java) != null) return
application.registerService(ClsKotlinBinaryClassCache::class.java)
application.registerService(FileAttributeService::class.java, DummyFileAttributeService)
FileTypeFileViewProviders.INSTANCE.addExplicitExtension(
JavaClassFileType.INSTANCE,
ClassFileViewProviderFactory()
)
@Suppress("DEPRECATION")
ClassFileDecompilers.getInstance().EP_NAME.point.registerExtension(KotlinClassFileDecompiler(), LoadingOrder.FIRST)
@Suppress("DEPRECATION")
ClassFileDecompilers.getInstance().EP_NAME.point.registerExtension(KotlinBuiltInDecompiler(), LoadingOrder.FIRST)
}
override fun doOutOfBlockModification(file: KtFile) {
FirFrontendApiTestConfiguratorService.doOutOfBlockModification(file)
}
}
private object DummyFileAttributeService : FileAttributeService {
override fun <T> write(file: VirtualFile, id: String, value: T, writeValueFun: (DataOutput, T) -> Unit): CachedAttributeData<T> {
return CachedAttributeData(value, 0)
}
override fun <T> read(file: VirtualFile, id: String, readValueFun: (DataInput) -> T): CachedAttributeData<T>? {
return null
}
}
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.source
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesFacadeTest
abstract class AbstractSymbolLightClassesFacadeForSourceTest :
AbstractSymbolLightClassesFacadeTest(
FirFrontendApiTestConfiguratorService,
EXTENSIONS.FIR_JAVA,
stopIfCompilationErrorDirectivePresent = false
)
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.source
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesTest
abstract class AbstractSymbolLightClassesForSourceTest :
AbstractSymbolLightClassesTest(
FirFrontendApiTestConfiguratorService,
EXTENSIONS.FIR_JAVA,
stopIfCompilationErrorDirectivePresent = false
)
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.light.classes.symbol.source
import org.jetbrains.kotlin.analysis.api.fir.FirFrontendApiTestConfiguratorService
import org.jetbrains.kotlin.light.classes.symbol.base.AbstractSymbolLightClassesLoadingTest
abstract class AbstractSymbolLightClassesLoadingForSourceTest :
AbstractSymbolLightClassesLoadingTest(
FirFrontendApiTestConfiguratorService,
EXTENSIONS.FIR_JAVA,
stopIfCompilationErrorDirectivePresent = false
)