From 154b0d8351d7fd7120b9bb11ee4d34c904b1b898 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Tue, 16 Jun 2015 16:24:02 +0300 Subject: [PATCH] KT-7899 "Do not check if annotated by" setting for "Unused symbol" doesn't affect properties #KT-7899 fixed --- .../inspections/UnusedSymbolInspection.kt | 36 +++++++++++++++++++ .../unusedSymbol/function/_common.kt | 3 ++ .../function/unusedButEntryPointAnnotated.kt | 4 +++ .../unusedSymbol/property/_common.kt | 3 ++ .../property/unusedButEntryPointAnnotated.kt | 2 ++ .../codeInsight/AbstractJetInspectionTest.kt | 15 ++++++++ 6 files changed, 63 insertions(+) create mode 100644 idea/testData/inspections/unusedSymbol/function/_common.kt create mode 100644 idea/testData/inspections/unusedSymbol/function/unusedButEntryPointAnnotated.kt create mode 100644 idea/testData/inspections/unusedSymbol/property/_common.kt create mode 100644 idea/testData/inspections/unusedSymbol/property/unusedButEntryPointAnnotated.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt index 512c9705233..acb26d8429f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt @@ -20,6 +20,8 @@ import com.intellij.codeInsight.FileModificationService import com.intellij.codeInsight.daemon.QuickFixBundle import com.intellij.codeInspection.* import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection +import com.intellij.codeInspection.ex.EntryPointsManager +import com.intellij.codeInspection.ex.EntryPointsManagerBase import com.intellij.codeInspection.ex.EntryPointsManagerImpl import com.intellij.openapi.project.Project import com.intellij.openapi.util.TextRange @@ -34,6 +36,7 @@ import com.intellij.refactoring.safeDelete.SafeDeleteHandler import com.intellij.util.Processor import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.descriptors.annotations.Annotated import org.jetbrains.kotlin.idea.JetBundle import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindClassUsagesHandler @@ -44,6 +47,7 @@ import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext import org.jetbrains.kotlin.psi.psiUtil.isAncestor +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.utils.singletonOrEmptyList import java.awt.GridBagConstraints @@ -65,10 +69,42 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() { val lightElement: PsiElement? = when (declaration) { is JetClassOrObject -> declaration.toLightClass() is JetNamedFunction, is JetSecondaryConstructor -> LightClassUtil.getLightClassMethod(declaration as JetFunction) + is JetProperty -> { + // can't rely on light element, check annotation ourselves + val descriptor = declaration.descriptor ?: return false + val entryPointsManager = EntryPointsManager.getInstance(declaration.getProject()) as EntryPointsManagerBase + return checkAnnotatedUsingPatterns( + descriptor, + entryPointsManager.getAdditionalAnnotations() + entryPointsManager.ADDITIONAL_ANNOTATIONS + ) + } else -> return false } return lightElement != null && javaInspection.isEntryPoint(lightElement) } + + // variation of IDEA's AnnotationUtil.checkAnnotatedUsingPatterns() + private fun checkAnnotatedUsingPatterns(annotated: Annotated, annotationPatterns: Collection): Boolean { + val annotationsPresent = annotated.getAnnotations() + .map { it.getType() } + .filter { !it.isError() } + .map { it.getConstructor().getDeclarationDescriptor()?.let { DescriptorUtils.getFqName(it).asString() } } + .filterNotNull() + + if (annotationsPresent.isEmpty()) return false + + for (pattern in annotationPatterns) { + val hasAnnotation = if (pattern.endsWith(".*")) { + annotationsPresent.any { it.startsWith(pattern.dropLast(1)) } + } else { + pattern in annotationsPresent + } + if (hasAnnotation) return true + } + + return false + } + } override fun runForWholeFile() = true diff --git a/idea/testData/inspections/unusedSymbol/function/_common.kt b/idea/testData/inspections/unusedSymbol/function/_common.kt new file mode 100644 index 00000000000..0484e4c2f15 --- /dev/null +++ b/idea/testData/inspections/unusedSymbol/function/_common.kt @@ -0,0 +1,3 @@ +package test.anno + +public annotation class EntryPoint \ No newline at end of file diff --git a/idea/testData/inspections/unusedSymbol/function/unusedButEntryPointAnnotated.kt b/idea/testData/inspections/unusedSymbol/function/unusedButEntryPointAnnotated.kt new file mode 100644 index 00000000000..e020d436b59 --- /dev/null +++ b/idea/testData/inspections/unusedSymbol/function/unusedButEntryPointAnnotated.kt @@ -0,0 +1,4 @@ +@test.anno.EntryPoint +fun entryPoint() { + +} \ No newline at end of file diff --git a/idea/testData/inspections/unusedSymbol/property/_common.kt b/idea/testData/inspections/unusedSymbol/property/_common.kt new file mode 100644 index 00000000000..0484e4c2f15 --- /dev/null +++ b/idea/testData/inspections/unusedSymbol/property/_common.kt @@ -0,0 +1,3 @@ +package test.anno + +public annotation class EntryPoint \ No newline at end of file diff --git a/idea/testData/inspections/unusedSymbol/property/unusedButEntryPointAnnotated.kt b/idea/testData/inspections/unusedSymbol/property/unusedButEntryPointAnnotated.kt new file mode 100644 index 00000000000..5a64001b77c --- /dev/null +++ b/idea/testData/inspections/unusedSymbol/property/unusedButEntryPointAnnotated.kt @@ -0,0 +1,2 @@ +@test.anno.EntryPoint +val entryPoint = "" \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractJetInspectionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractJetInspectionTest.kt index 03a7cdf1033..817b996b216 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractJetInspectionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractJetInspectionTest.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.codeInsight import com.intellij.analysis.AnalysisScope import com.intellij.codeInspection.InspectionManager import com.intellij.codeInspection.LocalInspectionTool +import com.intellij.codeInspection.ex.EntryPointsManagerBase import com.intellij.codeInspection.ex.InspectionManagerEx import com.intellij.codeInspection.ex.LocalInspectionToolWrapper import com.intellij.openapi.util.io.FileUtil @@ -35,8 +36,22 @@ import org.jetbrains.kotlin.test.JetTestUtils import java.io.File public abstract class AbstractJetInspectionTest: LightCodeInsightFixtureTestCase() { + companion object { + val ENTRY_POINT_ANNOTATION = "test.anno.EntryPoint" + } + override fun getProjectDescriptor(): LightProjectDescriptor = JetLightProjectDescriptor.INSTANCE + override fun setUp() { + super.setUp() + EntryPointsManagerBase.getInstance(getProject()).ADDITIONAL_ANNOTATIONS.add(ENTRY_POINT_ANNOTATION) + } + + override fun tearDown() { + EntryPointsManagerBase.getInstance(getProject()).ADDITIONAL_ANNOTATIONS.remove(ENTRY_POINT_ANNOTATION) + super.tearDown() + } + protected fun doTest(path: String) { val optionsFile = File(path) val options = FileUtil.loadFile(optionsFile, true)