Fix decompiler tests.

For now, JVM and JS backends produce different metadata for package facades (and package parts),
and thus different output is expected for JVM and JS decompiler.
Split decompiler tests into common (decompiledText), JVM-specific (decompiledTextJvm),
and JS-specific (decompiledTextJs)
Join them back together if JS backend migrates to JVM-like package model.
This commit is contained in:
Dmitry Petrov
2015-09-01 10:10:50 +03:00
committed by Michael Bogdanov
parent 282727b9b2
commit f9901f6075
18 changed files with 200 additions and 57 deletions
@@ -61,8 +61,7 @@ import org.jetbrains.kotlin.idea.debugger.AbstractSmartStepIntoTest
import org.jetbrains.kotlin.idea.debugger.evaluate.*
import org.jetbrains.kotlin.idea.decompiler.navigation.AbstractNavigateToLibrarySourceTest
import org.jetbrains.kotlin.idea.decompiler.stubBuilder.AbstractClsStubBuilderTest
import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractDecompiledTextFromJsMetadataTest
import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractDecompiledTextTest
import org.jetbrains.kotlin.idea.decompiler.textBuilder.*
import org.jetbrains.kotlin.idea.editor.quickDoc.AbstractJetQuickDocProviderTest
import org.jetbrains.kotlin.idea.folding.AbstractKotlinFoldingTest
import org.jetbrains.kotlin.idea.hierarchy.AbstractHierarchyTest
@@ -607,14 +606,22 @@ fun main(args: Array<String>) {
model("expressionSelection", testMethod = "doTestExpressionSelection", pattern = """^([^\.]+)\.kt$""")
}
testClass(javaClass<AbstractDecompiledTextTest>()) {
testClass(AbstractCommonDecompiledTextTest::class.java) {
model("decompiler/decompiledText", pattern = """^([^\.]+)$""")
}
testClass(javaClass<AbstractDecompiledTextFromJsMetadataTest>()) {
testClass(AbstractJvmDecompiledTextTest::class.java) {
model("decompiler/decompiledTextJvm", pattern = """^([^\.]+)$""")
}
testClass(AbstractCommonDecompiledTextFromJsMetadataTest::class.java) {
model("decompiler/decompiledText", pattern = """^([^\.]+)$""", targetBackend = TargetBackend.JS)
}
testClass(AbstractJsDecompiledTextFromJsMetadataTest::class.java) {
model("decompiler/decompiledTextJs", pattern = """^([^\.]+)$""", targetBackend = TargetBackend.JS)
}
testClass(javaClass<AbstractClsStubBuilderTest>()) {
model("decompiler/stubBuilder", extension = null, recursive = false)
}
@@ -65,12 +65,9 @@ public fun buildDecompiledText(
.replace(FILE_ABI_VERSION_MARKER, classHeader.version.toString()),
mapOf())
}
classHeader.isCompatiblePackageFacadeKind() ->
buildDecompiledText(packageFqName,
ArrayList(resolver.resolveDeclarationsInFacade(PackageClassUtils.getPackageClassFqName(packageFqName))))
classHeader.isCompatiblePackageFacadeKind(),
classHeader.isCompatibleFileFacadeKind() ->
buildDecompiledText(packageFqName,
ArrayList(resolver.resolveDeclarationsInFacade(classId.asSingleFqName())))
buildDecompiledText(packageFqName, ArrayList(resolver.resolveDeclarationsInFacade(classId.asSingleFqName())))
classHeader.isCompatibleClassKind() ->
buildDecompiledText(packageFqName, listOf(resolver.resolveTopLevelClass(classId)).filterNotNull())
else ->
@@ -0,0 +1,12 @@
// IntelliJ API Decompiler stub source generated from a class file
// Implementation of methods is not available
package test
private var i: kotlin.Int /* compiled code */
internal val p: kotlin.Int /* compiled code */
internal fun f(): kotlin.Unit { /* compiled code */ }
internal fun kotlin.Int.plus(i: kotlin.Int /* = compiled code */): kotlin.Int { /* compiled code */ }
@@ -10,4 +10,3 @@ internal val p: kotlin.Int /* compiled code */
internal fun f(): kotlin.Unit { /* compiled code */ }
internal fun kotlin.Int.plus(i: kotlin.Int /* = compiled code */): kotlin.Int { /* compiled code */ }
@@ -0,0 +1,10 @@
package test
fun f() {}
val p = 3
private var i = 2
fun Int.plus(i: Int = 1) = this + i
class ShouldNotBeVisible1
interface ShouldNotBeVisible2
@@ -0,0 +1,4 @@
// IntelliJ API Decompiler stub source generated from a class file
// Implementation of methods is not available
package test
@@ -0,0 +1,10 @@
package test
fun f() {}
val p = 3
private var i = 2
fun Int.plus(i: Int = 1) = this + i
class ShouldNotBeVisible1
interface ShouldNotBeVisible2
@@ -30,8 +30,11 @@ import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import kotlin.test.fail
public abstract class AbstractDecompiledTextBaseTest(private val isJsLibrary: Boolean = false) : JetLightCodeInsightFixtureTestCase() {
protected val TEST_DATA_PATH: String = PluginTestCaseBase.getTestDataPathBase() + "/decompiler/decompiledText"
public abstract class AbstractDecompiledTextBaseTest(
baseDirectory: String,
private val isJsLibrary: Boolean = false
) : JetLightCodeInsightFixtureTestCase() {
protected val TEST_DATA_PATH: String = PluginTestCaseBase.getTestDataPathBase() + baseDirectory
protected val TEST_PACKAGE: String = "test"
@@ -27,11 +27,10 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import kotlin.test.assertTrue
public abstract class AbstractDecompiledTextFromJsMetadataTest : AbstractDecompiledTextBaseTest(true) {
public abstract class AbstractDecompiledTextFromJsMetadataTest(baseDirectory: String) : AbstractDecompiledTextBaseTest(baseDirectory, true) {
protected override fun getFileToDecompile(): VirtualFile {
val className = getTestName(false)
val virtualFileFinder = JsVirtualFileFinder.SERVICE.getInstance(getProject())
val virtualFileFinder = JsVirtualFileFinder.SERVICE.getInstance(project)
val classId = ClassId(FqName(TEST_PACKAGE), FqName(className), false)
return virtualFileFinder.findVirtualFileWithHeader(classId)!!
}
@@ -42,6 +41,10 @@ public abstract class AbstractDecompiledTextFromJsMetadataTest : AbstractDecompi
override fun setUp() {
super.setUp()
myModule!!.configureAs(ModuleKind.KOTLIN_JAVASCRIPT)
KotlinJavaScriptLibraryManager.getInstance(getProject()).syncUpdateProjectLibrary()
KotlinJavaScriptLibraryManager.getInstance(project).syncUpdateProjectLibrary()
}
}
public abstract class AbstractCommonDecompiledTextFromJsMetadataTest : AbstractDecompiledTextFromJsMetadataTest("/decompiler/decompiledText")
public abstract class AbstractJsDecompiledTextFromJsMetadataTest : AbstractDecompiledTextFromJsMetadataTest("/decompiler/decompiledTextJs")
@@ -22,11 +22,14 @@ import org.jetbrains.kotlin.idea.decompiler.JetClsFile
import org.jetbrains.kotlin.idea.decompiler.navigation.NavigateToDecompiledLibraryTest
import kotlin.test.assertTrue
public abstract class AbstractDecompiledTextTest() : AbstractDecompiledTextBaseTest() {
public abstract class AbstractDecompiledTextTest(baseDirectory: String) : AbstractDecompiledTextBaseTest(baseDirectory) {
protected override fun getFileToDecompile(): VirtualFile =
NavigateToDecompiledLibraryTest.getClassFile(TEST_PACKAGE, getTestName(false), myModule!!)
protected override fun checkPsiFile(psiFile: PsiFile) =
assertTrue(psiFile is JetClsFile, "Expecting decompiled kotlin file, was: " + psiFile.javaClass)
}
public abstract class AbstractCommonDecompiledTextTest : AbstractDecompiledTextTest("/decompiler/decompiledText")
public abstract class AbstractJvmDecompiledTextTest : AbstractDecompiledTextTest("/decompiler/decompiledTextJvm")
@@ -30,7 +30,7 @@ import java.util.regex.Pattern;
@TestMetadata("idea/testData/decompiler/decompiledText")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class DecompiledTextFromJsMetadataTestGenerated extends AbstractDecompiledTextFromJsMetadataTest {
public class CommonDecompiledTextFromJsMetadataTestGenerated extends AbstractCommonDecompiledTextFromJsMetadataTest {
@TestMetadata("DependencyOnNestedClasses")
public void ignoredDependencyOnNestedClasses() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/decompiler/decompiledText/DependencyOnNestedClasses/");
@@ -107,10 +107,4 @@ public class DecompiledTextFromJsMetadataTestGenerated extends AbstractDecompile
doTest(fileName);
}
@TestMetadata("TestPackage")
public void testTestPackage() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/decompiler/decompiledText/TestPackage/");
doTest(fileName);
}
}
@@ -30,7 +30,7 @@ import java.util.regex.Pattern;
@TestMetadata("idea/testData/decompiler/decompiledText")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class DecompiledTextTestGenerated extends AbstractDecompiledTextTest {
public class CommonDecompiledTextTestGenerated extends AbstractCommonDecompiledTextTest {
public void testAllFilesPresentInDecompiledText() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/decompiler/decompiledText"), Pattern.compile("^([^\\.]+)$"), true);
}
@@ -107,10 +107,4 @@ public class DecompiledTextTestGenerated extends AbstractDecompiledTextTest {
doTest(fileName);
}
@TestMetadata("TestPackage")
public void testTestPackage() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/decompiler/decompiledText/TestPackage/");
doTest(fileName);
}
}
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.idea.decompiler.textBuilder
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.test.JetWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.load.kotlin.JvmVirtualFileFinder
@@ -26,8 +26,10 @@ import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.BindingTraceContext
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.descriptors.PackageFacadeProvider
import org.jetbrains.kotlin.idea.caches.resolve.IDEPackageFacadeProvider
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
public class DecompiledTextConsistencyTest : TextConsistencyBaseTest() {
@@ -38,14 +40,14 @@ public class DecompiledTextConsistencyTest : TextConsistencyBaseTest() {
override fun getTopLevelMembers(): Map<String, String> = mapOf("kotlin.JUtilKt" to "linkedListOf")
override fun getVirtualFileFinder(): VirtualFileFinder =
JvmVirtualFileFinder.SERVICE.getInstance(getProject())
JvmVirtualFileFinder.SERVICE.getInstance(project)
override fun getDecompiledText(packageFile: VirtualFile, resolver: ResolverForDecompiler?): String =
(resolver?.let { buildDecompiledText(packageFile, it) } ?: buildDecompiledText(packageFile)).text
override fun getModuleDescriptor(): ModuleDescriptor =
TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext(
TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(getProject(), "test"),
TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(project, "test"),
listOf(), BindingTraceContext(), null, null,
IDEPackageFacadeProvider(GlobalSearchScope.allScope(project))
).moduleDescriptor
@@ -54,4 +56,9 @@ public class DecompiledTextConsistencyTest : TextConsistencyBaseTest() {
object : JetWithJdkAndRuntimeLightProjectDescriptor() {
override fun getSdk() = PluginTestCaseBase.fullJdk()
}
override fun isFromFacade(descriptor: CallableMemberDescriptor, facadeFqName: FqName): Boolean =
descriptor is DeserializedCallableMemberDescriptor &&
descriptor.proto.hasExtension(JvmProtoBuf.implClassName) &&
facadeFqName == PackagePartClassUtils.getPackagePartFqName(descriptor)
}
@@ -0,0 +1,44 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.decompiler.textBuilder;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.JetTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("idea/testData/decompiler/decompiledTextJs")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class JsDecompiledTextFromJsMetadataTestGenerated extends AbstractJsDecompiledTextFromJsMetadataTest {
public void testAllFilesPresentInDecompiledTextJs() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/decompiler/decompiledTextJs"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("TestPackage")
public void testTestPackage() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/decompiler/decompiledTextJs/TestPackage/");
doTest(fileName);
}
}
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.decompiler.textBuilder;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.JetTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("idea/testData/decompiler/decompiledTextJvm")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class JvmDecompiledTextTestGenerated extends AbstractJvmDecompiledTextTest {
public void testAllFilesPresentInDecompiledTextJvm() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/decompiler/decompiledTextJvm"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("TestKt")
public void testTestKt() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/decompiler/decompiledTextJvm/TestKt/");
doTest(fileName);
}
@TestMetadata("TestPackage")
public void testTestPackage() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/decompiler/decompiledTextJvm/TestPackage/");
doTest(fileName);
}
}
@@ -18,10 +18,14 @@ package org.jetbrains.kotlin.idea.decompiler.textBuilder
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.idea.js.KotlinJavaScriptLibraryManager
import org.jetbrains.kotlin.idea.test.KotlinStdJSProjectDescriptor
import org.jetbrains.kotlin.idea.vfilefinder.JsVirtualFileFinder
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
@@ -44,14 +48,14 @@ public class KotlinJavaScriptDecompiledTextConsistencyTest : TextConsistencyBase
override fun setUp() {
super.setUp()
KotlinJavaScriptLibraryManager.getInstance(getProject()).syncUpdateProjectLibrary()
KotlinJavaScriptLibraryManager.getInstance(project).syncUpdateProjectLibrary()
}
override fun getDecompiledText(packageFile: VirtualFile, resolver: ResolverForDecompiler?): String =
(resolver?.let { buildDecompiledTextFromJsMetadata(packageFile, it) } ?: buildDecompiledTextFromJsMetadata(packageFile)).text
override fun getModuleDescriptor(): ModuleDescriptor {
val stdlibJar = PathUtil.getKotlinPathsForDistDirectory().getJsStdLibJarPath().getAbsolutePath()
val stdlibJar = PathUtil.getKotlinPathsForDistDirectory().jsStdLibJarPath.absolutePath
val module = JetTestUtils.createEmptyModule("<module for stdlib>")
val metadata = KotlinJavascriptMetadataUtils.loadMetadata(stdlibJar)
assert(metadata.size() == 1)
@@ -60,10 +64,16 @@ public class KotlinJavaScriptDecompiledTextConsistencyTest : TextConsistencyBase
.sure { "No package fragment provider was created" }
module.initialize(provider)
module.setDependencies(module, KotlinBuiltIns.getInstance().getBuiltInsModule())
module.setDependencies(module, KotlinBuiltIns.getInstance().builtInsModule)
return module
}
override fun getProjectDescriptor() = KotlinStdJSProjectDescriptor.instance
override fun isFromFacade(descriptor: CallableMemberDescriptor, facadeFqName: FqName): Boolean {
val containingDeclaration = descriptor.containingDeclaration
return containingDeclaration is PackageFragmentDescriptor &&
facadeFqName == PackageClassUtils.getPackageClassFqName(containingDeclaration.fqName)
}
}
@@ -25,15 +25,12 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.idea.test.JetLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinder
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.MemberComparator
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
import org.junit.Assert
public abstract class TextConsistencyBaseTest : JetLightCodeInsightFixtureTestCase() {
@@ -50,6 +47,8 @@ public abstract class TextConsistencyBaseTest : JetLightCodeInsightFixtureTestCa
protected abstract fun getModuleDescriptor(): ModuleDescriptor
protected abstract fun isFromFacade(descriptor: CallableMemberDescriptor, facadeFqName: FqName): Boolean
public fun testConsistency() {
getPackages().forEach { doTestPackage(it) }
getFacades().forEach { doTestFacade(it) }
@@ -74,20 +73,17 @@ public abstract class TextConsistencyBaseTest : JetLightCodeInsightFixtureTestCa
}
Assert.assertFalse(projectBasedText.contains("ERROR"))
}
private inner class ResolverForDecompilerImpl(val module: ModuleDescriptor) : ResolverForDecompiler {
override fun resolveTopLevelClass(classId: ClassId): ClassDescriptor? =
module.resolveTopLevelClass(classId.asSingleFqName(), NoLookupLocation.FROM_TEST)
override fun resolveDeclarationsInFacade(facadeFqName: FqName): Collection<DeclarationDescriptor> =
module.getPackage(facadeFqName.parent()).memberScope.getAllDescriptors().filter {
it is CallableMemberDescriptor &&
it.module != KotlinBuiltIns.getInstance().builtInsModule &&
isFromFacade(it, facadeFqName)
}.sortedWith(MemberComparator.INSTANCE)
}
}
private class ResolverForDecompilerImpl(val module: ModuleDescriptor) : ResolverForDecompiler {
override fun resolveTopLevelClass(classId: ClassId): ClassDescriptor? =
module.resolveTopLevelClass(classId.asSingleFqName(), NoLookupLocation.FROM_TEST)
override fun resolveDeclarationsInFacade(facadeFqName: FqName): Collection<DeclarationDescriptor> =
module.getPackage(facadeFqName.parent()).memberScope.getAllDescriptors().filter {
it is CallableMemberDescriptor &&
it.module != KotlinBuiltIns.getInstance().builtInsModule &&
(it is DeserializedCallableMemberDescriptor && isFromFacade(it, facadeFqName))
}.sortedWith(MemberComparator.INSTANCE)
private fun isFromFacade(descriptor: DeserializedCallableMemberDescriptor, facadeFqName: FqName): Boolean =
descriptor.proto.hasExtension(JvmProtoBuf.implClassName) &&
facadeFqName == PackagePartClassUtils.getPackagePartFqName(descriptor)
}