[analysis api] move some test framework parts to a separate module

This commit is contained in:
Ilya Kirillov
2022-03-16 18:11:28 +01:00
parent 19658b3a47
commit 3838552a75
131 changed files with 302 additions and 253 deletions
@@ -3,7 +3,7 @@
* 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.analysis.api.impl.barebone.test
package org.jetbrains.kotlin.analysis.test.framework
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
@@ -1,276 +0,0 @@
/*
* 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.analysis.api.impl.barebone.test
import com.intellij.mock.MockApplication
import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.testFramework.TestDataFile
import junit.framework.ComparisonFailure
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoots
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.ExecutionListenerBasedDisposableProvider
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.TestInfrastructureInternals
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.builders.testConfiguration
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives
import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.model.ResultingArtifact
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.impl.TemporaryDirectoryManagerImpl
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.TestInfo
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.ExecutionException
import kotlin.io.path.exists
import kotlin.io.path.nameWithoutExtension
interface FrontendApiTestConfiguratorService {
val testPrefix: String?
get() = null
val allowDependedAnalysisSession: Boolean
get() = true
fun TestConfigurationBuilder.configureTest(disposable: Disposable)
fun processTestFiles(files: List<KtFile>): List<KtFile> = files
fun getOriginalFile(file: KtFile): KtFile = file
fun registerProjectServices(
project: MockProject,
compilerConfig: CompilerConfiguration,
files: List<KtFile>,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
projectStructureProvider: ProjectStructureProvider,
jarFileSystem: CoreJarFileSystem,
)
fun registerApplicationServices(application: MockApplication)
fun prepareTestFiles(files: List<KtFile>, module: TestModule, testServices: TestServices) {}
fun doOutOfBlockModification(file: KtFile)
fun preprocessTestDataPath(path: Path): Path = path
}
abstract class AbstractFrontendApiTest : TestWithDisposable() {
abstract val configurator: FrontendApiTestConfiguratorService
protected open val enableTestInDependedMode: Boolean
get() = configurator.allowDependedAnalysisSession
protected lateinit var testInfo: KotlinTestInfo
private set
protected var useDependedAnalysisSession: Boolean = false
protected lateinit var testDataPath: Path
private set
protected open fun configureTest(builder: TestConfigurationBuilder) {
with(configurator) {
builder.configureTest(disposable)
}
}
protected abstract fun doTestByFileStructure(ktFiles: List<KtFile>, moduleStructure: TestModuleStructure, testServices: TestServices)
protected fun AssertionsService.assertEqualsToTestDataFileSibling(actual: String, extension: String = ".txt") {
val testPrefix = configurator.testPrefix
val expectedFile = getTestDataFileSiblingPath(extension, testPrefix = testPrefix)
assertEqualsToFile(expectedFile, actual)
if (testPrefix != null) {
val expectedFileWithoutPrefix = getTestDataFileSiblingPath(extension, testPrefix = null)
if (expectedFile != expectedFileWithoutPrefix) {
try {
assertEqualsToFile(expectedFileWithoutPrefix, actual)
} catch (ignored: ComparisonFailure) {
return
}
throw AssertionError("\"$expectedFile\" has the same content as \"$expectedFileWithoutPrefix\". Delete the prefixed file.")
}
}
}
protected fun getTestDataFileSiblingPath(extension: String, testPrefix: String?): Path {
val extensionWithDot = "." + extension.removePrefix(".")
val baseName = testDataPath.nameWithoutExtension
if (testPrefix != null) {
val prefixedFile = testDataPath.resolveSibling("$baseName.$testPrefix$extensionWithDot")
if (prefixedFile.exists()) {
return prefixedFile
}
}
return testDataPath.resolveSibling(baseName + extensionWithDot)
}
@OptIn(TestInfrastructureInternals::class)
private val configure: TestConfigurationBuilder.() -> Unit = {
globalDefaults {
frontend = FrontendKinds.FIR
targetPlatform = JvmPlatforms.defaultJvmPlatform
dependencyKind = DependencyKind.Source
}
useConfigurators(
::CommonEnvironmentConfigurator,
::JvmEnvironmentConfigurator,
)
assertions = JUnit5Assertions
useAdditionalService<TemporaryDirectoryManager>(::TemporaryDirectoryManagerImpl)
useDirectives(*AbstractKotlinCompilerTest.defaultDirectiveContainers.toTypedArray())
useDirectives(JvmEnvironmentConfigurationDirectives)
useSourcePreprocessor(::ExpressionMarkersSourceFilePreprocessor)
useAdditionalService { ExpressionMarkerProvider() }
useAdditionalService(::TestKtModuleProvider)
useAdditionalService<ApplicationDisposableProvider> { ExecutionListenerBasedDisposableProvider() }
useAdditionalService<KotlinStandardLibrariesPathProvider> { StandardLibrariesPathProviderForKotlinProject }
configureTest(this)
startingArtifactFactory = { ResultingArtifact.Source() }
this.testInfo = this@AbstractFrontendApiTest.testInfo
}
protected open fun handleInitializationError(exception: Throwable, moduleStructure: TestModuleStructure): InitializationErrorAction =
InitializationErrorAction.THROW
enum class InitializationErrorAction {
IGNORE, THROW
}
protected fun runTest(@TestDataFile path: String) {
testDataPath = configurator.preprocessTestDataPath(Paths.get(path))
val testConfiguration = testConfiguration(path, configure)
Disposer.register(disposable, testConfiguration.rootDisposable)
val testServices = testConfiguration.testServices
val moduleStructure = testConfiguration.moduleStructureExtractor.splitTestDataByModules(
path,
testConfiguration.directives,
)
val singleModule = moduleStructure.modules.single()
val project = try {
testServices.compilerConfigurationProvider.getProject(singleModule)
} catch (_: SkipTestException) {
return
}
registerApplicationServices()
testConfiguration.testServices.register(TestModuleStructure::class, moduleStructure)
testConfiguration.preAnalysisHandlers.forEach { preprocessor ->
try {
preprocessor.preprocessModuleStructure(moduleStructure)
} catch (exception: Throwable) {
when (handleInitializationError(exception, moduleStructure)) {
InitializationErrorAction.IGNORE -> {}
InitializationErrorAction.THROW -> throw exception
}
}
}
val ktFiles = getKtFilesFromModule(testServices, singleModule)
with(project as MockProject) {
val compilerConfigurationProvider = testServices.compilerConfigurationProvider
val compilerConfiguration = compilerConfigurationProvider.getCompilerConfiguration(singleModule)
compilerConfiguration.addJavaSourceRoots(ktFiles.map { File(it.virtualFilePath) })
configurator.registerProjectServices(
this,
compilerConfiguration,
ktFiles,
compilerConfigurationProvider.getPackagePartProviderFactory(singleModule),
KotlinProjectStructureProviderTestImpl(testServices),
compilerConfigurationProvider.getJarFileSystem(singleModule)
)
}
testConfiguration.preAnalysisHandlers.forEach { preprocessor ->
try {
preprocessor.prepareSealedClassInheritors(moduleStructure)
} catch (exception: Throwable) {
when (handleInitializationError(exception, moduleStructure)) {
InitializationErrorAction.IGNORE -> {}
InitializationErrorAction.THROW -> throw exception
}
}
}
configurator.prepareTestFiles(ktFiles, singleModule, testServices)
doTestByFileStructure(ktFiles, moduleStructure, testServices)
if (!enableTestInDependedMode || ktFiles.any {
InTextDirectivesUtils.isDirectiveDefined(it.text, DISABLE_DEPENDED_MODE_DIRECTIVE)
}) {
return
}
try {
useDependedAnalysisSession = true
doTestByFileStructure(configurator.processTestFiles(ktFiles), moduleStructure, testServices)
} catch (e: SkipDependedModeException) {
// Skip the test if needed
} catch (e: ExecutionException) {
if (e.cause !is SkipDependedModeException)
throw Exception("Test succeeded in normal analysis mode but failed in depended analysis mode.", e)
} catch (e: Exception) {
throw Exception("Test succeeded in normal analysis mode but failed in depended analysis mode.", e)
}
}
private fun registerApplicationServices() {
val application = ApplicationManager.getApplication() as MockApplication
KotlinCoreEnvironment.underApplicationLock {
configurator.registerApplicationServices(application)
}
}
@BeforeEach
fun initTestInfo(testInfo: TestInfo) {
this.testInfo = KotlinTestInfo(
className = testInfo.testClass.orElseGet(null)?.name ?: "_undefined_",
methodName = testInfo.testMethod.orElseGet(null)?.name ?: "_testUndefined_",
tags = testInfo.tags
)
}
protected class SkipDependedModeException : Exception()
companion object {
val DISABLE_DEPENDED_MODE_DIRECTIVE = "DISABLE_DEPENDED_MODE"
}
}
fun getKtFilesFromModule(testServices: TestServices, testModule: TestModule): List<KtFile> {
val moduleInfoProvider = testServices.projectModuleProvider
return when (val moduleInfo = moduleInfoProvider.getModule(testModule.name)) {
is TestKtSourceModule -> moduleInfo.testFilesToKtFiles.filterKeys { testFile -> !testFile.isAdditional }.values.toList()
is TestKtLibraryModule -> moduleInfo.ktFiles.toList()
is TestKtLibrarySourceModule -> moduleInfo.ktFiles.toList()
else -> error("Unexpected $moduleInfo")
}
}
@@ -1,140 +0,0 @@
/*
* 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.analysis.api.impl.barebone.test
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.analysis.api.impl.barebone.parentOfType
import org.jetbrains.kotlin.fir.PrivateForInline
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.elementsInRange
import org.jetbrains.kotlin.test.model.TestFile
import org.jetbrains.kotlin.test.services.SourceFilePreprocessor
import org.jetbrains.kotlin.test.services.TestService
import org.jetbrains.kotlin.test.services.TestServices
internal class ExpressionMarkersSourceFilePreprocessor(testServices: TestServices) : SourceFilePreprocessor(testServices) {
override fun process(file: TestFile, content: String): String {
val withSelectedProcessed = processSelectedExpression(file, content)
return processCaretExpression(file, withSelectedProcessed)
}
private fun processSelectedExpression(file: TestFile, content: String): String {
val startCaretPosition = content.indexOfOrNull(TAGS.OPENING_EXPRESSION_TAG) ?: return content
val endCaretPosition = content.indexOfOrNull(TAGS.CLOSING_EXPRESSION_TAG)
?: error("${TAGS.CLOSING_EXPRESSION_TAG} was not found in the file")
check(startCaretPosition < endCaretPosition)
testServices.expressionMarkerProvider.addSelectedExpression(
file,
TextRange.create(startCaretPosition, endCaretPosition - TAGS.OPENING_EXPRESSION_TAG.length)
)
return content
.replace(TAGS.OPENING_EXPRESSION_TAG, "")
.replace(TAGS.CLOSING_EXPRESSION_TAG, "")
}
private fun processCaretExpression(file: TestFile, content: String): String {
var result = content
var match = TAGS.CARET_REGEXP.find(result)
while (match != null) {
val startCaretPosition = match.range.first
val tag = match.groups[2]?.value
testServices.expressionMarkerProvider.addCaret(file, tag, startCaretPosition)
result = result.removeRange(match.range)
match = TAGS.CARET_REGEXP.find(result)
}
return result
}
object TAGS {
const val OPENING_EXPRESSION_TAG = "<expr>"
const val CLOSING_EXPRESSION_TAG = "</expr>"
val CARET_REGEXP = "<caret(_(\\w+))?>".toRegex()
}
}
class ExpressionMarkerProvider : TestService {
private val selected = mutableMapOf<String, TextRange>()
@PrivateForInline
val carets = CaretProvider()
fun addSelectedExpression(file: TestFile, range: TextRange) {
selected[file.relativePath] = range
}
@OptIn(PrivateForInline::class)
fun addCaret(file: TestFile, caretTag: String?, caretOffset: Int) {
carets.addCaret(file.name, caretTag, caretOffset)
}
@OptIn(PrivateForInline::class)
fun getCaretPosition(file: KtFile, caretTag: String? = null): Int {
return carets.getCaretOffset(file.name, caretTag)
?: run {
val caretName = "caret${caretTag?.let { "_$it" }.orEmpty()}"
error("No <$caretName> found in file")
}
}
inline fun <reified P : KtElement> getElementOfTypAtCaret(file: KtFile, caretName: String? = null): P {
val offset = getCaretPosition(file, caretName)
return file.findElementAt(offset)
?.parentOfType<P>()
?: error("No expression found at caret")
}
fun getSelectedElement(file: KtFile): KtElement {
val range = selected[file.name]
?: error("No selected expression found in file")
val elements = file.elementsInRange(range).trimWhitespaces()
if (elements.size != 1) {
error("Expected one element at rage but found ${elements.size} [${elements.joinToString { it::class.simpleName + ": " + it.text }}]")
}
return elements.single() as KtElement
}
private fun List<PsiElement>.trimWhitespaces(): List<PsiElement> =
dropWhile { it is PsiWhiteSpace }
.dropLastWhile { it is PsiWhiteSpace }
}
@PrivateForInline
class CaretProvider {
private val caretToFile = mutableMapOf<String, CaretsInFile>()
fun getCaretOffset(filename: String, caretTag: String?): Int? {
val cartsInFile = caretToFile[filename] ?: return null
return cartsInFile.getCaretOffsetByTag(caretTag)
}
fun addCaret(filename: String, caretTag: String?, caretOffset: Int) {
val cartsInFile = caretToFile.getOrPut(filename) { CaretsInFile() }
cartsInFile.addCaret(caretTag, caretOffset)
}
private class CaretsInFile {
private val carets = mutableMapOf<String, Int>()
fun getCaretOffsetByTag(tag: String?): Int? {
return carets[tag.orEmpty()]
}
fun addCaret(caretTag: String?, caretOffset: Int) {
carets[caretTag.orEmpty()] = caretOffset
}
}
}
val TestServices.expressionMarkerProvider: ExpressionMarkerProvider by TestServices.testServiceAccessor()
fun String.indexOfOrNull(substring: String) =
indexOf(substring).takeIf { it >= 0 }
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2022 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.analysis.api.impl.barebone.test
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.services.TestServices
class KotlinProjectStructureProviderTestImpl(private val testServices: TestServices) : ProjectStructureProvider() {
private val moduleInfoProvider = testServices.projectModuleProvider
override fun getKtModuleForKtElement(element: PsiElement): KtModule {
val containingFile = element.containingFile as KtFile
return moduleInfoProvider.getModuleInfoByKtFile(containingFile) as KtModule
}
override fun getKtLibraryModules(): Collection<TestKtLibraryModule> {
return moduleInfoProvider.getLibraryModules()
}
}
@@ -1,8 +0,0 @@
/*
* Copyright 2010-2022 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.analysis.api.impl.barebone.test
abstract class SkipTestException : RuntimeException()
@@ -1,35 +0,0 @@
/*
* 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.analysis.api.impl.barebone.test
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestService
import org.jetbrains.kotlin.test.services.TestServices
class TestKtModuleProvider(
private val testServices: TestServices
) : TestService {
private val cache = mutableMapOf<String, TestKtModule>()
fun registerModuleInfo(testModule: TestModule, ktModule: TestKtModule) {
cache[testModule.name] = ktModule
}
fun getModuleInfoByKtFile(ktFile: KtFile): TestKtModule =
cache.values.first { moduleSourceInfo ->
(if (ktFile.isPhysical) ktFile else ktFile.originalFile) in moduleSourceInfo.ktFiles
}
fun getModule(moduleName: String): TestKtModule =
cache.getValue(moduleName)
fun getLibraryModules(): Collection<TestKtLibraryModule> {
return cache.values.filterIsInstance<TestKtLibraryModule>()
}
}
val TestServices.projectModuleProvider: TestKtModuleProvider by TestServices.testServiceAccessor()
@@ -1,150 +0,0 @@
/*
* 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.analysis.api.impl.barebone.test
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.ProjectScope
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.test.frontend.fir.getAnalyzerServices
import org.jetbrains.kotlin.test.model.TestFile
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
import org.jetbrains.kotlin.utils.addIfNotNull
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths
@OptIn(ExperimentalStdlibApi::class)
abstract class TestKtModule(
val project: Project,
val testModule: TestModule,
val ktFiles: Set<KtFile>,
testServices: TestServices,
) {
private val moduleProvider = testServices.projectModuleProvider
private val compilerConfigurationProvider = testServices.compilerConfigurationProvider
private val configuration = compilerConfigurationProvider.getCompilerConfiguration(testModule)
val moduleName: String
get() = testModule.name
val directRegularDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
buildList {
testModule.allDependencies.mapTo(this) { moduleProvider.getModule(it.moduleName) as KtModule }
addIfNotNull(
libraryByRoots(
(configuration.jvmModularRoots + configuration.jvmClasspathRoots).map(File::toPath)
)
)
}
}
val directRefinementDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
testModule.dependsOnDependencies
.map { moduleProvider.getModule(it.moduleName) as KtModule }
}
val directFriendDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
buildList {
testModule.friendDependencies.mapTo(this) { moduleProvider.getModule(it.moduleName) as KtModule }
addIfNotNull(
libraryByRoots(configuration[JVMConfigurationKeys.FRIEND_PATHS].orEmpty().map(Paths::get))
)
}
}
protected abstract val ktModule: KtModule
private fun libraryByRoots(roots: List<Path>): LibraryByRoots? {
if (roots.isEmpty()) return null
return LibraryByRoots(
roots,
ktModule,
project,
)
}
val languageVersionSettings: LanguageVersionSettings
get() = testModule.languageVersionSettings
val platform: TargetPlatform
get() = testModule.targetPlatform
val analyzerServices: PlatformDependentAnalyzerServices
get() = testModule.targetPlatform.getAnalyzerServices()
}
class TestKtSourceModule(
project: Project,
testModule: TestModule,
val testFilesToKtFiles: Map<TestFile, KtFile>,
testServices: TestServices
) : TestKtModule(project, testModule, testFilesToKtFiles.values.toSet(), testServices), KtSourceModule {
override val ktModule: KtModule get() = this
override val contentScope: GlobalSearchScope =
TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, testFilesToKtFiles.values)
}
class TestKtLibraryModule(
project: Project,
testModule: TestModule,
ktFiles: Collection<KtFile>,
testServices: TestServices
) : TestKtModule(project, testModule, ktFiles.toSet(), testServices), KtLibraryModule {
override val ktModule: KtModule get() = this
override val libraryName: String get() = testModule.name
override val librarySources: KtLibrarySourceModule? get() = null
override fun getBinaryRoots(): Collection<Path> = ktFiles.map { it.virtualFile.toNioPath() }
override val contentScope: GlobalSearchScope =
GlobalSearchScope.filesScope(project, ktFiles.map { it.virtualFile })
}
class TestKtLibrarySourceModule(
project: Project,
testModule: TestModule,
ktFilesFromSourceJar: Set<KtFile>,
testServices: TestServices,
override val binaryLibrary: KtLibraryModule,
) : TestKtModule(project, testModule, ktFilesFromSourceJar, testServices), KtLibrarySourceModule {
override val ktModule: KtModule get() = this
override val contentScope: GlobalSearchScope get() = GlobalSearchScope.filesScope(project, ktFiles.map { it.virtualFile })
override val libraryName: String get() = testModule.name
}
private class LibraryByRoots(
private val roots: List<Path>,
private val module: KtModule,
override val project: Project,
) : KtLibraryModule {
override val libraryName: String get() = "Test Library"
override val directRegularDependencies: List<KtModule> get() = emptyList()
override val directRefinementDependencies: List<KtModule> get() = emptyList()
override val directFriendDependencies: List<KtModule> get() = emptyList()
override val contentScope: GlobalSearchScope get() = ProjectScope.getLibrariesScope(project)
override val platform: TargetPlatform get() = module.platform
override val analyzerServices: PlatformDependentAnalyzerServices get() = module.analyzerServices
override fun getBinaryRoots(): Collection<Path> = roots
override val librarySources: KtLibrarySourceModule? get() = null
}
@@ -1,28 +0,0 @@
/*
* 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.analysis.api.impl.barebone.test
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.TestInfo
abstract class TestWithDisposable {
private var _disposable: Disposable? = null
protected val disposable: Disposable get() = _disposable!!
@BeforeEach
private fun initDisposable(testInfo: TestInfo) {
_disposable = Disposer.newDisposable("disposable for ${testInfo.displayName}")
}
@AfterEach
private fun disposeDisposable() {
_disposable?.let { Disposer.dispose(it) }
_disposable = null
}
}