From 5dc0b52e38c88a898816374c817f6edc10553970 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Fri, 7 May 2021 16:20:32 -0700 Subject: [PATCH] FIR UAST: fix/test allCommentsInFile in UFile --- .../kotlin/declarations/FirKotlinUFile.kt | 13 +++- .../testData/declaration/facade.comments.txt | 6 ++ .../testData/declaration/facade.kt | 4 ++ .../testData/declaration/objects.comments.txt | 5 ++ .../testData/declaration/objects.kt | 4 ++ .../kotlin/FirUastCommentLogTestBase.kt | 66 +++++++++++++++++++ .../kotlin/FirUastFileComparisonTestBase.kt | 52 +++++++++++++++ .../common/kotlin/FirUastPluginSelection.kt | 4 +- .../common/kotlin/FirUastRenderLogTestBase.kt | 57 +++------------- .../uast/common/kotlin/FirUastTestSuffix.kt | 13 ++++ .../kotlin/AbstractFE1UastCommentsTest.kt | 30 +++++++++ .../kotlin/AbstractFirUastCommentsTest.kt | 22 +++++++ .../uast/test/kotlin/FE1UastCommentsTest.java | 31 +++++++++ .../uast/test/kotlin/FirUastCommentsTest.java | 31 +++++++++ 14 files changed, 286 insertions(+), 52 deletions(-) create mode 100644 plugins/uast-kotlin-fir/testData/declaration/facade.comments.txt create mode 100644 plugins/uast-kotlin-fir/testData/declaration/objects.comments.txt create mode 100644 plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastCommentLogTestBase.kt create mode 100644 plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastFileComparisonTestBase.kt create mode 100644 plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastTestSuffix.kt create mode 100644 plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/AbstractFE1UastCommentsTest.kt create mode 100644 plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/AbstractFirUastCommentsTest.kt create mode 100644 plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FE1UastCommentsTest.java create mode 100644 plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FirUastCommentsTest.java diff --git a/plugins/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/declarations/FirKotlinUFile.kt b/plugins/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/declarations/FirKotlinUFile.kt index 50f173ad7b1..5aeb9f30b53 100644 --- a/plugins/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/declarations/FirKotlinUFile.kt +++ b/plugins/uast-kotlin-fir/src/org/jetbrains/uast/kotlin/declarations/FirKotlinUFile.kt @@ -5,12 +5,15 @@ package org.jetbrains.uast.kotlin +import com.intellij.psi.PsiComment import com.intellij.psi.PsiElement +import com.intellij.psi.PsiRecursiveElementWalkingVisitor import org.jetbrains.kotlin.asJava.findFacadeClass import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.uast.* +import java.util.ArrayList class FirKotlinUFile( override val psi: KtFile, @@ -30,7 +33,15 @@ class FirKotlinUFile( sourcePsi.packageFqName.asString() } - override val allCommentsInFile: List = comments + override val allCommentsInFile by lz { + val comments = ArrayList(0) + psi.accept(object : PsiRecursiveElementWalkingVisitor() { + override fun visitComment(comment: PsiComment) { + comments += UComment(comment, this@FirKotlinUFile) + } + }) + comments + } override val imports: List by lz { sourcePsi.importDirectives.map { FirKotlinUImportStatement(it, this) } diff --git a/plugins/uast-kotlin-fir/testData/declaration/facade.comments.txt b/plugins/uast-kotlin-fir/testData/declaration/facade.comments.txt new file mode 100644 index 00000000000..95c00e50e7a --- /dev/null +++ b/plugins/uast-kotlin-fir/testData/declaration/facade.comments.txt @@ -0,0 +1,6 @@ +UFile(allCommentsInFile: +UComment(// Single-line comment bound to fun foo) +UComment(/* + * Multi-line comment bound to extension fun buzz + */) +) \ No newline at end of file diff --git a/plugins/uast-kotlin-fir/testData/declaration/facade.kt b/plugins/uast-kotlin-fir/testData/declaration/facade.kt index 51b821e8c08..9aeab10eb91 100644 --- a/plugins/uast-kotlin-fir/testData/declaration/facade.kt +++ b/plugins/uast-kotlin-fir/testData/declaration/facade.kt @@ -3,8 +3,12 @@ package declaration +// Single-line comment bound to fun foo fun foo(): Int = 42 +/* + * Multi-line comment bound to extension fun buzz + */ fun String.buzz(): String { return "$this... zzz..." } diff --git a/plugins/uast-kotlin-fir/testData/declaration/objects.comments.txt b/plugins/uast-kotlin-fir/testData/declaration/objects.comments.txt new file mode 100644 index 00000000000..61def61132b --- /dev/null +++ b/plugins/uast-kotlin-fir/testData/declaration/objects.comments.txt @@ -0,0 +1,5 @@ +UFile(allCommentsInFile: +UComment(// file comment) +UComment(// Single-line comment bound to top-level property) +UComment(// Single-line comment bound to object) +) \ No newline at end of file diff --git a/plugins/uast-kotlin-fir/testData/declaration/objects.kt b/plugins/uast-kotlin-fir/testData/declaration/objects.kt index bbdce4a141d..906f5572205 100644 --- a/plugins/uast-kotlin-fir/testData/declaration/objects.kt +++ b/plugins/uast-kotlin-fir/testData/declaration/objects.kt @@ -1,12 +1,16 @@ import java.lang.Runnable import java.lang.Thread +// file comment + +// Single-line comment bound to top-level property val topRunnable = object : Runnable { override fun run() { println("I'm running") } } +// Single-line comment bound to object object RunnableManager { val tasks : MutableList = mutableListOf() diff --git a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastCommentLogTestBase.kt b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastCommentLogTestBase.kt new file mode 100644 index 00000000000..cd8ca268cdb --- /dev/null +++ b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastCommentLogTestBase.kt @@ -0,0 +1,66 @@ +/* + * 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.uast.common.kotlin + +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.uast.UComment +import org.jetbrains.uast.UFile +import org.jetbrains.uast.asRecursiveLogString +import org.jetbrains.uast.common.kotlin.FirUastTestSuffix.TXT +import org.jetbrains.uast.kotlin.internal.KotlinUElementWithComments +import java.io.File + +interface FirUastCommentLogTestBase : FirUastPluginSelection, FirUastFileComparisonTestBase { + private fun getCommentsFile(filePath: String, suffix: String): File = getTestMetadataFileFromPath(filePath, "comments$suffix") + + private fun getIdenticalCommentsFile(filePath: String): File = getCommentsFile(filePath, TXT) + + private fun getPluginCommentsFile(filePath: String): File { + val identicalFile = getIdenticalCommentsFile(filePath) + if (identicalFile.exists()) return identicalFile + return getCommentsFile(filePath, "$pluginSuffix$TXT") + } + + private fun UComment.testLog(): String { + return "UComment(${text})" + } + + fun check(filePath: String, file: UFile) { + val commentsFile = getPluginCommentsFile(filePath) + + val comments = file.asRecursiveLogString { uElement -> + val stringBuilder = StringBuilder() + when (uElement) { + is UFile -> { + if (uElement.allCommentsInFile.isNotEmpty()) { + stringBuilder.append("UFile(allCommentsInFile:\n") + stringBuilder.append(uElement.allCommentsInFile.joinToString(separator = "\n") { it.testLog() }) + stringBuilder.append("\n)") + } + } + is KotlinUElementWithComments -> { + if (uElement.comments.isNotEmpty()) { + stringBuilder.append("${uElement::class.java.simpleName}(\n") + uElement.comments.joinToString(separator = "\n") { it.testLog() } + stringBuilder.append("\n)") + } + } + } + stringBuilder.toString() + } + // No comments in the file + if (comments.isEmpty()) return + + KotlinTestUtils.assertEqualsToFile(commentsFile, comments) + + cleanUpIdenticalFile( + commentsFile, + getCommentsFile(filePath, "$counterpartSuffix$TXT"), + getIdenticalCommentsFile(filePath), + kind = "comments" + ) + } +} diff --git a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastFileComparisonTestBase.kt b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastFileComparisonTestBase.kt new file mode 100644 index 00000000000..7c89663eaee --- /dev/null +++ b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastFileComparisonTestBase.kt @@ -0,0 +1,52 @@ +/* + * 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.uast.common.kotlin + +import com.intellij.openapi.util.io.FileUtil +import org.jetbrains.kotlin.test.KtAssert +import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase +import java.io.File + +interface FirUastFileComparisonTestBase { + fun getTestMetadataFileFromPath(filePath: String, ext: String): File { + return File(filePath.removeSuffix(".kt") + '.' + ext) + } + + private val isTeamCityBuild: Boolean + get() = System.getenv("TEAMCITY_VERSION") != null + || KtUsefulTestCase.IS_UNDER_TEAMCITY + + fun cleanUpIdenticalFile( + currentFile: File, + counterpartFile: File, + identicalFile: File, + kind: String + ) { + // Already cleaned up + if (identicalFile.exists()) return + // Nothing to compare + if (!currentFile.exists() || !counterpartFile.exists()) return + + val content = currentFile.readText().trim() + if (content == counterpartFile.readText().trim()) { + val message = if (isTeamCityBuild) { + "Please remove .$kind.fir.txt dump and .$kind.fe10.txt dump" + } else { + currentFile.delete() + counterpartFile.delete() + FileUtil.writeToFile(identicalFile, content) + "Deleted .$kind.fir.txt dump and .$kind.fe10.txt dump, added .$kind.txt instead" + } + KtAssert.fail( + """ + Dump via FIR UAST & via FE10 UAST are the same. + $message + Please re-run the test now + """.trimIndent() + ) + } + } +} diff --git a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastPluginSelection.kt b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastPluginSelection.kt index 4ee4c76274c..c179459d672 100644 --- a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastPluginSelection.kt +++ b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastPluginSelection.kt @@ -5,8 +5,8 @@ package org.jetbrains.uast.common.kotlin -private const val FE10_SUFFIX = ".fe10" -private const val FIR_SUFFIX = ".fir" +import org.jetbrains.uast.common.kotlin.FirUastTestSuffix.FE10_SUFFIX +import org.jetbrains.uast.common.kotlin.FirUastTestSuffix.FIR_SUFFIX interface FirUastPluginSelection { // Whether this is FIR UAST plugin or FE 1.0 UAST plugin diff --git a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastRenderLogTestBase.kt b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastRenderLogTestBase.kt index 8da6ffd0875..b5077bc8da4 100644 --- a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastRenderLogTestBase.kt +++ b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastRenderLogTestBase.kt @@ -5,35 +5,29 @@ package org.jetbrains.uast.common.kotlin -import com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.test.KotlinTestUtils -import org.jetbrains.kotlin.test.KtAssert -import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase import org.jetbrains.uast.UFile import org.jetbrains.uast.asRecursiveLogString +import org.jetbrains.uast.common.kotlin.FirUastTestSuffix.TXT import java.io.File -interface FirUastRenderLogTestBase : FirUastPluginSelection { - fun getTestMetadataFileFromPath(filePath: String, ext: String): File { - return File(filePath.removeSuffix(".kt") + '.' + ext) - } - +interface FirUastRenderLogTestBase : FirUastPluginSelection, FirUastFileComparisonTestBase { private fun getRenderFile(filePath: String, suffix: String): File = getTestMetadataFileFromPath(filePath, "render$suffix") private fun getLogFile(filePath: String, suffix: String): File = getTestMetadataFileFromPath(filePath, "log$suffix") - private fun getIdenticalRenderFile(filePath: String): File = getRenderFile(filePath, ".txt") - private fun getIdenticalLogFile(filePath: String): File = getLogFile(filePath, ".txt") + private fun getIdenticalRenderFile(filePath: String): File = getRenderFile(filePath, TXT) + private fun getIdenticalLogFile(filePath: String): File = getLogFile(filePath, TXT) private fun getPluginRenderFile(filePath: String): File { val identicalFile = getIdenticalRenderFile(filePath) if (identicalFile.exists()) return identicalFile - return getRenderFile(filePath, "$pluginSuffix.txt") + return getRenderFile(filePath, "$pluginSuffix$TXT") } private fun getPluginLogFile(filePath: String): File { val identicalFile = getIdenticalLogFile(filePath) if (identicalFile.exists()) return identicalFile - return getLogFile(filePath, "$pluginSuffix.txt") + return getLogFile(filePath, "$pluginSuffix$TXT") } fun check(filePath: String, file: UFile) { @@ -45,50 +39,15 @@ interface FirUastRenderLogTestBase : FirUastPluginSelection { cleanUpIdenticalFile( renderFile, - getRenderFile(filePath, "$counterpartSuffix.txt"), + getRenderFile(filePath, "$counterpartSuffix$TXT"), getIdenticalRenderFile(filePath), kind = "render" ) cleanUpIdenticalFile( logFile, - getLogFile(filePath, "$counterpartSuffix.txt"), + getLogFile(filePath, "$counterpartSuffix$TXT"), getIdenticalLogFile(filePath), kind = "log" ) } - - private val isTeamCityBuild: Boolean - get() = System.getenv("TEAMCITY_VERSION") != null - || KtUsefulTestCase.IS_UNDER_TEAMCITY - - private fun cleanUpIdenticalFile( - currentFile: File, - counterpartFile: File, - identicalFile: File, - kind: String - ) { - // Already cleaned up - if (identicalFile.exists()) return - // Nothing to compare - if (!currentFile.exists() || !counterpartFile.exists()) return - - val content = currentFile.readText().trim() - if (content == counterpartFile.readText().trim()) { - val message = if (isTeamCityBuild) { - "Please remove .$kind.fir.txt dump and .$kind.fe10.txt dump" - } else { - currentFile.delete() - counterpartFile.delete() - FileUtil.writeToFile(identicalFile, content) - "Deleted .$kind.fir.txt dump and .$kind.fe10.txt dump, added .$kind.txt instead" - } - KtAssert.fail( - """ - Dump via FIR UAST & via FE10 UAST are the same. - $message - Please re-run the test now - """.trimIndent() - ) - } - } } diff --git a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastTestSuffix.kt b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastTestSuffix.kt new file mode 100644 index 00000000000..90408cb613a --- /dev/null +++ b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/common/kotlin/FirUastTestSuffix.kt @@ -0,0 +1,13 @@ +/* + * 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.uast.common.kotlin + +object FirUastTestSuffix { + internal const val FE10_SUFFIX = ".fe10" + internal const val FIR_SUFFIX = ".fir" + + internal const val TXT = ".txt" +} diff --git a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/AbstractFE1UastCommentsTest.kt b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/AbstractFE1UastCommentsTest.kt new file mode 100644 index 00000000000..74aa4b63b83 --- /dev/null +++ b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/AbstractFE1UastCommentsTest.kt @@ -0,0 +1,30 @@ +/* + * 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.uast.test.kotlin + +import org.jetbrains.uast.UFile +import org.jetbrains.uast.common.kotlin.FirUastCommentLogTestBase +import java.io.File + +abstract class AbstractFE1UastCommentsTest : AbstractKotlinUastTest(), FirUastCommentLogTestBase { + override val isFirUastPlugin: Boolean = false + + override fun check(filePath: String, file: UFile) { + super.check(filePath, file) + } + + override var testDataDir = File("plugins/uast-kotlin-fir/testData") + + fun doTest(filePath: String) { + testDataDir = File(filePath).parentFile + val testName = filePath.substring(filePath.lastIndexOf('/') + 1).removeSuffix(".kt") + val virtualFile = getVirtualFile(testName) + + val psiFile = psiManager.findFile(virtualFile) ?: error("Can't get psi file for $testName") + val uFile = uastContext.convertElementWithParent(psiFile, null) ?: error("Can't get UFile for $testName") + check(filePath, uFile as UFile) + } +} diff --git a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/AbstractFirUastCommentsTest.kt b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/AbstractFirUastCommentsTest.kt new file mode 100644 index 00000000000..98e716862e0 --- /dev/null +++ b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/AbstractFirUastCommentsTest.kt @@ -0,0 +1,22 @@ +/* + * 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.uast.test.kotlin + +import org.jetbrains.uast.UFile +import org.jetbrains.uast.common.kotlin.FirUastCommentLogTestBase +import org.jetbrains.uast.test.env.kotlin.AbstractFirUastTest + +abstract class AbstractFirUastCommentsTest : AbstractFirUastTest(), FirUastCommentLogTestBase { + override val isFirUastPlugin: Boolean = true + + override fun check(filePath: String, file: UFile) { + super.check(filePath, file) + } + + fun doTest(filePath: String) { + doCheck(filePath) + } +} diff --git a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FE1UastCommentsTest.java b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FE1UastCommentsTest.java new file mode 100644 index 00000000000..a3517984807 --- /dev/null +++ b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FE1UastCommentsTest.java @@ -0,0 +1,31 @@ +/* + * 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.uast.test.kotlin; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +@TestMetadata("plugins/uast-kotlin-fir/testData/declaration") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class FE1UastCommentsTest extends AbstractFE1UastCommentsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("facade.kt") + public void testFacade() throws Exception { + runTest("plugins/uast-kotlin-fir/testData/declaration/facade.kt"); + } + + @TestMetadata("objects.kt") + public void testObjects() throws Exception { + runTest("plugins/uast-kotlin-fir/testData/declaration/objects.kt"); + } +} diff --git a/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FirUastCommentsTest.java b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FirUastCommentsTest.java new file mode 100644 index 00000000000..54de4682fb8 --- /dev/null +++ b/plugins/uast-kotlin-fir/tests/org/jetbrains/uast/test/kotlin/FirUastCommentsTest.java @@ -0,0 +1,31 @@ +/* + * 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.uast.test.kotlin; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +@TestMetadata("plugins/uast-kotlin-fir/testData/declaration") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class FirUastCommentsTest extends AbstractFirUastCommentsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("facade.kt") + public void testFacade() throws Exception { + runTest("plugins/uast-kotlin-fir/testData/declaration/facade.kt"); + } + + @TestMetadata("objects.kt") + public void testObjects() throws Exception { + runTest("plugins/uast-kotlin-fir/testData/declaration/objects.kt"); + } +}