Finding unused functions.
This commit is contained in:
@@ -118,6 +118,7 @@ goto.super.property.chooser.title=Choose super property
|
||||
goto.super.class.chooser.title=Choose super class or interface
|
||||
|
||||
unused.class=Class ''{0}'' is never used
|
||||
unused.function=Function ''{0}'' is never used
|
||||
|
||||
livetemplate.description.main=main() function
|
||||
livetemplate.description.soutp=Prints function parameter names and values to System.out
|
||||
|
||||
@@ -27,6 +27,7 @@ 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
|
||||
@@ -49,7 +50,7 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||
override fun visitClass(klass: JetClass) {
|
||||
if (klass.getName() == null) return
|
||||
|
||||
if (classIsEntryPoint(klass)) return
|
||||
if (isEntryPoint(klass)) return
|
||||
if (hasNonTrivialUsages(klass)) return
|
||||
if (classHasTextUsages(klass)) return
|
||||
|
||||
@@ -59,13 +60,30 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL
|
||||
) // TODO add quick fix to delete it
|
||||
}
|
||||
|
||||
override fun visitNamedFunction(function: JetNamedFunction) {
|
||||
if (function.getName() == null) return
|
||||
|
||||
if (function.hasModifier(JetTokens.OVERRIDE_KEYWORD)) return
|
||||
if (isEntryPoint(function)) return
|
||||
if (hasNonTrivialUsages(function)) return
|
||||
|
||||
holder.registerProblem(
|
||||
function.getNameIdentifier(),
|
||||
JetBundle.message("unused.function", function.getName()),
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL
|
||||
) // TODO add quick fix to delete it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun classIsEntryPoint(klass: JetClass): Boolean {
|
||||
val lightClass = klass.toLightClass()
|
||||
if (lightClass != null && javaInspection.isEntryPoint(lightClass)) return true
|
||||
return false
|
||||
private fun isEntryPoint(declaration: JetNamedDeclaration): Boolean {
|
||||
val lightElement: PsiElement? = when (declaration) {
|
||||
is JetClass -> declaration.toLightClass()
|
||||
is JetNamedFunction -> LightClassUtil.getLightClassMethod(declaration)
|
||||
else -> null
|
||||
}
|
||||
return lightElement != null && javaInspection.isEntryPoint(lightElement)
|
||||
}
|
||||
|
||||
private fun classHasTextUsages(klass: JetClass): Boolean {
|
||||
@@ -88,6 +106,7 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||
private fun hasNonTrivialUsages(declaration: JetNamedDeclaration): Boolean {
|
||||
val searchHelper: UsagesSearchHelper<out JetNamedDeclaration> = when (declaration) {
|
||||
is JetClass -> ClassUsagesSearchHelper(constructorUsages = true, nonConstructorUsages = true, skipImports = true)
|
||||
is JetNamedFunction -> FunctionUsagesSearchHelper(skipImports = true)
|
||||
else -> return false
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
fun f() {
|
||||
fun main(args: Array<String>) {
|
||||
class Local {
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
fun f() {
|
||||
fun main(args: Array<String>) {
|
||||
class Local {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
class A
|
||||
|
||||
fun f(): A {
|
||||
fun main(args: Array<String>) {
|
||||
val x: A? = null
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
class A {
|
||||
fun f(other: A) {
|
||||
}
|
||||
val x: A? = null
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
open class Klass {
|
||||
fun used() {
|
||||
}
|
||||
}
|
||||
|
||||
class Subklass: Klass()
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
Subklass().used()
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
open class Klass {
|
||||
open fun used() {
|
||||
}
|
||||
}
|
||||
|
||||
class Subklass: Klass() {
|
||||
override fun used() {
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
Subklass().used()
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class Klass: Iterable<String> {
|
||||
override fun iterator(): Iterator<String> {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
Klass()
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class Klass {
|
||||
fun unused() {
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
Klass()
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class Klass {
|
||||
fun used() {
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
Klass().used()
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<problems>
|
||||
<problem>
|
||||
<file>topLevelUnused.kt</file>
|
||||
<line>1</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/topLevelUnused.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
|
||||
<description>Function 'unused' is never used</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>topLevelOnlyInImport.kt</file>
|
||||
<line>5</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/topLevelOnlyInImport.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
|
||||
<description>Function 'onlyInImport' is never used</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>local.kt</file>
|
||||
<line>2</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/local.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
|
||||
<description>Function 'local' is never used</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>local.kt</file>
|
||||
<line>1</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/local.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
|
||||
<description>Function 'outer' is never used</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>usedOnlyRecursively.kt</file>
|
||||
<line>1</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/usedOnlyRecursively.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
|
||||
<description>Function 'usedOnlyRecursively' is never used</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>classMemberUnused.kt</file>
|
||||
<line>2</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/classMemberUnused.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unused Symbol</problem_class>
|
||||
<description>Function 'unused' is never used</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -0,0 +1 @@
|
||||
// INSPECTION_CLASS: org.jetbrains.kotlin.idea.inspections.UnusedSymbolInspection
|
||||
@@ -0,0 +1,5 @@
|
||||
fun outer() {
|
||||
fun local() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package foo
|
||||
|
||||
import foo.onlyInImport
|
||||
|
||||
fun onlyInImport() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fun unused() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fun used() {
|
||||
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
used()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fun usedOnlyRecursively() {
|
||||
usedOnlyRecursively()
|
||||
}
|
||||
@@ -83,5 +83,11 @@ public class JetInspectionTestGenerated extends AbstractJetInspectionTest {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/inspections/unusedSymbol/class/inspectionData/inspections.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("unusedSymbol/function/inspectionData/inspections.test")
|
||||
public void testUnusedSymbol_function_inspectionData_Inspections_test() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/inspections/unusedSymbol/function/inspectionData/inspections.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user