mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-07 22:09:38 +07:00
[java-inspections] SameErasureButDifferentMethodsFix: ModCommand
GitOrigin-RevId: 5fbc113100be4f0d0dfcbf32f97342a69b089b39
This commit is contained in:
committed by
intellij-monorepo-bot
parent
9c34f534f0
commit
3f0c4e919a
@@ -1,149 +1,73 @@
|
||||
// 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.intention.impl;
|
||||
|
||||
import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo;
|
||||
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.java.JavaBundle;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.modcommand.ActionContext;
|
||||
import com.intellij.modcommand.ModPsiUpdater;
|
||||
import com.intellij.modcommand.Presentation;
|
||||
import com.intellij.modcommand.PsiUpdateModCommandAction;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.JavaClassSupers;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.MethodSignatureUtil;
|
||||
import com.intellij.refactoring.JavaRefactoringFactory;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
// @Override void f(List<String> p); -> @Override void f(List<? super String> p);
|
||||
public class SameErasureButDifferentMethodsFix extends LocalQuickFixAndIntentionActionOnPsiElement {
|
||||
private final SmartPsiElementPointer<PsiMethod> methodPtr;
|
||||
public class SameErasureButDifferentMethodsFix extends PsiUpdateModCommandAction<PsiMethod> {
|
||||
private final SmartPsiElementPointer<PsiMethod> superMethodPtr;
|
||||
|
||||
public SameErasureButDifferentMethodsFix(@NotNull PsiMethod method, @NotNull PsiMethod superMethod) {
|
||||
super(superMethod);
|
||||
methodPtr = SmartPointerManager.getInstance(method.getProject()).createSmartPsiElementPointer(method);
|
||||
super(method);
|
||||
superMethodPtr = SmartPointerManager.createPointer(superMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
|
||||
PsiMethod method = methodPtr.getElement();
|
||||
if (method == null) {
|
||||
return IntentionPreviewInfo.EMPTY;
|
||||
}
|
||||
if (!(getStartElement() instanceof PsiMethod superMethod)) {
|
||||
return IntentionPreviewInfo.EMPTY;
|
||||
}
|
||||
List<ParameterInfoImpl> infos = getParameterInfos(superMethod, method);
|
||||
String before = getMethodDescription(method, null);
|
||||
String after = getMethodDescription(method, infos);
|
||||
if (before == null || after == null) {
|
||||
return IntentionPreviewInfo.EMPTY;
|
||||
}
|
||||
return new IntentionPreviewInfo.CustomDiff(JavaFileType.INSTANCE, before, after);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getMethodDescription(@Nullable PsiMethod method, @Nullable List<ParameterInfoImpl> infos) {
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
PsiCodeBlock body = method.getBody();
|
||||
PsiParameterList list = method.getParameterList();
|
||||
for (PsiElement child : method.getChildren()) {
|
||||
if (child == body) {
|
||||
break;
|
||||
}
|
||||
if (child == list && infos != null) {
|
||||
StringJoiner joiner = new StringJoiner(", ", "(", ")");
|
||||
for (ParameterInfoImpl info : infos) {
|
||||
joiner.add(info.getTypeText() + " " + info.getName());
|
||||
}
|
||||
builder.append(joiner);
|
||||
continue;
|
||||
}
|
||||
builder.append(child.getText());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@Nullable Editor editor,
|
||||
@NotNull PsiElement startElement,
|
||||
@NotNull PsiElement endElement) {
|
||||
if (!isAvailable(project, file, startElement, endElement)) return;
|
||||
PsiMethod superMethod = (PsiMethod)startElement;
|
||||
PsiMethod method = methodPtr.getElement();
|
||||
List<ParameterInfoImpl> infos = getParameterInfos(superMethod, method);
|
||||
if (infos == null) return;
|
||||
|
||||
var processor = JavaRefactoringFactory.getInstance(project)
|
||||
.createChangeSignatureProcessor(method, false, null, method.getName(), method.getReturnType(), infos.toArray(new ParameterInfoImpl[]{}),
|
||||
null, null, null, null);
|
||||
|
||||
processor.run();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static List<ParameterInfoImpl> getParameterInfos(PsiMethod superMethod, PsiMethod method) {
|
||||
if (method == null || !method.isValid()) return null;
|
||||
protected void invoke(@NotNull ActionContext context, @NotNull PsiMethod method, @NotNull ModPsiUpdater updater) {
|
||||
PsiMethod superMethod = superMethodPtr.getElement();
|
||||
if (superMethod == null || !superMethod.isValid()) return;
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
PsiClass superContainingClass = superMethod.getContainingClass();
|
||||
if (containingClass == null || superContainingClass == null) return null;
|
||||
if (containingClass == null || superContainingClass == null) return;
|
||||
PsiSubstitutor superSubstitutor = JavaClassSupers.getInstance()
|
||||
.getSuperClassSubstitutor(superContainingClass, containingClass, containingClass.getResolveScope(), PsiSubstitutor.EMPTY);
|
||||
if (superSubstitutor == null) return null;
|
||||
|
||||
if (superSubstitutor == null) return;
|
||||
PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
PsiParameter[] superParameters = superMethod.getParameterList().getParameters();
|
||||
if (parameters.length != superParameters.length) return null;
|
||||
List<ParameterInfoImpl> infos = new ArrayList<>(parameters.length);
|
||||
if (parameters.length != superParameters.length) return;
|
||||
updater.trackDeclaration(method);
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.project());
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
PsiParameter parameter = parameters[i];
|
||||
PsiParameter superParameter = superParameters[i];
|
||||
PsiType superParameterType = superSubstitutor.substitute(superParameter.getType());
|
||||
infos.add(ParameterInfoImpl.create(i).withName(parameter.getName()).withType(superParameterType));
|
||||
|
||||
PsiTypeElement typeElement = parameter.getTypeElement();
|
||||
if (typeElement != null && !superParameterType.equals(typeElement.getType())) {
|
||||
typeElement.replace(factory.createTypeElement(superParameterType));
|
||||
}
|
||||
}
|
||||
return infos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull PsiElement startElement,
|
||||
@NotNull PsiElement endElement) {
|
||||
PsiMethod superMethod = (PsiMethod)startElement;
|
||||
PsiMethod method = methodPtr.getElement();
|
||||
if (method == null || !method.isValid()) return false;
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
|
||||
protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiMethod method) {
|
||||
PsiMethod superMethod = superMethodPtr.getElement();
|
||||
if (superMethod == null || !superMethod.isValid()) return null;
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(context.project());
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
PsiClass superContainingClass = superMethod.getContainingClass();
|
||||
if (containingClass == null || superContainingClass == null) return false;
|
||||
if (!facade.getResolveHelper().isAccessible(superMethod, containingClass, null)) return false;
|
||||
if (containingClass == null || superContainingClass == null) return null;
|
||||
if (!facade.getResolveHelper().isAccessible(superMethod, containingClass, null)) return null;
|
||||
|
||||
MethodSignature signature = method.getSignature(PsiSubstitutor.EMPTY);
|
||||
PsiSubstitutor superSubstitutor = JavaClassSupers.getInstance()
|
||||
.getSuperClassSubstitutor(superContainingClass, containingClass, containingClass.getResolveScope(), PsiSubstitutor.EMPTY);
|
||||
if (superSubstitutor == null) return false;
|
||||
if (superSubstitutor == null) return null;
|
||||
MethodSignature superSignature = superMethod.getSignature(superSubstitutor);
|
||||
if (method.getParameterList().getParametersCount() != superMethod.getParameterList().getParametersCount()) return false;
|
||||
return !signature.equals(superSignature) && MethodSignatureUtil.areSignaturesErasureEqual(signature, superSignature);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
PsiMethod method = methodPtr.getElement();
|
||||
if (method == null || !method.isValid()) return getFamilyName();
|
||||
return JavaBundle.message("intention.text.fix.method.0.parameters.with.bounded.wildcards", method.getName());
|
||||
if (method.getParameterList().getParametersCount() != superMethod.getParameterList().getParametersCount()) return null;
|
||||
if (signature.equals(superSignature) || !MethodSignatureUtil.areSignaturesErasureEqual(signature, superSignature)) return null;
|
||||
return Presentation.of(JavaBundle.message("intention.text.fix.method.0.parameters.with.bounded.wildcards", method.getName()));
|
||||
}
|
||||
|
||||
@Nls
|
||||
@@ -152,9 +76,4 @@ public class SameErasureButDifferentMethodsFix extends LocalQuickFixAndIntention
|
||||
public String getFamilyName() {
|
||||
return JavaBundle.message("intention.family.fix.bounded.wildcards");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -955,7 +955,7 @@ public final class QuickFixFactoryImpl extends QuickFixFactory {
|
||||
@NotNull
|
||||
@Override
|
||||
public IntentionAction createSameErasureButDifferentMethodsFix(@NotNull PsiMethod method, @NotNull PsiMethod superMethod) {
|
||||
return new SameErasureButDifferentMethodsFix(method, superMethod);
|
||||
return new SameErasureButDifferentMethodsFix(method, superMethod).asIntention();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -1 +1,17 @@
|
||||
public void foo(List<? super String> s)
|
||||
// "Fix method 'foo' parameters with bounded wildcards" "true-preview"
|
||||
import java.util.List;
|
||||
|
||||
interface Xo {
|
||||
void foo(List<? super String> s);
|
||||
}
|
||||
public class ErrWarn implements Xo {
|
||||
public void foo(List<? super String> s) {
|
||||
|
||||
}
|
||||
}
|
||||
class D extends ErrWarn {
|
||||
@Override
|
||||
public void foo(List<String> s) {
|
||||
super.foo(s);
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
public void foo(List<? super String> s)
|
||||
Reference in New Issue
Block a user