KT-10337 Object marked as unused

#KT-10337 Fixed
This commit is contained in:
Valentin Kipyatkov
2016-01-15 16:48:26 +03:00
parent 4c2a14ff43
commit 4c62304a1d
7 changed files with 142 additions and 16 deletions
@@ -28,6 +28,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiReference
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.PsiSearchHelper
import com.intellij.psi.search.PsiSearchHelper.SearchCostResult.*
@@ -35,7 +36,6 @@ import com.intellij.psi.search.SearchScope
import com.intellij.psi.search.searches.DefinitionsScopedSearch
import com.intellij.psi.search.searches.ReferencesSearch
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
@@ -43,14 +43,12 @@ import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindClassUsagesHandler
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.search.usagesSearch.*
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.singletonOrEmptyList
@@ -246,11 +244,31 @@ class UnusedSymbolInspection : AbstractKotlinInspection() {
}
private fun hasReferences(declaration: KtNamedDeclaration, useScope: SearchScope): Boolean {
return !ReferencesSearch.search(declaration, useScope).forEach(Processor {
assert(it != null, { "Found reference is null, was looking for: " + declaration.getElementTextWithContext() })
declaration.isAncestor(it.element) ||
it.element.parent is KtValueArgumentName ||
it.element.getParentOfType<KtImportDirective>(false) != null
return !ReferencesSearch.search(declaration, useScope).forEach(fun (ref: PsiReference): Boolean {
if (declaration.isAncestor(ref.element)) return true // usages inside element's declaration are not counted
if (ref.element.parent is KtValueArgumentName) return true // usage of parameter in form of named argument is not counted
val import = ref.element.getParentOfType<KtImportDirective>(false)
if (import != null) {
// check if we import member(s) from object or enum and search for their usages
if (declaration is KtObjectDeclaration || (declaration is KtClass && declaration.isEnum())) {
if (import.isAllUnder) {
val importedFrom = import.importedReference?.getQualifiedElementSelector()?.mainReference?.resolve()
as? KtClassOrObject ?: return true
return importedFrom.declarations.none { it is KtNamedDeclaration && hasNonTrivialUsages(it) }
}
else {
if (import.importedFqName != declaration.fqName) {
val importedDeclaration = import.importedReference?.getQualifiedElementSelector()?.mainReference?.resolve() as? KtNamedDeclaration
return importedDeclaration == null || !hasNonTrivialUsages(importedDeclaration)
}
}
}
return true
}
return false
})
}
@@ -0,0 +1,28 @@
<problems>
<problem>
<file>usedViaMemberImport.kt</file>
<line>24</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="usedViaMemberImport.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused symbol</problem_class>
<description>Function 'f' is never used</description>
</problem>
<problem>
<file>usedViaMemberImport.kt</file>
<line>16</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="usedViaMemberImport.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused symbol</problem_class>
<description>Class 'E3' is never used</description>
</problem>
<problem>
<file>usedViaMemberImport.kt</file>
<line>20</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="usedViaMemberImport.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused symbol</problem_class>
<description>Class 'E4' is never used</description>
</problem>
</problems>
@@ -0,0 +1 @@
// INSPECTION_CLASS: org.jetbrains.kotlin.idea.inspections.UnusedSymbolInspection
@@ -0,0 +1,27 @@
package xxx
import xxx.E1.AAA1
import xxx.E2.*
import xxx.E3.AAA3
import xxx.E4.*
enum class E1 {
AAA1, BBB1
}
enum class E2 {
AAA2, BBB2
}
enum class E3 {
AAA3, BBB3
}
enum class E4 {
AAA4, BBB4
}
fun f() {
print(AAA1)
print(AAA2)
}
@@ -3,31 +3,34 @@
<file>unused.kt</file>
<line>1</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/unused.kt" />
<entry_point TYPE="file" FQNAME="unused.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
<description>Object 'A' is never used</description>
</problem>
<problem>
<file>usedOnlyInside.kt</file>
<line>1</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/usedOnlyInside.kt" />
<entry_point TYPE="file" FQNAME="usedOnlyInside.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
<description>Object 'A' is never used</description>
</problem>
<problem>
<file>usedInTextByShortName.kt</file>
<line>3</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/usedInTextByShortName.kt" />
<entry_point TYPE="file" FQNAME="usedInTextByShortName.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
<description>Object 'UsedInTextByShortName' is never used</description>
</problem>
<problem>
<file>usedOnlyInImport.kt</file>
<line>3</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/usedOnlyInImport.kt" />
<entry_point TYPE="file" FQNAME="usedOnlyInImport.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
<description>Object 'A' is never used</description>
</problem>
@@ -36,7 +39,7 @@
<file>companionObjectUnused.kt</file>
<line>2</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/companionObjectUnused.kt" />
<entry_point TYPE="file" FQNAME="companionObjectUnused.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
<description>Object 'Companion' is never used</description>
</problem>
@@ -45,8 +48,35 @@
<file>companionObjectUnused.kt</file>
<line>7</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="temp:///src/companionObjectUnused.kt" />
<entry_point TYPE="file" FQNAME="companionObjectUnused.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
<description>Object 'Named' is never used</description>
</problem>
<problem>
<file>usedViaMemberImport.kt</file>
<line>11</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="usedViaMemberImport.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused symbol</problem_class>
<description>Function 'bar' is never used</description>
</problem>
<problem>
<file>usedViaMemberImport.kt</file>
<line>10</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="usedViaMemberImport.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused symbol</problem_class>
<description>Object 'O2' is never used</description>
</problem>
<problem>
<file>usedViaMemberImport.kt</file>
<line>14</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="usedViaMemberImport.kt" />
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused symbol</problem_class>
<description>Function 'f' is never used</description>
</problem>
</problems>
@@ -0,0 +1,16 @@
package xxx
import xxx.O1.foo
import xxx.O2.bar
object O1 {
fun foo(){}
}
object O2 {
fun bar(){}
}
fun f() {
foo()
}
@@ -160,6 +160,12 @@ public class InspectionTestGenerated extends AbstractInspectionTest {
doTest(fileName);
}
@TestMetadata("unusedSymbol/enum/inspectionData/inspections.test")
public void testUnusedSymbol_enum_inspectionData_Inspections_test() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspections/unusedSymbol/enum/inspectionData/inspections.test");
doTest(fileName);
}
@TestMetadata("unusedSymbol/function/inspectionData/inspections.test")
public void testUnusedSymbol_function_inspectionData_Inspections_test() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspections/unusedSymbol/function/inspectionData/inspections.test");