[FIR] Generate and enable blackbox codegen tests.
This commit is contained in:
committed by
Mikhail Glukhikh
parent
ac590fa4c9
commit
fc9ccafb84
@@ -16,8 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.psi.PsiElementFinder
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.ProjectScope
|
||||
import org.jetbrains.kotlin.TestsCompiletimeError
|
||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
|
||||
import org.jetbrains.kotlin.backend.jvm.jvmPhases
|
||||
@@ -25,13 +30,31 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.output.writeAllTo
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.createSession
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.backend.Fir2IrConverter
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||
import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession
|
||||
import org.jetbrains.kotlin.fir.java.FirLibrarySession
|
||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.AnalyzingUtils
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
||||
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil
|
||||
import java.io.File
|
||||
|
||||
@@ -65,22 +88,69 @@ object GenerationUtils {
|
||||
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
|
||||
trace: BindingTrace = NoScopeRecordCliBindingTrace()
|
||||
): GenerationState {
|
||||
val analysisResult =
|
||||
JvmResolveUtil.analyzeAndCheckForErrors(files.first().project, files, configuration, packagePartProvider, trace)
|
||||
analysisResult.throwIfError()
|
||||
val project = files.first().project
|
||||
val state = if (configuration.getBoolean(CommonConfigurationKeys.USE_FIR)) {
|
||||
Extensions.getArea(project)
|
||||
.getExtensionPoint(PsiElementFinder.EP_NAME)
|
||||
.unregisterExtension(JavaElementFinder::class.java)
|
||||
|
||||
/* Currently Kapt3 only works with the old JVM backend, so disable IR for everything except actual bytecode generation. */
|
||||
val isIrBackend = classBuilderFactory.classBuilderMode == ClassBuilderMode.FULL && configuration.getBoolean(JVMConfigurationKeys.IR)
|
||||
val state = GenerationState.Builder(
|
||||
files.first().project, classBuilderFactory, analysisResult.moduleDescriptor, analysisResult.bindingContext,
|
||||
files, configuration
|
||||
).codegenFactory(
|
||||
if (isIrBackend)
|
||||
JvmIrCodegenFactory(configuration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jvmPhases))
|
||||
else DefaultCodegenFactory
|
||||
).isIrBackend(isIrBackend).build()
|
||||
if (analysisResult.shouldGenerateCode) {
|
||||
KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION)
|
||||
val scope = GlobalSearchScope.filesScope(project, files.map { it.virtualFile })
|
||||
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project))
|
||||
val librariesScope = ProjectScope.getLibrariesScope(project)
|
||||
val session = createSession(project, scope, librariesScope, packagePartProvider)
|
||||
|
||||
val builder = RawFirBuilder(session, stubMode = false)
|
||||
val resolveTransformer = FirTotalResolveTransformer()
|
||||
val firFiles = files.map {
|
||||
val firFile = builder.buildFirFile(it)
|
||||
(session.firProvider as FirProviderImpl).recordFile(firFile)
|
||||
firFile
|
||||
}.also {
|
||||
try {
|
||||
resolveTransformer.processFiles(it)
|
||||
} catch (e: Exception) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
val (moduleFragment, symbolTable, sourceManager) =
|
||||
Fir2IrConverter.createModuleFragment(session, firFiles, configuration.languageVersionSettings)
|
||||
val dummyBindingContext = NoScopeRecordCliBindingTrace().bindingContext
|
||||
|
||||
val codegenFactory = JvmIrCodegenFactory(configuration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jvmPhases))
|
||||
val generationState = GenerationState.Builder(
|
||||
project, classBuilderFactory, moduleFragment.descriptor, dummyBindingContext, files, configuration
|
||||
).codegenFactory(
|
||||
codegenFactory
|
||||
).isIrBackend(
|
||||
true
|
||||
).build()
|
||||
|
||||
generationState.beforeCompile()
|
||||
codegenFactory.generateModuleInFrontendIRMode(
|
||||
generationState, moduleFragment, CompilationErrorHandler.THROW_EXCEPTION, symbolTable, sourceManager
|
||||
)
|
||||
generationState.factory.done()
|
||||
generationState
|
||||
} else {
|
||||
val analysisResult =
|
||||
JvmResolveUtil.analyzeAndCheckForErrors(project, files, configuration, packagePartProvider, trace)
|
||||
analysisResult.throwIfError()
|
||||
|
||||
/* Currently Kapt3 only works with the old JVM backend, so disable IR for everything except actual bytecode generation. */
|
||||
val isIrBackend =
|
||||
classBuilderFactory.classBuilderMode == ClassBuilderMode.FULL && configuration.getBoolean(JVMConfigurationKeys.IR)
|
||||
val state = GenerationState.Builder(
|
||||
project, classBuilderFactory, analysisResult.moduleDescriptor, analysisResult.bindingContext,
|
||||
files, configuration
|
||||
).codegenFactory(
|
||||
if (isIrBackend)
|
||||
JvmIrCodegenFactory(configuration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jvmPhases))
|
||||
else DefaultCodegenFactory
|
||||
).isIrBackend(isIrBackend).build()
|
||||
if (analysisResult.shouldGenerateCode) {
|
||||
KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION)
|
||||
}
|
||||
state
|
||||
}
|
||||
|
||||
// For JVM-specific errors
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.codegen.ir
|
||||
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
|
||||
abstract class AbstractFirBlackBoxCodegenTest : AbstractIrBlackBoxCodegenTest() {
|
||||
override fun updateConfiguration(configuration: CompilerConfiguration) {
|
||||
configuration.put(CommonConfigurationKeys.USE_FIR, true)
|
||||
configuration.put(JVMConfigurationKeys.IR, true)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.fir
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession
|
||||
import org.jetbrains.kotlin.fir.java.FirLibrarySession
|
||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
||||
|
||||
fun createSession(
|
||||
environment: KotlinCoreEnvironment,
|
||||
sourceScope: GlobalSearchScope,
|
||||
librariesScope: GlobalSearchScope = GlobalSearchScope.notScope(sourceScope)
|
||||
) = createSession(environment.project, sourceScope, librariesScope, environment::createPackagePartProvider)
|
||||
|
||||
fun createSession(
|
||||
project: Project,
|
||||
sourceScope: GlobalSearchScope,
|
||||
librariesScope: GlobalSearchScope,
|
||||
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider
|
||||
): FirSession {
|
||||
val moduleInfo = FirTestModuleInfo()
|
||||
val provider = FirProjectSessionProvider(project)
|
||||
return FirJavaModuleBasedSession(moduleInfo, provider, sourceScope).also {
|
||||
createSessionForDependencies(project, provider, moduleInfo, librariesScope, packagePartProvider)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSessionForDependencies(
|
||||
project: Project,
|
||||
provider: FirProjectSessionProvider,
|
||||
moduleInfo: FirTestModuleInfo,
|
||||
librariesScope: GlobalSearchScope,
|
||||
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider
|
||||
) {
|
||||
val dependenciesInfo = FirTestModuleInfo()
|
||||
moduleInfo.dependencies.add(dependenciesInfo)
|
||||
FirLibrarySession.create(
|
||||
dependenciesInfo, provider, librariesScope, project, packagePartProvider(librariesScope)
|
||||
)
|
||||
}
|
||||
@@ -769,7 +769,7 @@ public class KotlinTestUtils {
|
||||
catch (Throwable e) {
|
||||
if (!isIgnored && AUTOMATICALLY_MUTE_FAILED_TESTS) {
|
||||
String text = doLoadFile(testDataFile);
|
||||
String directive = InTextDirectivesUtils.IGNORE_BACKEND_DIRECTIVE_PREFIX + targetBackend.name() + "\n";
|
||||
String directive = ignoreDirective + targetBackend.name() + "\n";
|
||||
|
||||
String newText;
|
||||
if (text.startsWith("// !")) {
|
||||
@@ -808,7 +808,7 @@ public class KotlinTestUtils {
|
||||
if (isIgnored) {
|
||||
if (AUTOMATICALLY_UNMUTE_PASSED_TESTS) {
|
||||
String text = doLoadFile(testDataFile);
|
||||
String directive = InTextDirectivesUtils.IGNORE_BACKEND_DIRECTIVE_PREFIX + targetBackend.name();
|
||||
String directive = ignoreDirective + targetBackend.name();
|
||||
String newText = Pattern.compile("^" + directive + "\n", Pattern.MULTILINE).matcher(text).replaceAll("");
|
||||
if (!newText.equals(text)) {
|
||||
System.err.println("\"" + directive + "\" was removed from \"" + testDataFile + "\"");
|
||||
|
||||
Reference in New Issue
Block a user