From 5612d6727939d857a5242a2b4702997129fa9ee7 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Thu, 23 Feb 2023 12:17:26 +0100 Subject: [PATCH] [code-inspections] SetInspectionOptionFix: support numerical value; used in ExtractMethodRecommenderInspection GitOrigin-RevId: d4f587f5f1e280eca12f5b0e0ab48e232ba187f3 --- .../messages/JavaAnalysisBundle.properties | 6 +- .../ExtractMethodRecommenderInspection.java | 14 +++- .../messages/AnalysisBundle.properties | 1 + .../SetInspectionOptionFix.java | 77 ++++++++++++++----- 4 files changed, 76 insertions(+), 22 deletions(-) diff --git a/java/java-analysis-api/resources/messages/JavaAnalysisBundle.properties b/java/java-analysis-api/resources/messages/JavaAnalysisBundle.properties index 2d49219b2dc1..ee71a54c4c6c 100644 --- a/java/java-analysis-api/resources/messages/JavaAnalysisBundle.properties +++ b/java/java-analysis-api/resources/messages/JavaAnalysisBundle.properties @@ -634,5 +634,7 @@ inspection.extract.method.inspection.name=Method can be extracted inspection.extract.method.nothing=nothing inspection.extract.method.preview.html=Extract {0} statements to a method, which accepts {1} and returns {2} inspection.extract.method.message=Extract method returning ''{0}'' -inspection.extract.method.option.min.length=Minimal length of code to extract:|characters -inspection.extract.method.option.max.parameters=Maximal number of parameters: \ No newline at end of file +inspection.extract.method.option.min.length=Minimal length of code to extract:|symbols +inspection.extract.method.option.max.parameters=Maximal number of parameters: +inspection.extract.method.dont.suggest.parameters=Don''t suggest to extract method accepting {0}+ parameters +inspection.extract.method.dont.suggest.length=Don't suggest to extract such a short methods \ No newline at end of file diff --git a/java/java-impl-refactorings/src/com/intellij/refactoring/extractMethod/ExtractMethodRecommenderInspection.java b/java/java-impl-refactorings/src/com/intellij/refactoring/extractMethod/ExtractMethodRecommenderInspection.java index 0b842df93fe5..7cdaedede2b4 100644 --- a/java/java-impl-refactorings/src/com/intellij/refactoring/extractMethod/ExtractMethodRecommenderInspection.java +++ b/java/java-impl-refactorings/src/com/intellij/refactoring/extractMethod/ExtractMethodRecommenderInspection.java @@ -104,10 +104,22 @@ public class ExtractMethodRecommenderInspection extends AbstractBaseJavaLocalIns textRange = textRange.union(ret.getTextRangeInParent()); } } + List fixes = new ArrayList<>(); + fixes.add(new ExtractMethodFix(from, count, output, inputVariables)); + if (inputVariables.size() > 1) { + fixes.add(new SetInspectionOptionFix(ExtractMethodRecommenderInspection.this, "maxParameters", + JavaAnalysisBundle.message("inspection.extract.method.dont.suggest.parameters", inputVariables.size()), + inputVariables.size() - 1)); + } + if (textRange.getLength() < 10_000) { + fixes.add(new SetInspectionOptionFix(ExtractMethodRecommenderInspection.this, "minLength", + JavaAnalysisBundle.message("inspection.extract.method.dont.suggest.length"), + textRange.getLength() + 1)); + } holder.registerProblem(block, JavaAnalysisBundle.message("inspection.extract.method.message", output.getName()), ProblemHighlightType.WEAK_WARNING, textRange, - new ExtractMethodFix(from, count, output, inputVariables)); + fixes.toArray(LocalQuickFix.EMPTY_ARRAY)); return; } catch (PrepareFailedException | ControlFlowWrapper.ExitStatementsNotSameException | ExtractException ignored) { diff --git a/platform/analysis-api/resources/messages/AnalysisBundle.properties b/platform/analysis-api/resources/messages/AnalysisBundle.properties index b9d5f6efc7ab..f10cac7d3a80 100644 --- a/platform/analysis-api/resources/messages/AnalysisBundle.properties +++ b/platform/analysis-api/resources/messages/AnalysisBundle.properties @@ -226,5 +226,6 @@ html.preview.navigate.line=, line # set.inspection.option.fix=Set inspection option set.inspection.option.description.uncheck=Uncheck inspection option: set.inspection.option.description.check=Check inspection option: +set.inspection.option.description.input=Update numerical inspection option: progress.title.submit.request=Submit progress.title.refresh=Refresh diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/SetInspectionOptionFix.java b/platform/analysis-impl/src/com/intellij/codeInspection/SetInspectionOptionFix.java index a0d0006d88ed..eb7d16cbaba4 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/SetInspectionOptionFix.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/SetInspectionOptionFix.java @@ -6,7 +6,9 @@ import com.intellij.codeInsight.intention.LowPriorityAction; import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo; import com.intellij.codeInspection.ex.InspectionProfileModifiableModelKt; import com.intellij.codeInspection.ex.InspectionToolWrapper; +import com.intellij.codeInspection.options.LocMessage; import com.intellij.codeInspection.options.OptCheckbox; +import com.intellij.codeInspection.options.OptNumber; import com.intellij.codeInspection.options.OptPane; import com.intellij.codeInspection.util.IntentionName; import com.intellij.icons.AllIcons; @@ -29,18 +31,24 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.function.Function; +import static com.intellij.openapi.util.text.HtmlChunk.*; + public class SetInspectionOptionFix extends IntentionAndQuickFixAction implements LowPriorityAction, Iconable { private final String myShortName; private final String myProperty; private final @IntentionName String myMessage; - private final boolean myValue; + private final Object myValue; private final @Nullable Function myExtractor; public SetInspectionOptionFix(LocalInspectionTool inspection, @NonNls String property, @IntentionName String message, boolean value) { this(inspection.getShortName(), property, message, value, null); } - private SetInspectionOptionFix(@NotNull String shortName, @NonNls String property, @IntentionName String message, boolean value, + public SetInspectionOptionFix(LocalInspectionTool inspection, @NonNls String property, @IntentionName String message, int value) { + this(inspection.getShortName(), property, message, value, null); + } + + private SetInspectionOptionFix(@NotNull String shortName, @NonNls String property, @IntentionName String message, Object value, @Nullable Function extractor) { myShortName = shortName; myProperty = property; @@ -83,11 +91,12 @@ public class SetInspectionOptionFix extends IntentionAndQuickFixAction implement @Override public void applyFix(@NotNull Project project, PsiFile file, @Nullable Editor editor) { VirtualFile vFile = file.getVirtualFile(); + Object oldValue = getOption(project, vFile); setOption(project, vFile, myValue); UndoManager.getInstance(project).undoableActionPerformed(new BasicUndoableAction(vFile) { @Override public void undo() { - setOption(project, vFile, !myValue); + setOption(project, vFile, oldValue); } @Override @@ -109,25 +118,55 @@ public class SetInspectionOptionFix extends IntentionAndQuickFixAction implement if (tool == null) return IntentionPreviewInfo.EMPTY; InspectionProfileEntry inspection = myExtractor == null ? tool.getTool() : myExtractor.apply(tool.getTool()); OptPane pane = inspection.getOptionsPane(); - OptCheckbox control = ObjectUtils.tryCast(pane.findControl(myProperty), OptCheckbox.class); - if (control == null) return IntentionPreviewInfo.EMPTY; - HtmlChunk label = HtmlChunk.text(control.label().label()); - HtmlChunk.Element checkbox = HtmlChunk.tag("input").attr("type", "checkbox").attr("readonly", "true"); - if (myValue) { - checkbox = checkbox.attr("checked", "true"); - } - HtmlChunk info = HtmlChunk.tag("table") - .child(HtmlChunk.tag("tr").children( - HtmlChunk.tag("td").child(checkbox), - HtmlChunk.tag("td").child(label) + if (myValue instanceof Boolean value) { + OptCheckbox control = ObjectUtils.tryCast(pane.findControl(myProperty), OptCheckbox.class); + if (control == null) return IntentionPreviewInfo.EMPTY; + HtmlChunk label = text(control.label().label()); + Element checkbox = tag("input").attr("type", "checkbox").attr("readonly", "true"); + if (value) { + checkbox = checkbox.attr("checked", "true"); + } + HtmlChunk info = tag("table") + .child(tag("tr").children( + tag("td").child(checkbox), + tag("td").child(label) + )); + return new IntentionPreviewInfo.Html( + new HtmlBuilder().append(value ? AnalysisBundle.message("set.inspection.option.description.check") + : AnalysisBundle.message("set.inspection.option.description.uncheck")) + .br().br().append(info).toFragment()); + } else if (myValue instanceof Integer value) { + OptNumber control = ObjectUtils.tryCast(pane.findControl(myProperty), OptNumber.class); + if (control == null) return IntentionPreviewInfo.EMPTY; + LocMessage.PrefixSuffix prefixSuffix = control.splitLabel().splitLabel(); + Element input = tag("input").attr("type", "text").attr("value", value) + .attr("size", value.toString().length() + 1).attr("readonly", "true"); + HtmlChunk info = tag("table").child(tag("tr").children( + tag("td").child(text(prefixSuffix.prefix())), + tag("td").child(input), + tag("td").child(text(prefixSuffix.suffix())) )); - return new IntentionPreviewInfo.Html( - new HtmlBuilder().append(myValue ? AnalysisBundle.message("set.inspection.option.description.check") - : AnalysisBundle.message("set.inspection.option.description.uncheck")) - .br().br().append(info).toFragment()); + return new IntentionPreviewInfo.Html( + new HtmlBuilder().append(AnalysisBundle.message("set.inspection.option.description.input")) + .br().br().append(info).br().toFragment()); + } else { + throw new IllegalStateException("Value of type " + myValue.getClass() + " is not supported"); + } + } + + private Object getOption(@NotNull Project project, @NotNull VirtualFile vFile) { + PsiFile file = PsiManager.getInstance(project).findFile(vFile); + if (file == null) return null; + InspectionToolWrapper tool = InspectionProfileManager.getInstance(project).getCurrentProfile().getInspectionTool(myShortName, file); + if (tool == null) return null; + InspectionProfileEntry inspection = tool.getTool(); + if (myExtractor != null) { + inspection = myExtractor.apply(inspection); + } + return inspection.getOptionController().getOption(myProperty); } - private void setOption(@NotNull Project project, @NotNull VirtualFile vFile, boolean value) { + private void setOption(@NotNull Project project, @NotNull VirtualFile vFile, Object value) { PsiFile file = PsiManager.getInstance(project).findFile(vFile); if (file == null) return; InspectionProfileModifiableModelKt.modifyAndCommitProjectProfile(project, model -> {