Supported default objects in unused symbol inspection.
This commit is contained in:
@@ -16,60 +16,40 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.inspections
|
package org.jetbrains.kotlin.idea.inspections
|
||||||
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
|
||||||
import com.intellij.codeInspection.ProblemsHolder
|
|
||||||
import com.intellij.codeInspection.LocalInspectionToolSession
|
|
||||||
import com.intellij.psi.PsiElementVisitor
|
|
||||||
import org.jetbrains.kotlin.psi.JetVisitorVoid
|
|
||||||
import org.jetbrains.kotlin.psi.JetClass
|
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchTarget
|
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearch
|
|
||||||
import org.jetbrains.kotlin.idea.JetBundle
|
|
||||||
import com.intellij.codeInspection.ProblemHighlightType
|
|
||||||
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection
|
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
|
||||||
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindClassUsagesHandler
|
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
|
||||||
import org.jetbrains.kotlin.psi.JetNamedDeclaration
|
|
||||||
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens
|
|
||||||
import org.jetbrains.kotlin.psi.JetNamedFunction
|
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchHelper
|
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.ClassUsagesSearchHelper
|
|
||||||
import org.jetbrains.kotlin.asJava.toLightClass
|
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.FunctionUsagesSearchHelper
|
|
||||||
import com.intellij.psi.search.PsiSearchHelper
|
|
||||||
import com.intellij.psi.search.PsiSearchHelper.SearchCostResult.*
|
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.getOperationSymbolsToSearch
|
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.INVOKE_OPERATION_NAME
|
|
||||||
import org.jetbrains.kotlin.psi.JetEnumEntry
|
|
||||||
import org.jetbrains.kotlin.psi.JetProperty
|
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.PropertyUsagesSearchHelper
|
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.getAccessorNames
|
|
||||||
import org.jetbrains.kotlin.psi.JetParameter
|
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.dataClassComponentFunctionName
|
|
||||||
import org.jetbrains.kotlin.psi.JetTypeParameter
|
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.DefaultSearchHelper
|
|
||||||
import com.intellij.util.Processor
|
|
||||||
import com.intellij.codeInspection.LocalQuickFix
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.codeInspection.ProblemDescriptor
|
|
||||||
import com.intellij.codeInsight.daemon.QuickFixBundle
|
|
||||||
import com.intellij.codeInsight.FileModificationService
|
import com.intellij.codeInsight.FileModificationService
|
||||||
import com.intellij.refactoring.safeDelete.SafeDeleteHandler
|
import com.intellij.codeInsight.daemon.QuickFixBundle
|
||||||
import org.jetbrains.kotlin.psi.JetPsiUtil
|
import com.intellij.codeInspection.*
|
||||||
import org.jetbrains.kotlin.psi.JetObjectDeclaration
|
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection
|
||||||
import org.jetbrains.kotlin.psi.JetClassOrObject
|
|
||||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
|
||||||
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
|
|
||||||
import javax.swing.JComponent
|
|
||||||
import java.awt.GridBagConstraints
|
|
||||||
import java.awt.Insets
|
|
||||||
import com.intellij.codeInspection.ex.EntryPointsManager
|
import com.intellij.codeInspection.ex.EntryPointsManager
|
||||||
import com.intellij.codeInspection.ex.EntryPointsManagerImpl
|
import com.intellij.codeInspection.ex.EntryPointsManagerImpl
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.project.ProjectUtil
|
import com.intellij.openapi.project.ProjectUtil
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiElementVisitor
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
|
import com.intellij.psi.search.PsiSearchHelper
|
||||||
|
import com.intellij.psi.search.PsiSearchHelper.SearchCostResult.FEW_OCCURRENCES
|
||||||
|
import com.intellij.psi.search.PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES
|
||||||
|
import com.intellij.psi.search.PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES
|
||||||
|
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.idea.JetBundle
|
||||||
|
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
|
||||||
|
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindClassUsagesHandler
|
||||||
|
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
|
||||||
|
import org.jetbrains.kotlin.idea.search.usagesSearch.*
|
||||||
|
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||||
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||||
|
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||||
|
import java.awt.GridBagConstraints
|
||||||
import java.awt.GridBagLayout
|
import java.awt.GridBagLayout
|
||||||
|
import java.awt.Insets
|
||||||
|
import javax.swing.JComponent
|
||||||
import javax.swing.JPanel
|
import javax.swing.JPanel
|
||||||
|
|
||||||
public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||||
@@ -121,14 +101,13 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
|||||||
if (!ProjectRootsUtil.isInProjectSource(declaration)) return
|
if (!ProjectRootsUtil.isInProjectSource(declaration)) return
|
||||||
|
|
||||||
// Simple PSI-based checks
|
// Simple PSI-based checks
|
||||||
if (declaration.getNameIdentifier() == null) return
|
val isDefaultObject = declaration is JetObjectDeclaration && declaration.isDefault()
|
||||||
|
if (declaration.getNameIdentifier() == null && !isDefaultObject) return
|
||||||
if (declaration is JetEnumEntry) return
|
if (declaration is JetEnumEntry) return
|
||||||
if (declaration.hasModifier(JetTokens.OVERRIDE_KEYWORD)) return
|
if (declaration.hasModifier(JetTokens.OVERRIDE_KEYWORD)) return
|
||||||
if (declaration is JetProperty && declaration.isLocal()) return
|
if (declaration is JetProperty && declaration.isLocal()) return
|
||||||
if (declaration is JetParameter && (declaration.getParent()?.getParent() !is JetClass || !declaration.hasValOrVarNode())) return
|
if (declaration is JetParameter && (declaration.getParent()?.getParent() !is JetClass || !declaration.hasValOrVarNode())) return
|
||||||
if (declaration is JetNamedFunction && isConventionalName(declaration)) return
|
if (declaration is JetNamedFunction && isConventionalName(declaration)) return
|
||||||
//TODO: support this inspection for default objects
|
|
||||||
if (declaration is JetObjectDeclaration && declaration.isDefault()) return
|
|
||||||
|
|
||||||
// More expensive, resolve-based checks
|
// More expensive, resolve-based checks
|
||||||
if (isEntryPoint(declaration)) return
|
if (isEntryPoint(declaration)) return
|
||||||
@@ -139,12 +118,23 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
|||||||
if (hasNonTrivialUsages(declaration)) return
|
if (hasNonTrivialUsages(declaration)) return
|
||||||
if (declaration is JetClassOrObject && classOrObjectHasTextUsages(declaration)) return
|
if (declaration is JetClassOrObject && classOrObjectHasTextUsages(declaration)) return
|
||||||
|
|
||||||
holder.registerProblem(
|
val (inspectionTarget, textRange) = if (isDefaultObject && declaration.getNameIdentifier() == null) {
|
||||||
declaration.getNameIdentifier(),
|
val objectKeyword = (declaration as JetObjectDeclaration).getObjectKeyword()
|
||||||
|
Pair(declaration, TextRange(0, objectKeyword.getStartOffsetInParent() + objectKeyword.getTextLength()))
|
||||||
|
} else {
|
||||||
|
Pair(declaration.getNameIdentifier()!!, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
val problemDescriptor = holder.getManager().createProblemDescriptor(
|
||||||
|
inspectionTarget,
|
||||||
|
textRange,
|
||||||
JetBundle.message(messageKey, declaration.getName()),
|
JetBundle.message(messageKey, declaration.getName()),
|
||||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||||
|
true,
|
||||||
createQuickFix(declaration)
|
createQuickFix(declaration)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
holder.registerProblem(problemDescriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,7 +167,7 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
|||||||
if (useScope is GlobalSearchScope) {
|
if (useScope is GlobalSearchScope) {
|
||||||
var zeroOccurrences = true
|
var zeroOccurrences = true
|
||||||
|
|
||||||
for (name in listOf(declaration.getName()) + declaration.getAccessorNames()) {
|
for (name in listOf(declaration.getName()) + declaration.getAccessorNames() + declaration.getClassNameForDefaultObject().singletonOrEmptyList()) {
|
||||||
when (psiSearchHelper.isCheapEnoughToSearch(name, useScope, null, null)) {
|
when (psiSearchHelper.isCheapEnoughToSearch(name, useScope, null, null)) {
|
||||||
ZERO_OCCURRENCES -> {} // go on, check other names
|
ZERO_OCCURRENCES -> {} // go on, check other names
|
||||||
FEW_OCCURRENCES -> zeroOccurrences = false
|
FEW_OCCURRENCES -> zeroOccurrences = false
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
package defaultObject
|
|
||||||
|
|
||||||
class A {
|
|
||||||
default object {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class B {
|
|
||||||
default object NamedUnused {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class C {
|
|
||||||
default object NamedUsed {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
|
||||||
A()
|
|
||||||
B()
|
|
||||||
C()
|
|
||||||
C.NamedUsed
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
class A {
|
||||||
|
default object {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
default object Named {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
A()
|
||||||
|
B()
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
class A {
|
||||||
|
default object {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
default object Named {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
val a = A
|
||||||
|
B.Named
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import defaultObjectUsedInJava.*
|
||||||
|
|
||||||
|
class JavaUsage {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println(A.CONST + C.CONST);
|
||||||
|
B.foo();
|
||||||
|
D.foo();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package defaultObjectUsedInJava
|
||||||
|
|
||||||
|
import kotlin.platform.platformStatic
|
||||||
|
|
||||||
|
class A {
|
||||||
|
default object {
|
||||||
|
val CONST = 42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
default object {
|
||||||
|
platformStatic fun foo() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class C {
|
||||||
|
default object Named {
|
||||||
|
val CONST = 42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class D {
|
||||||
|
default object Named {
|
||||||
|
platformStatic fun foo() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,4 +31,22 @@
|
|||||||
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
|
||||||
<description>Object 'A' is never used</description>
|
<description>Object 'A' is never used</description>
|
||||||
</problem>
|
</problem>
|
||||||
|
|
||||||
|
<problem>
|
||||||
|
<file>defaultObjectUnused.kt</file>
|
||||||
|
<line>2</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/defaultObjectUnused.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
|
||||||
|
<description>Object 'Default' is never used</description>
|
||||||
|
</problem>
|
||||||
|
|
||||||
|
<problem>
|
||||||
|
<file>defaultObjectUnused.kt</file>
|
||||||
|
<line>7</line>
|
||||||
|
<module>light_idea_test_case</module>
|
||||||
|
<entry_point TYPE="file" FQNAME="temp:///src/defaultObjectUnused.kt" />
|
||||||
|
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
|
||||||
|
<description>Object 'Named' is never used</description>
|
||||||
|
</problem>
|
||||||
</problems>
|
</problems>
|
||||||
|
|||||||
Reference in New Issue
Block a user