From 2aaf13e7340b331a48afc6f929fd767db4fa41c5 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 15 Mar 2019 10:24:15 +0300 Subject: [PATCH] FIR: fix test compilation for 181 patchset --- .../AbstractFirTypeEnhancementTest.kt.181 | 235 ++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt.181 diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt.181 b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt.181 new file mode 100644 index 00000000000..854a17ea89a --- /dev/null +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt.181 @@ -0,0 +1,235 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. 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.java + +import com.intellij.lang.java.JavaLanguage +import com.intellij.openapi.extensions.Extensions +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.text.StringUtilRt +import com.intellij.psi.* +import com.intellij.psi.impl.PsiFileFactoryImpl +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.testFramework.LightVirtualFile +import org.jetbrains.kotlin.asJava.finder.JavaElementFinder +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM +import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime +import org.jetbrains.kotlin.fir.FirRenderer +import org.jetbrains.kotlin.fir.createSession +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass +import org.jetbrains.kotlin.fir.java.declarations.FirJavaConstructor +import org.jetbrains.kotlin.fir.java.declarations.FirJavaField +import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod +import org.jetbrains.kotlin.fir.java.scopes.JavaClassEnhancementScope +import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider +import org.jetbrains.kotlin.fir.resolve.impl.FirCompositeSymbolProvider +import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope +import org.jetbrains.kotlin.fir.service +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType +import org.jetbrains.kotlin.test.* +import org.jetbrains.kotlin.test.KotlinTestUtils.getAnnotationsJar +import org.jetbrains.kotlin.test.KotlinTestUtils.newConfiguration +import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase +import java.io.File +import java.io.IOException + +abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() { + private lateinit var javaFilesDir: File + + private lateinit var environment: KotlinCoreEnvironment + + val project: Project + get() { + return environment.project + } + + @Throws(Exception::class) + override fun setUp() { + super.setUp() + javaFilesDir = KotlinTestUtils.tmpDirForTest(this) + } + + override fun tearDown() { + FileUtil.delete(javaFilesDir) + super.tearDown() + } + + private fun createJarWithForeignAnnotations(): File = + MockLibraryUtil.compileJavaFilesLibraryToJar(FOREIGN_ANNOTATIONS_SOURCES_PATH, "foreign-annotations") + + private fun createEnvironment(content: String): KotlinCoreEnvironment { + val classpath = mutableListOf(getAnnotationsJar(), ForTestCompileRuntime.runtimeJarForTests()) + if (InTextDirectivesUtils.isDirectiveDefined(content, "ANDROID_ANNOTATIONS")) { + classpath.add(ForTestCompileRuntime.androidAnnotationsForTests()) + } + if (InTextDirectivesUtils.isDirectiveDefined(content, "JVM_ANNOTATIONS")) { + classpath.add(ForTestCompileRuntime.jvmAnnotationsForTests()) + } + if (InTextDirectivesUtils.isDirectiveDefined(content, "FOREIGN_ANNOTATIONS")) { + classpath.add(createJarWithForeignAnnotations()) + } + return KotlinCoreEnvironment.createForTests( + testRootDisposable, + newConfiguration( + ConfigurationKind.JDK_NO_RUNTIME, TestJdkKind.FULL_JDK, classpath, listOf(javaFilesDir) + ), + EnvironmentConfigFiles.JVM_CONFIG_FILES + ) + } + + fun doTest(path: String) { + val javaFile = File(path) + val javaLines = javaFile.readLines() + val content = javaLines.joinToString(separator = "\n") + if (InTextDirectivesUtils.isDirectiveDefined(content, "SKIP_IN_FIR_TEST")) return + + val srcFiles = KotlinTestUtils.createTestFiles( + javaFile.name, FileUtil.loadFile(javaFile, true), + object : KotlinTestUtils.TestFileFactoryNoModules() { + override fun create(fileName: String, text: String, directives: Map): File { + var currentDir = javaFilesDir + if ("/" !in fileName) { + val packageFqName = + text.split("\n").firstOrNull { + it.startsWith("package") + }?.substringAfter("package")?.trim()?.substringBefore(";")?.let { name -> + FqName(name) + } ?: FqName.ROOT + for (segment in packageFqName.pathSegments()) { + currentDir = File(currentDir, segment.asString()).apply { mkdir() } + } + } + val targetFile = File(currentDir, fileName) + try { + FileUtil.writeToFile(targetFile, text) + } catch (e: IOException) { + throw AssertionError(e) + } + + return targetFile + } + }, "" + ) + environment = createEnvironment(content) + val virtualFiles = srcFiles.map { + object : LightVirtualFile( + it.name, JavaLanguage.INSTANCE, StringUtilRt.convertLineSeparators(it.readText()) + ) { + override fun getPath(): String { + //TODO: patch LightVirtualFile + return "/${it.name}" + } + } + } + val factory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl + val psiFiles = virtualFiles.map { factory.trySetupPsiForFile(it, JavaLanguage.INSTANCE, true, false)!! } + + val scope = GlobalSearchScope.filesScope(project, virtualFiles) + .uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project)) + val session = createSession(project, scope) + + val topPsiClasses = psiFiles.flatMap { it.getChildrenOfType().toList() } + + val javaFirDump = StringBuilder().also { builder -> + val renderer = FirRenderer(builder) + val symbolProvider = session.service() as FirCompositeSymbolProvider + val javaProvider = symbolProvider.providers.filterIsInstance().first() + + fun processClassWithChildren(psiClass: PsiClass, parentFqName: FqName) { + val psiFile = psiClass.containingFile + val packageStatement = psiFile.children.filterIsInstance().firstOrNull() + val packageName = packageStatement?.packageName + val fqName = parentFqName.child(Name.identifier(psiClass.name!!)) + val classId = ClassId(packageName?.let { FqName(it) } ?: FqName.ROOT, fqName, false) + javaProvider.getClassLikeSymbolByFqName(classId) + ?: throw AssertionError(classId.asString()) + psiClass.innerClasses.forEach { + processClassWithChildren(psiClass = it, parentFqName = fqName) + } + } + for (psiClass in topPsiClasses) { + processClassWithChildren(psiClass, FqName.ROOT) + } + + val processedJavaClasses = mutableSetOf() + for (javaClass in javaProvider.getJavaTopLevelClasses().sortedBy { it.name }) { + if (javaClass !is FirJavaClass || javaClass in processedJavaClasses) continue + val enhancementScope = javaClass.buildClassSpecificUseSiteScope(session).let { + when (it) { + is FirCompositeScope -> it.scopes.filterIsInstance().first() + is JavaClassEnhancementScope -> it + else -> null + } + } + if (enhancementScope == null) { + javaClass.accept(renderer, null) + } else { + renderer.visitMemberDeclaration(javaClass) + renderer.renderSupertypes(javaClass) + renderer.renderInBraces { + val renderedDeclarations = mutableListOf() + for (declaration in javaClass.declarations) { + if (declaration in renderedDeclarations) continue + when (declaration) { + is FirJavaConstructor -> enhancementScope.processFunctionsByName(javaClass.name) { symbol -> + val enhanced = (symbol as? FirFunctionSymbol)?.fir + if (enhanced != null && enhanced !in renderedDeclarations) { + enhanced.accept(renderer, null) + renderer.newLine() + renderedDeclarations += enhanced + } + ProcessorAction.NEXT + } + is FirJavaMethod -> enhancementScope.processFunctionsByName(declaration.name) { symbol -> + val enhanced = (symbol as? FirFunctionSymbol)?.fir + if (enhanced != null && enhanced !in renderedDeclarations) { + enhanced.accept(renderer, null) + renderer.newLine() + renderedDeclarations += enhanced + } + ProcessorAction.NEXT + } + is FirJavaField -> enhancementScope.processPropertiesByName(declaration.name) { symbol -> + val enhanced = (symbol as? FirPropertySymbol)?.fir + if (enhanced != null && enhanced !in renderedDeclarations) { + enhanced.accept(renderer, null) + renderer.newLine() + renderedDeclarations += enhanced + } + ProcessorAction.NEXT + } + else -> { + declaration.accept(renderer, null) + renderer.newLine() + renderedDeclarations += declaration + } + } + } + } + } + processedJavaClasses += javaClass + } + }.toString() + + val expectedFile = File(javaFile.absolutePath.replace(".java", ".fir.txt")) + KotlinTestUtils.assertEqualsToFile(expectedFile, javaFirDump) + } + + companion object { + private const val FOREIGN_ANNOTATIONS_SOURCES_PATH = "third-party/annotations" + } +} + +abstract class AbstractOwnFirTypeEnhancementTest : AbstractFirTypeEnhancementTest() \ No newline at end of file