[FIR] Generate and enable blackbox codegen tests.

This commit is contained in:
Mark Punzalan
2019-11-18 14:34:45 -08:00
committed by Mikhail Glukhikh
parent ac590fa4c9
commit fc9ccafb84
9 changed files with 26932 additions and 178 deletions
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys.CONTENT_ROOTS
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.fir.builder.RawFirBuilder import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.dump.MultiModuleHtmlFirDump import org.jetbrains.kotlin.fir.dump.MultiModuleHtmlFirDump
@@ -16,8 +16,13 @@
package org.jetbrains.kotlin.codegen 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.GlobalSearchScope
import com.intellij.psi.search.ProjectScope
import org.jetbrains.kotlin.TestsCompiletimeError 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.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.backend.jvm.jvmPhases 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.common.output.writeAllTo
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace 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.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys 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.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.psi.KtFile
import org.jetbrains.kotlin.resolve.AnalyzingUtils import org.jetbrains.kotlin.resolve.AnalyzingUtils
import org.jetbrains.kotlin.resolve.BindingTrace 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 org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil
import java.io.File import java.io.File
@@ -65,14 +88,59 @@ object GenerationUtils {
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider, packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
trace: BindingTrace = NoScopeRecordCliBindingTrace() trace: BindingTrace = NoScopeRecordCliBindingTrace()
): GenerationState { ): GenerationState {
val project = files.first().project
val state = if (configuration.getBoolean(CommonConfigurationKeys.USE_FIR)) {
Extensions.getArea(project)
.getExtensionPoint(PsiElementFinder.EP_NAME)
.unregisterExtension(JavaElementFinder::class.java)
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 = val analysisResult =
JvmResolveUtil.analyzeAndCheckForErrors(files.first().project, files, configuration, packagePartProvider, trace) JvmResolveUtil.analyzeAndCheckForErrors(project, files, configuration, packagePartProvider, trace)
analysisResult.throwIfError() analysisResult.throwIfError()
/* Currently Kapt3 only works with the old JVM backend, so disable IR for everything except actual bytecode generation. */ /* 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 isIrBackend =
classBuilderFactory.classBuilderMode == ClassBuilderMode.FULL && configuration.getBoolean(JVMConfigurationKeys.IR)
val state = GenerationState.Builder( val state = GenerationState.Builder(
files.first().project, classBuilderFactory, analysisResult.moduleDescriptor, analysisResult.bindingContext, project, classBuilderFactory, analysisResult.moduleDescriptor, analysisResult.bindingContext,
files, configuration files, configuration
).codegenFactory( ).codegenFactory(
if (isIrBackend) if (isIrBackend)
@@ -82,6 +150,8 @@ object GenerationUtils {
if (analysisResult.shouldGenerateCode) { if (analysisResult.shouldGenerateCode) {
KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION) KotlinCodegenFacade.compileCorrectFiles(state, CompilationErrorHandler.THROW_EXCEPTION)
} }
state
}
// For JVM-specific errors // For JVM-specific errors
try { try {
@@ -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)
}
}
@@ -5,35 +5,43 @@
package org.jetbrains.kotlin.fir package org.jetbrains.kotlin.fir
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession import org.jetbrains.kotlin.fir.java.FirJavaModuleBasedSession
import org.jetbrains.kotlin.fir.java.FirLibrarySession import org.jetbrains.kotlin.fir.java.FirLibrarySession
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
fun createSession( fun createSession(
environment: KotlinCoreEnvironment, environment: KotlinCoreEnvironment,
sourceScope: GlobalSearchScope, sourceScope: GlobalSearchScope,
librariesScope: GlobalSearchScope = GlobalSearchScope.notScope(sourceScope) librariesScope: GlobalSearchScope = GlobalSearchScope.notScope(sourceScope)
) = createSession(environment.project, sourceScope, librariesScope, environment::createPackagePartProvider)
fun createSession(
project: Project,
sourceScope: GlobalSearchScope,
librariesScope: GlobalSearchScope,
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider
): FirSession { ): FirSession {
val moduleInfo = FirTestModuleInfo() val moduleInfo = FirTestModuleInfo()
val project = environment.project
val provider = FirProjectSessionProvider(project) val provider = FirProjectSessionProvider(project)
return FirJavaModuleBasedSession(moduleInfo, provider, sourceScope).also { return FirJavaModuleBasedSession(moduleInfo, provider, sourceScope).also {
createSessionForDependencies(provider, moduleInfo, librariesScope, environment) createSessionForDependencies(project, provider, moduleInfo, librariesScope, packagePartProvider)
} }
} }
private fun createSessionForDependencies( private fun createSessionForDependencies(
project: Project,
provider: FirProjectSessionProvider, provider: FirProjectSessionProvider,
moduleInfo: FirTestModuleInfo, moduleInfo: FirTestModuleInfo,
librariesScope: GlobalSearchScope, librariesScope: GlobalSearchScope,
environment: KotlinCoreEnvironment packagePartProvider: (GlobalSearchScope) -> PackagePartProvider
) { ) {
val dependenciesInfo = FirTestModuleInfo() val dependenciesInfo = FirTestModuleInfo()
moduleInfo.dependencies.add(dependenciesInfo) moduleInfo.dependencies.add(dependenciesInfo)
FirLibrarySession.create( FirLibrarySession.create(
dependenciesInfo, provider, librariesScope, environment.project, dependenciesInfo, provider, librariesScope, project, packagePartProvider(librariesScope)
environment.createPackagePartProvider(librariesScope)
) )
} }
@@ -769,7 +769,7 @@ public class KotlinTestUtils {
catch (Throwable e) { catch (Throwable e) {
if (!isIgnored && AUTOMATICALLY_MUTE_FAILED_TESTS) { if (!isIgnored && AUTOMATICALLY_MUTE_FAILED_TESTS) {
String text = doLoadFile(testDataFile); String text = doLoadFile(testDataFile);
String directive = InTextDirectivesUtils.IGNORE_BACKEND_DIRECTIVE_PREFIX + targetBackend.name() + "\n"; String directive = ignoreDirective + targetBackend.name() + "\n";
String newText; String newText;
if (text.startsWith("// !")) { if (text.startsWith("// !")) {
@@ -808,7 +808,7 @@ public class KotlinTestUtils {
if (isIgnored) { if (isIgnored) {
if (AUTOMATICALLY_UNMUTE_PASSED_TESTS) { if (AUTOMATICALLY_UNMUTE_PASSED_TESTS) {
String text = doLoadFile(testDataFile); 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(""); String newText = Pattern.compile("^" + directive + "\n", Pattern.MULTILINE).matcher(text).replaceAll("");
if (!newText.equals(text)) { if (!newText.equals(text)) {
System.err.println("\"" + directive + "\" was removed from \"" + testDataFile + "\""); System.err.println("\"" + directive + "\" was removed from \"" + testDataFile + "\"");
File diff suppressed because it is too large Load Diff
@@ -482,6 +482,16 @@ fun main(args: Array<String>) {
} }
} }
testGroup(
"compiler/tests", "compiler/testData",
testRunnerMethodName = "runTestWithCustomIgnoreDirective",
additionalRunnerArguments = listOf("\"// IGNORE_BACKEND_FIR: \"")
) {
testClass<AbstractFirBlackBoxCodegenTest> {
model("codegen/box", targetBackend = TargetBackend.JVM_IR, excludeDirs = listOf("oldLanguageVersions"))
}
}
testGroup( testGroup(
"compiler/tests", "compiler/testData", "compiler/tests", "compiler/testData",
testRunnerMethodName = "runTestWithCustomIgnoreDirective", testRunnerMethodName = "runTestWithCustomIgnoreDirective",