Analysis LC: introduce Symbol LC tests
This commit is contained in:
+31
-14
@@ -33,8 +33,8 @@ import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.TestInfo
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import kotlin.io.path.exists
|
||||
import java.util.concurrent.ExecutionException
|
||||
import kotlin.io.path.exists
|
||||
import kotlin.io.path.nameWithoutExtension
|
||||
|
||||
interface FrontendApiTestConfiguratorService {
|
||||
@@ -56,7 +56,7 @@ interface FrontendApiTestConfiguratorService {
|
||||
|
||||
fun doOutOfBlockModification(file: KtFile)
|
||||
|
||||
fun preprocessTestDataPath(path: Path) : Path = path
|
||||
fun preprocessTestDataPath(path: Path): Path = path
|
||||
}
|
||||
|
||||
abstract class AbstractFrontendApiTest(val configurator: FrontendApiTestConfiguratorService) : TestWithDisposable() {
|
||||
@@ -99,7 +99,7 @@ abstract class AbstractFrontendApiTest(val configurator: FrontendApiTestConfigur
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTestDataFileSiblingPath(extension: String, testPrefix: String?): Path {
|
||||
protected fun getTestDataFileSiblingPath(extension: String, testPrefix: String?): Path {
|
||||
val extensionWithDot = "." + extension.removePrefix(".")
|
||||
val baseName = testDataPath.nameWithoutExtension
|
||||
|
||||
@@ -139,6 +139,13 @@ abstract class AbstractFrontendApiTest(val configurator: FrontendApiTestConfigur
|
||||
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)
|
||||
@@ -147,26 +154,36 @@ abstract class AbstractFrontendApiTest(val configurator: FrontendApiTestConfigur
|
||||
val moduleStructure = testConfiguration.moduleStructureExtractor.splitTestDataByModules(
|
||||
path,
|
||||
testConfiguration.directives,
|
||||
).also { testModuleStructure ->
|
||||
testConfiguration.testServices.register(TestModuleStructure::class, testModuleStructure)
|
||||
testConfiguration.preAnalysisHandlers.forEach { preprocessor ->
|
||||
preprocessor.preprocessModuleStructure(testModuleStructure)
|
||||
}
|
||||
}
|
||||
|
||||
)
|
||||
val singleModule = moduleStructure.modules.single()
|
||||
val project = testServices.compilerConfigurationProvider.getProject(singleModule)
|
||||
val moduleInfoProvider = testServices.projectModuleProvider
|
||||
|
||||
val moduleInfo = moduleInfoProvider.getModule(singleModule.name)
|
||||
|
||||
with(project as MockProject) {
|
||||
configurator.registerProjectServices(this)
|
||||
}
|
||||
|
||||
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 moduleInfo = moduleInfoProvider.getModule(singleModule.name)
|
||||
|
||||
val ktFiles = when (moduleInfo) {
|
||||
is TestKtSourceModule -> moduleInfo.testFilesToKtFiles.filterKeys { testFile -> !testFile.isAdditional }.values.toList()
|
||||
is TestKtLibraryModule -> moduleInfo.ktFiles.toList()
|
||||
else -> error("Unexpected $moduleInfo")
|
||||
}
|
||||
|
||||
val ktFiles = moduleInfo.testFilesToKtFiles.filterKeys { testFile -> !testFile.isAdditional }.values.toList()
|
||||
configurator.prepareTestFiles(ktFiles, singleModule, testServices)
|
||||
doTestByFileStructure(ktFiles, moduleStructure, testServices)
|
||||
if (!enableTestInDependedMode || ktFiles.any {
|
||||
|
||||
+5
-7
@@ -5,9 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.impl.barebone.test
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.model.TestFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestService
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
@@ -15,18 +13,18 @@ import org.jetbrains.kotlin.test.services.TestServices
|
||||
class TestKtModuleProvider(
|
||||
private val testServices: TestServices
|
||||
) : TestService {
|
||||
private val cache = mutableMapOf<String, TestKtSourceModule>()
|
||||
private val cache = mutableMapOf<String, TestKtModule>()
|
||||
|
||||
fun registerModuleInfo(project: Project, testModule: TestModule, ktFiles: Map<TestFile, KtFile>) {
|
||||
cache[testModule.name] = TestKtSourceModule(project, testModule, ktFiles, testServices)
|
||||
fun registerModuleInfo(testModule: TestModule, ktModule: TestKtModule) {
|
||||
cache[testModule.name] = ktModule
|
||||
}
|
||||
|
||||
fun getModuleInfoByKtFile(ktFile: KtFile): TestKtSourceModule =
|
||||
fun getModuleInfoByKtFile(ktFile: KtFile): TestKtModule =
|
||||
cache.values.first { moduleSourceInfo ->
|
||||
(if (ktFile.isPhysical) ktFile else ktFile.originalFile) in moduleSourceInfo.ktFiles
|
||||
}
|
||||
|
||||
fun getModule(moduleName: String): TestKtSourceModule =
|
||||
fun getModule(moduleName: String): TestKtModule =
|
||||
cache.getValue(moduleName)
|
||||
}
|
||||
|
||||
|
||||
+48
-22
@@ -31,24 +31,23 @@ import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
class TestKtSourceModule(
|
||||
override val project: Project,
|
||||
abstract class TestKtModule(
|
||||
val project: Project,
|
||||
val testModule: TestModule,
|
||||
val testFilesToKtFiles: Map<TestFile, KtFile>,
|
||||
val ktFiles: Set<KtFile>,
|
||||
testServices: TestServices,
|
||||
) : KtSourceModule {
|
||||
) {
|
||||
private val moduleProvider = testServices.projectModuleProvider
|
||||
private val compilerConfigurationProvider = testServices.compilerConfigurationProvider
|
||||
private val configuration = compilerConfigurationProvider.getCompilerConfiguration(testModule)
|
||||
|
||||
val ktFiles = testFilesToKtFiles.values.toSet()
|
||||
|
||||
override val moduleName: String
|
||||
val moduleName: String
|
||||
get() = testModule.name
|
||||
|
||||
override val directRegularDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
val directRegularDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
buildList {
|
||||
testModule.allDependencies.mapTo(this) { moduleProvider.getModule(it.moduleName) }
|
||||
testModule.allDependencies.mapTo(this) { moduleProvider.getModule(it.moduleName) as KtModule }
|
||||
addIfNotNull(
|
||||
libraryByRoots(
|
||||
(configuration.jvmModularRoots + configuration.jvmClasspathRoots).map(File::toPath)
|
||||
@@ -57,45 +56,72 @@ class TestKtSourceModule(
|
||||
}
|
||||
}
|
||||
|
||||
override val directRefinementDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
val directRefinementDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
testModule.dependsOnDependencies
|
||||
.map { moduleProvider.getModule(it.moduleName) }
|
||||
.map { moduleProvider.getModule(it.moduleName) as KtModule }
|
||||
}
|
||||
|
||||
override val directFriendDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
val directFriendDependencies: List<KtModule> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
buildList {
|
||||
testModule.friendDependencies.mapTo(this) { moduleProvider.getModule(it.moduleName) }
|
||||
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,
|
||||
this@TestKtSourceModule,
|
||||
ktModule,
|
||||
project,
|
||||
)
|
||||
}
|
||||
|
||||
override val contentScope: GlobalSearchScope =
|
||||
TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, testFilesToKtFiles.values)
|
||||
|
||||
override val languageVersionSettings: LanguageVersionSettings
|
||||
val languageVersionSettings: LanguageVersionSettings
|
||||
get() = testModule.languageVersionSettings
|
||||
|
||||
override val platform: TargetPlatform
|
||||
val platform: TargetPlatform
|
||||
get() = testModule.targetPlatform
|
||||
|
||||
override val analyzerServices: PlatformDependentAnalyzerServices
|
||||
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 })
|
||||
}
|
||||
|
||||
private class LibraryByRoots(
|
||||
private val roots: List<Path>,
|
||||
private val sourceModule: KtSourceModule,
|
||||
private val module: KtModule,
|
||||
override val project: Project,
|
||||
) : KtLibraryModule {
|
||||
override val libraryName: String get() = "Test Library"
|
||||
@@ -103,8 +129,8 @@ private class LibraryByRoots(
|
||||
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() = sourceModule.platform
|
||||
override val analyzerServices: PlatformDependentAnalyzerServices get() = sourceModule.analyzerServices
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user