Quick fix for unused symbol inspection.
This commit is contained in:
@@ -52,6 +52,12 @@ import org.jetbrains.kotlin.idea.search.usagesSearch.dataClassComponentFunctionN
|
||||
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.refactoring.safeDelete.SafeDeleteHandler
|
||||
|
||||
public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||
private val javaInspection = UnusedDeclarationInspection()
|
||||
@@ -60,6 +66,19 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
|
||||
return object : JetVisitorVoid() {
|
||||
private fun createQuickFix(declaration: JetNamedDeclaration): LocalQuickFix {
|
||||
return object : LocalQuickFix {
|
||||
override fun getName() = QuickFixBundle.message("safe.delete.text", declaration.getName())
|
||||
|
||||
override fun getFamilyName() = "whatever"
|
||||
|
||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor?) {
|
||||
if (!FileModificationService.getInstance().prepareFileForWrite(declaration.getContainingFile())) return
|
||||
SafeDeleteHandler.invoke(project, array(declaration), false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitClass(klass: JetClass) {
|
||||
if (klass.getName() == null) return
|
||||
|
||||
@@ -72,8 +91,9 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||
holder.registerProblem(
|
||||
klass.getNameIdentifier(),
|
||||
JetBundle.message("unused.class", klass.getName()),
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL
|
||||
) // TODO add quick fix to delete it
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||
createQuickFix(klass)
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitNamedFunction(function: JetNamedFunction) {
|
||||
@@ -87,8 +107,9 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||
holder.registerProblem(
|
||||
function.getNameIdentifier(),
|
||||
JetBundle.message("unused.function", function.getName()),
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL
|
||||
) // TODO add quick fix to delete it
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||
createQuickFix(function)
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitProperty(property: JetProperty) {
|
||||
@@ -102,8 +123,9 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||
holder.registerProblem(
|
||||
property.getNameIdentifier(),
|
||||
JetBundle.message("unused.property", property.getName()),
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL
|
||||
) // TODO add quick fix to delete it
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||
createQuickFix(property)
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitParameter(parameter: JetParameter) {
|
||||
@@ -120,8 +142,9 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||
holder.registerProblem(
|
||||
parameter.getNameIdentifier(),
|
||||
JetBundle.message("unused.property", parameter.getName()),
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL
|
||||
) // TODO add quick fix to delete it
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||
createQuickFix(parameter)
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitTypeParameter(parameter: JetTypeParameter) {
|
||||
@@ -132,8 +155,9 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||
holder.registerProblem(
|
||||
parameter.getNameIdentifier(),
|
||||
JetBundle.message("unused.type.parameter", parameter.getName()),
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL
|
||||
) // TODO add quick fix to delete it
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||
createQuickFix(parameter)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,4 +224,4 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() {
|
||||
|
||||
return !query.forEach(Processor { declaration.isAncestor(it.getElement()) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
org.jetbrains.kotlin.idea.inspections.UnusedSymbolInspection
|
||||
@@ -0,0 +1,3 @@
|
||||
// "Safe delete 'UnusedClass'" "true"
|
||||
class DummyClass
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// "Safe delete 'unusedFun'" "true"
|
||||
fun dummy() {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
// "Safe delete 'property'" "true"
|
||||
class UnusedProperty() {
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
// "Safe delete 'property'" "true"
|
||||
class UnusedPropertyAsConstructorParameter()
|
||||
@@ -0,0 +1,2 @@
|
||||
// "Safe delete 'T'" "true"
|
||||
class UnusedTypeParameter<P>(val p: P)
|
||||
@@ -0,0 +1,4 @@
|
||||
// "Safe delete 'UnusedClass'" "true"
|
||||
class DummyClass
|
||||
|
||||
class <caret>UnusedClass
|
||||
@@ -0,0 +1,7 @@
|
||||
// "Safe delete 'unusedFun'" "true"
|
||||
fun dummy() {
|
||||
}
|
||||
|
||||
fun <caret>unusedFun() {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// "Safe delete 'property'" "true"
|
||||
class UnusedProperty() {
|
||||
val <caret>property: String = ":)"
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
// "Safe delete 'property'" "true"
|
||||
class UnusedPropertyAsConstructorParameter(val <caret>property: String)
|
||||
@@ -0,0 +1,2 @@
|
||||
// "Safe delete 'T'" "true"
|
||||
class UnusedTypeParameter<<caret>T, P>(val p: P)
|
||||
@@ -26,9 +26,11 @@ import com.intellij.openapi.projectRoots.JavaSdk;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.apache.commons.lang.SystemUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.idea.DirectiveBasedActionUtils;
|
||||
import org.jetbrains.kotlin.idea.KotlinLightQuickFixTestCase;
|
||||
import org.jetbrains.kotlin.idea.PluginTestCaseBase;
|
||||
@@ -39,6 +41,7 @@ import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -50,6 +53,19 @@ public abstract class AbstractQuickFixTest extends KotlinLightQuickFixTestCase {
|
||||
((StartupManagerImpl) StartupManager.getInstance(getProject())).runPostStartupActivities();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static File findInspectionFile(@NotNull File startDir) {
|
||||
File currentDir = startDir;
|
||||
while (currentDir != null) {
|
||||
File inspectionFile = new File(currentDir, ".inspection");
|
||||
if (inspectionFile.exists()) {
|
||||
return inspectionFile;
|
||||
}
|
||||
currentDir = currentDir.getParentFile();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void doTest(@NotNull String beforeFileName) throws Exception {
|
||||
boolean isWithRuntime = beforeFileName.endsWith("Runtime.kt");
|
||||
|
||||
@@ -58,6 +74,8 @@ public abstract class AbstractQuickFixTest extends KotlinLightQuickFixTestCase {
|
||||
ConfigLibraryUtil.configureKotlinRuntime(getModule(), getFullJavaJDK());
|
||||
}
|
||||
|
||||
enableInspections(beforeFileName);
|
||||
|
||||
doSingleTest(getTestName(false) + ".kt");
|
||||
checkForUnexpectedActions();
|
||||
checkForUnexpectedErrors();
|
||||
@@ -69,6 +87,15 @@ public abstract class AbstractQuickFixTest extends KotlinLightQuickFixTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
private void enableInspections(String beforeFileName) throws IOException, ClassNotFoundException {
|
||||
File inspectionFile = findInspectionFile(new File(beforeFileName).getParentFile());
|
||||
if (inspectionFile != null) {
|
||||
String className = FileUtil.loadFile(inspectionFile).trim();
|
||||
Class<?> inspectionClass = Class.forName(className);
|
||||
enableInspectionTools(inspectionClass);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForUnexpectedActions() throws ClassNotFoundException {
|
||||
String text = getEditor().getDocument().getText();
|
||||
Pair<String, Boolean> pair = parseActionHintImpl(getFile(), text);
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.regex.Pattern;
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/testData/quickfix")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@InnerTestClasses({QuickFixTestGenerated.Abstract.class, QuickFixTestGenerated.AddStarProjections.class, QuickFixTestGenerated.AutoImports.class, QuickFixTestGenerated.ChangeSignature.class, QuickFixTestGenerated.CheckArguments.class, QuickFixTestGenerated.ConflictingImports.class, QuickFixTestGenerated.CreateFromUsage.class, QuickFixTestGenerated.Expressions.class, QuickFixTestGenerated.Migration.class, QuickFixTestGenerated.Modifiers.class, QuickFixTestGenerated.Nullables.class, QuickFixTestGenerated.Override.class, QuickFixTestGenerated.PlatformClasses.class, QuickFixTestGenerated.Supercalls.class, QuickFixTestGenerated.SupertypeInitialization.class, QuickFixTestGenerated.Suppress.class, QuickFixTestGenerated.TypeAddition.class, QuickFixTestGenerated.TypeImports.class, QuickFixTestGenerated.TypeMismatch.class, QuickFixTestGenerated.TypeProjection.class, QuickFixTestGenerated.Variables.class, QuickFixTestGenerated.When.class})
|
||||
@InnerTestClasses({QuickFixTestGenerated.Abstract.class, QuickFixTestGenerated.AddStarProjections.class, QuickFixTestGenerated.AutoImports.class, QuickFixTestGenerated.ChangeSignature.class, QuickFixTestGenerated.CheckArguments.class, QuickFixTestGenerated.ConflictingImports.class, QuickFixTestGenerated.CreateFromUsage.class, QuickFixTestGenerated.Expressions.class, QuickFixTestGenerated.Migration.class, QuickFixTestGenerated.Modifiers.class, QuickFixTestGenerated.Nullables.class, QuickFixTestGenerated.Override.class, QuickFixTestGenerated.PlatformClasses.class, QuickFixTestGenerated.RemoveUnused.class, QuickFixTestGenerated.Supercalls.class, QuickFixTestGenerated.SupertypeInitialization.class, QuickFixTestGenerated.Suppress.class, QuickFixTestGenerated.TypeAddition.class, QuickFixTestGenerated.TypeImports.class, QuickFixTestGenerated.TypeMismatch.class, QuickFixTestGenerated.TypeProjection.class, QuickFixTestGenerated.Variables.class, QuickFixTestGenerated.When.class})
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
public void testAllFilesPresentInQuickfix() throws Exception {
|
||||
@@ -3423,6 +3423,45 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/removeUnused")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class RemoveUnused extends AbstractQuickFixTest {
|
||||
public void testAllFilesPresentInRemoveUnused() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/removeUnused"), Pattern.compile("^before(\\w+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeUnusedClass.kt")
|
||||
public void testUnusedClass() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/removeUnused/beforeUnusedClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeUnusedFunction.kt")
|
||||
public void testUnusedFunction() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/removeUnused/beforeUnusedFunction.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeUnusedProperty.kt")
|
||||
public void testUnusedProperty() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/removeUnused/beforeUnusedProperty.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeUnusedPropertyAsConstructorParameter.kt")
|
||||
public void testUnusedPropertyAsConstructorParameter() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/removeUnused/beforeUnusedPropertyAsConstructorParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("beforeUnusedTypeParameter.kt")
|
||||
public void testUnusedTypeParameter() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/removeUnused/beforeUnusedTypeParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/quickfix/supercalls")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user