IJ-CR-98117 Fixes after review

IDEA-298829

GitOrigin-RevId: 973ebc9ea23341ac96d42fe79385d6fb32679f36
This commit is contained in:
Andrey Cherkasov
2022-11-10 02:37:07 +04:00
committed by intellij-monorepo-bot
parent 3631003713
commit 8d8c2f125d
10 changed files with 135 additions and 111 deletions

View File

@@ -10,7 +10,6 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PropertyMemberType;
import org.jetbrains.annotations.Nls;
@@ -632,30 +631,4 @@ public abstract class QuickFixFactory {
*/
@NotNull
public abstract IntentionAction createDeleteFix(@NotNull PsiElement @NotNull [] elements, @NotNull @Nls String text);
/**
* @param deconstructionList deconstruction list to add the patterns to its end
* @param missingPatterns patterns to add to the end of the deconstruction list
* @return a fix that add the missing patterns to the end of the deconstruction list
*/
@NotNull
public abstract IntentionAction createAddMissingNestedPatternsFix(@NotNull PsiDeconstructionList deconstructionList,
@NotNull Collection<Pattern> missingPatterns);
public record Pattern(@NotNull String type, @NotNull String name) {
public static Pattern create(@NotNull PsiRecordComponent recordComponent, @NotNull PsiElement context) {
JavaCodeStyleManager manager = JavaCodeStyleManager.getInstance(context.getProject());
String name = manager.suggestUniqueVariableName(recordComponent.getName(), context, true);
PsiType type = recordComponent.getType();
if (type instanceof PsiClassType classType && classType.resolve() instanceof PsiTypeParameter) {
return new Pattern("var", name);
}
return new Pattern(type.getCanonicalText(), name);
}
@Override
public String toString() {
return type + " " + name;
}
}
}

View File

@@ -5,9 +5,10 @@ import com.intellij.codeInsight.daemon.JavaErrorBundle;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.quickfix.AddMissingDeconstructionComponentsFix;
import com.intellij.codeInsight.daemon.impl.quickfix.AddMissingDeconstructionComponentsFix.Pattern;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.codeInsight.intention.QuickFixFactory.Pattern;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.JavaPsiPatternUtil;
@@ -103,7 +104,7 @@ class PatternHighlightingModel {
builder.range(deconstructionList);
var missingRecordComponents = Arrays.copyOfRange(recordComponents, patternComponents.length, recordComponents.length);
var missingPatterns = ContainerUtil.map(missingRecordComponents, component -> Pattern.create(component, deconstructionList));
fix = QUICK_FIX_FACTORY.createAddMissingNestedPatternsFix(deconstructionList, missingPatterns);
fix = new AddMissingDeconstructionComponentsFix(deconstructionList, missingPatterns);
builder.registerFix(fix, null, null, null, null);
}
else {
@@ -113,9 +114,8 @@ class PatternHighlightingModel {
TextRange textRange = TextRange.create(startOffset, endOffset);
builder.range(deconstructionList, textRange);
PsiPattern[] elementsToDelete = Arrays.copyOfRange(patternComponents, recordComponents.length, patternComponents.length);
String text = QuickFixBundle.message("remove.redundant.nested.patterns.fix.text",
patternComponents.length -
recordComponents.length == 1 ? 0 : 1);
int diff = patternComponents.length - recordComponents.length;
String text = QuickFixBundle.message("remove.redundant.nested.patterns.fix.text", diff);
fix = QUICK_FIX_FACTORY.createDeleteFix(elementsToDelete, text);
builder.registerFix(fix, null, text, null, null);
}

View File

@@ -0,0 +1,74 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
public class AddMissingDeconstructionComponentsFix extends LocalQuickFixAndIntentionActionOnPsiElement {
@SafeFieldForPreview
private final @NotNull Collection<Pattern> myMissingPatterns;
public AddMissingDeconstructionComponentsFix(@NotNull PsiDeconstructionList deconstructionList,
@NotNull Collection<Pattern> missingPatterns) {
super(deconstructionList);
myMissingPatterns = missingPatterns;
}
@Override
public @NotNull String getFamilyName() {
return QuickFixBundle.message("add.missing.nested.patterns.fix.text", myMissingPatterns.size());
}
@Override
public @NotNull String getText() {
return getFamilyName();
}
@Override
public void invoke(@NotNull Project project,
@NotNull PsiFile file,
@Nullable Editor editor,
@NotNull PsiElement startElement,
@NotNull PsiElement endElement) {
PsiDeconstructionList deconstructionList = (PsiDeconstructionList)startElement;
if (deconstructionList.getParent() instanceof PsiDeconstructionPattern deconstructionPattern) {
boolean isEmptyList = deconstructionList.getDeconstructionComponents().length == 0;
String deconstructionListText = deconstructionList.getText();
String prefix = deconstructionListText.substring(0, deconstructionListText.length() - 1) + (isEmptyList ? "" : ",");
String newDeconstructionListText = StreamEx.of(myMissingPatterns).map(Pattern::toString).joining(",", prefix, ")");
PsiElementFactory factory = PsiElementFactory.getInstance(project);
String text = "o instanceof " + deconstructionPattern.getTypeElement().getText() + newDeconstructionListText;
PsiInstanceOfExpression instanceOf = (PsiInstanceOfExpression)factory.createExpressionFromText(text, null);
PsiDeconstructionPattern newPattern = (PsiDeconstructionPattern)instanceOf.getPattern();
assert newPattern != null;
deconstructionPattern.replace(newPattern);
}
}
public record Pattern(@NotNull String type, @NotNull String name) {
@Override
public String toString() {
return type + " " + name;
}
public static Pattern create(@NotNull PsiRecordComponent recordComponent, @NotNull PsiElement context) {
JavaCodeStyleManager manager = JavaCodeStyleManager.getInstance(context.getProject());
String name = manager.suggestUniqueVariableName(recordComponent.getName(), context, true);
PsiType type = recordComponent.getType();
if (type instanceof PsiClassType classType && classType.resolve() instanceof PsiTypeParameter) {
return new Pattern("var", name);
}
return new Pattern(type.getCanonicalText(), name);
}
}
}

View File

@@ -448,5 +448,5 @@ move.switch.branch.up.text=Move switch branch ''{0}'' before ''{1}''
qualify.method.call.fix=Qualify the call with ''{0}''
qualify.method.call.family=Qualify method call
remove.redundant.nested.patterns.fix.text=Remove redundant nested pattern{0, choice, 0#|1#s}
add.missing.nested.patterns.fix.text=Add missing nested pattern{0, choice, 0#|1#s}
remove.redundant.nested.patterns.fix.text=Remove redundant nested pattern{0, choice, 1#|2#s}
add.missing.nested.patterns.fix.text=Add missing nested pattern{0, choice, 1#|2#s}

View File

@@ -1,68 +0,0 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.intention.FileModifier;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.JavaPsiPatternUtil;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
public class AddMissingDeconstructionComponentsFix extends LocalQuickFixAndIntentionActionOnPsiElement {
private final @NotNull Collection<QuickFixFactory.Pattern> myMissingPatterns;
public AddMissingDeconstructionComponentsFix(@NotNull PsiDeconstructionList deconstructionList,
@NotNull Collection<QuickFixFactory.Pattern> missingPatterns) {
super(deconstructionList);
myMissingPatterns = missingPatterns;
}
@Override
public @NotNull String getText() {
return getFamilyName();
}
@Override
public @NotNull String getFamilyName() {
return QuickFixBundle.message("add.missing.nested.patterns.fix.text", myMissingPatterns.size() == 1 ? 0 : 1);
}
@Override
public void invoke(@NotNull Project project,
@NotNull PsiFile file,
@Nullable Editor editor,
@NotNull PsiElement startElement,
@NotNull PsiElement endElement) {
PsiElementFactory factory = PsiElementFactory.getInstance(project);
for (var missingPattern : myMissingPatterns) {
// record pattern is used here to handle not only patterns with explicit types, but also with 'var'
String text = "o instanceof R(" + missingPattern + ")";
PsiInstanceOfExpression instanceOf = (PsiInstanceOfExpression)factory.createExpressionFromText(text, null);
PsiDeconstructionPattern deconstructionPattern = (PsiDeconstructionPattern)instanceOf.getPattern();
assert deconstructionPattern != null;
PsiDeconstructionList list = deconstructionPattern.getDeconstructionList();
PsiPattern component = list.getDeconstructionComponents()[0];
PsiPatternVariable variable = JavaPsiPatternUtil.getPatternVariable(component);
assert variable != null;
startElement.add(component);
}
}
@Override
public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) {
PsiDeconstructionList copy = (PsiDeconstructionList)PsiTreeUtil.findSameElementInCopy(myStartElement.getElement(), target);
return copy != null ? new AddMissingDeconstructionComponentsFix(copy, myMissingPatterns) : null;
}
@Override
public boolean startInWriteAction() {
return true;
}
}

View File

@@ -5,8 +5,12 @@ import com.intellij.codeInsight.CodeInsightWorkspaceSettings;
import com.intellij.codeInsight.actions.OptimizeImportsProcessor;
import com.intellij.codeInsight.daemon.JavaErrorBundle;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.*;
import com.intellij.codeInsight.daemon.impl.analysis.*;
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx;
import com.intellij.codeInsight.daemon.impl.DaemonListeners;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.LocalInspectionsPass;
import com.intellij.codeInsight.daemon.impl.analysis.IncreaseLanguageLevelFix;
import com.intellij.codeInsight.daemon.impl.analysis.UpgradeSdkFix;
import com.intellij.codeInsight.daemon.impl.quickfix.*;
import com.intellij.codeInsight.daemon.impl.quickfix.makefinal.MakeVarEffectivelyFinalFix;
import com.intellij.codeInsight.daemon.quickFix.CreateClassOrPackageFix;
@@ -57,7 +61,10 @@ import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
public final class QuickFixFactoryImpl extends QuickFixFactory {
private static final Logger LOG = Logger.getInstance(QuickFixFactoryImpl.class);
@@ -1195,10 +1202,4 @@ public final class QuickFixFactoryImpl extends QuickFixFactory {
public @NotNull IntentionAction createDeleteFix(@NotNull PsiElement @NotNull [] elements, @NotNull @Nls String text) {
return new DeleteElementFix.DeleteMultiFix(elements, text);
}
@NotNull
@Override
public IntentionAction createAddMissingNestedPatternsFix(@NotNull PsiDeconstructionList deconstructionList, @NotNull Collection<Pattern> missingPatterns) {
return new AddMissingDeconstructionComponentsFix(deconstructionList, missingPatterns);
}
}

View File

@@ -0,0 +1,11 @@
// "Add missing nested patterns" "true-preview"
class Main {
void foo(Object obj) {
switch (obj) {
case Point(/*blah blah blah*/double x, double y, double z) -> {}
default -> {}
}
}
record Point(double x, double y, double z) {}
}

View File

@@ -0,0 +1,11 @@
// "Add missing nested patterns" "true-preview"
class Main {
void foo(Object obj) {
switch (obj) {
case Point(double x/*blah blah blah*/, double y, double z) -> {}
default -> {}
}
}
record Point(double x, double y, double z) {}
}

View File

@@ -0,0 +1,11 @@
// "Add missing nested patterns" "true-preview"
class Main {
void foo(Object obj) {
switch (obj) {
case Point(/*blah blah blah*/<caret>) -> {}
default -> {}
}
}
record Point(double x, double y, double z) {}
}

View File

@@ -0,0 +1,11 @@
// "Add missing nested patterns" "true-preview"
class Main {
void foo(Object obj) {
switch (obj) {
case Point(double x/*blah blah blah*/<caret>) -> {}
default -> {}
}
}
record Point(double x, double y, double z) {}
}