KT-10337 Object marked as unused
#KT-10337 Fixed
This commit is contained in:
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user