Don't show local/anonymous classes in libraries in Project view

This commit is contained in:
Alexander Udalov
2015-03-31 18:52:08 +03:00
parent 0d4d719156
commit 7fda4ef438
3 changed files with 45 additions and 17 deletions
@@ -16,13 +16,17 @@
package org.jetbrains.kotlin.idea.decompiler package org.jetbrains.kotlin.idea.decompiler
import com.intellij.ide.highlighter.JavaClassFileType
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.ClassFileViewProvider
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import com.intellij.psi.ClassFileViewProvider
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass
import com.intellij.ide.highlighter.JavaClassFileType
/**
* Checks if this file is a compiled Kotlin class file (not necessarily ABI-compatible with the current plugin)
*/
public fun isKotlinCompiledFile(file: VirtualFile): Boolean { public fun isKotlinCompiledFile(file: VirtualFile): Boolean {
if (file.getExtension() != JavaClassFileType.INSTANCE!!.getDefaultExtension()) { if (file.getExtension() != JavaClassFileType.INSTANCE!!.getDefaultExtension()) {
return false return false
@@ -34,6 +38,9 @@ public fun isKotlinCompiledFile(file: VirtualFile): Boolean {
header.syntheticClassKind != KotlinSyntheticClass.Kind.LOCAL_TRAIT_IMPL header.syntheticClassKind != KotlinSyntheticClass.Kind.LOCAL_TRAIT_IMPL
} }
/**
* Checks if this file is a compiled Kotlin class file ABI-compatible with the current plugin
*/
public fun isKotlinWithCompatibleAbiVersion(file: VirtualFile): Boolean { public fun isKotlinWithCompatibleAbiVersion(file: VirtualFile): Boolean {
if (!isKotlinCompiledFile(file)) return false if (!isKotlinCompiledFile(file)) return false
@@ -41,6 +48,10 @@ public fun isKotlinWithCompatibleAbiVersion(file: VirtualFile): Boolean {
return header != null && header.isCompatibleAbiVersion return header != null && header.isCompatibleAbiVersion
} }
/**
* Checks if this file is a compiled "internal" Kotlin class, i.e. a Kotlin class (not necessarily ABI-compatible with the current plugin)
* which should NOT be decompiled (and, as a result, shown under the library in the Project view, be searchable via Find class, etc.)
*/
public fun isKotlinInternalCompiledFile(file: VirtualFile): Boolean { public fun isKotlinInternalCompiledFile(file: VirtualFile): Boolean {
if (!isKotlinCompiledFile(file)) { if (!isKotlinCompiledFile(file)) {
return false return false
@@ -49,6 +60,7 @@ public fun isKotlinInternalCompiledFile(file: VirtualFile): Boolean {
if (ClassFileViewProvider.isInnerClass(file)) { if (ClassFileViewProvider.isInnerClass(file)) {
return true return true
} }
val header = KotlinBinaryClassCache.getKotlinBinaryClass(file)?.getClassHeader() val header = KotlinBinaryClassCache.getKotlinBinaryClass(file)?.getClassHeader() ?: return false
return header?.kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS return header.kind == KotlinClassHeader.Kind.SYNTHETIC_CLASS ||
(header.kind == KotlinClassHeader.Kind.CLASS && header.classKind != null && header.classKind != KotlinClass.Kind.CLASS)
} }
@@ -16,26 +16,33 @@
package org.jetbrains.kotlin.idea.decompiler package org.jetbrains.kotlin.idea.decompiler
import org.jetbrains.kotlin.idea.JetLightCodeInsightFixtureTestCase
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.load.java.JvmAbi
import com.intellij.psi.PsiManager
import org.junit.Assert
import com.intellij.psi.impl.compiled.ClsFileImpl
import com.intellij.psi.PsiCompiledFile import com.intellij.psi.PsiCompiledFile
import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiJavaFile
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass.Kind.* import com.intellij.psi.impl.compiled.ClsFileImpl
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache import org.jetbrains.kotlin.idea.JetLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.decompiler.navigation.NavigateToDecompiledLibraryTest import org.jetbrains.kotlin.idea.decompiler.navigation.NavigateToDecompiledLibraryTest
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass.Kind.TRAIT_IMPL
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.junit.Assert
public abstract class AbstractInternalCompiledClassesTest : JetLightCodeInsightFixtureTestCase() { public abstract class AbstractInternalCompiledClassesTest : JetLightCodeInsightFixtureTestCase() {
private fun isSyntheticClassOfKind(kind: KotlinSyntheticClass.Kind) : VirtualFile.() -> Boolean = { private fun isFileWithHeader(predicate: (KotlinClassHeader) -> Boolean) : VirtualFile.() -> Boolean = {
val header = KotlinBinaryClassCache.getKotlinBinaryClass(this)?.getClassHeader() val header = KotlinBinaryClassCache.getKotlinBinaryClass(this)?.getClassHeader()
header?.syntheticClassKind == kind header != null && predicate(header)
} }
private fun isSyntheticClassOfKind(kind: KotlinSyntheticClass.Kind) : VirtualFile.() -> Boolean =
isFileWithHeader { it.syntheticClassKind == kind }
private fun isClassOfKind(kind: KotlinClass.Kind) : VirtualFile.() -> Boolean =
isFileWithHeader { it.classKind == kind }
protected fun doTestTraitImplClassIsVisibleAsJavaClass() { protected fun doTestTraitImplClassIsVisibleAsJavaClass() {
val project = getProject() val project = getProject()
doTest("trait impl", isSyntheticClassOfKind(TRAIT_IMPL)) { doTest("trait impl", isSyntheticClassOfKind(TRAIT_IMPL)) {
@@ -54,6 +61,9 @@ public abstract class AbstractInternalCompiledClassesTest : JetLightCodeInsightF
} }
} }
protected fun doTestNoPsiFilesAreBuiltForLocalClass(kind: KotlinClass.Kind): Unit =
doTestNoPsiFilesAreBuiltFor(kind.toString(), isClassOfKind(kind))
protected fun doTestNoPsiFilesAreBuiltForSyntheticClass(kind: KotlinSyntheticClass.Kind): Unit = protected fun doTestNoPsiFilesAreBuiltForSyntheticClass(kind: KotlinSyntheticClass.Kind): Unit =
doTestNoPsiFilesAreBuiltFor(kind.toString(), isSyntheticClassOfKind(kind)) doTestNoPsiFilesAreBuiltFor(kind.toString(), isSyntheticClassOfKind(kind))
@@ -16,10 +16,12 @@
package org.jetbrains.kotlin.idea.decompiler package org.jetbrains.kotlin.idea.decompiler
import com.intellij.psi.ClassFileViewProvider
import com.intellij.testFramework.LightProjectDescriptor import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.kotlin.idea.JdkAndMockLibraryProjectDescriptor import org.jetbrains.kotlin.idea.JdkAndMockLibraryProjectDescriptor
import org.jetbrains.kotlin.idea.PluginTestCaseBase import org.jetbrains.kotlin.idea.PluginTestCaseBase
import com.intellij.psi.ClassFileViewProvider import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass.Kind.ANONYMOUS_OBJECT
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinClass.Kind.LOCAL_CLASS
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass.Kind.* import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass.Kind.*
public class InternalCompiledClassesTest : AbstractInternalCompiledClassesTest() { public class InternalCompiledClassesTest : AbstractInternalCompiledClassesTest() {
@@ -37,6 +39,10 @@ public class InternalCompiledClassesTest : AbstractInternalCompiledClassesTest()
fun testAnonymousFunctionIsInvisible() = doTestNoPsiFilesAreBuiltForSyntheticClass(ANONYMOUS_FUNCTION) fun testAnonymousFunctionIsInvisible() = doTestNoPsiFilesAreBuiltForSyntheticClass(ANONYMOUS_FUNCTION)
fun testLocalClassIsInvisible() = doTestNoPsiFilesAreBuiltForLocalClass(LOCAL_CLASS)
fun testAnonymousObjectIsInvisible() = doTestNoPsiFilesAreBuiltForLocalClass(ANONYMOUS_OBJECT)
fun testInnerClassIsInvisible() = doTestNoPsiFilesAreBuiltFor("inner or nested class") { fun testInnerClassIsInvisible() = doTestNoPsiFilesAreBuiltFor("inner or nested class") {
ClassFileViewProvider.isInnerClass(this) ClassFileViewProvider.isInnerClass(this)
} }