mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-inspections] DeferFinalAssignmentFix: ModCommand
GitOrigin-RevId: b71aaf9098c2d60e69b63c18408845492918dc65
This commit is contained in:
committed by
intellij-monorepo-bot
parent
090e1b85cf
commit
001d26930f
+27
-84
@@ -1,59 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2023 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.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
|
||||
import com.intellij.codeInspection.PsiUpdateModCommandAction;
|
||||
import com.intellij.modcommand.ModPsiUpdater;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.controlFlow.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.ig.psiutils.VariableNameGenerator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class DeferFinalAssignmentFix implements IntentionAction {
|
||||
public class DeferFinalAssignmentFix extends PsiUpdateModCommandAction<PsiVariable> {
|
||||
private static final Logger LOG = Logger.getInstance(DeferFinalAssignmentFix.class);
|
||||
|
||||
private final PsiVariable variable;
|
||||
private final PsiReferenceExpression expression;
|
||||
|
||||
public DeferFinalAssignmentFix(@NotNull PsiVariable variable, @NotNull PsiReferenceExpression expression) {
|
||||
this.variable = variable;
|
||||
super(variable);
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) {
|
||||
if (variable.getContainingFile() != expression.getContainingFile()) return null;
|
||||
return new DeferFinalAssignmentFix(PsiTreeUtil.findSameElementInCopy(variable, target),
|
||||
PsiTreeUtil.findSameElementInCopy(expression, target));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
@@ -61,33 +37,24 @@ public class DeferFinalAssignmentFix implements IntentionAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return QuickFixBundle.message("defer.final.assignment.with.temp.text", variable.getName());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement getElementToMakeWritable(@NotNull PsiFile currentFile) {
|
||||
return variable.getContainingFile();
|
||||
protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiVariable variable) {
|
||||
boolean available = expression.isValid() && !(variable instanceof PsiParameter) && !(variable instanceof ImplicitVariable);
|
||||
return available ? Presentation.of(QuickFixBundle.message("defer.final.assignment.with.temp.text", variable.getName())) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
if (variable instanceof PsiField) {
|
||||
deferField((PsiField)variable);
|
||||
protected void invoke(@NotNull ActionContext context, @NotNull PsiVariable variable, @NotNull ModPsiUpdater updater) {
|
||||
if (variable instanceof PsiField field) {
|
||||
PsiCodeBlock codeBlock = getEnclosingCodeBlock(field, updater.getWritable(expression));
|
||||
if (codeBlock == null) return;
|
||||
deferVariable(codeBlock, variable, null, updater);
|
||||
}
|
||||
else {
|
||||
deferLocalVariable((PsiLocalVariable)variable);
|
||||
PsiElement outerCodeBlock = PsiUtil.getVariableCodeBlock(variable, null);
|
||||
deferVariable(outerCodeBlock, variable, variable.getParent(), updater);
|
||||
}
|
||||
}
|
||||
|
||||
private void deferField(PsiField field) throws IncorrectOperationException {
|
||||
PsiCodeBlock codeBlock = getEnclosingCodeBlock(field, expression);
|
||||
if (codeBlock == null) return;
|
||||
deferVariable(codeBlock, field, null);
|
||||
}
|
||||
|
||||
private static PsiCodeBlock getEnclosingCodeBlock(PsiField field, PsiElement element) {
|
||||
PsiClass aClass = field.getContainingClass();
|
||||
if (aClass == null) return null;
|
||||
@@ -107,19 +74,20 @@ public class DeferFinalAssignmentFix implements IntentionAction {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void deferLocalVariable(PsiLocalVariable variable) throws IncorrectOperationException {
|
||||
PsiElement outerCodeBlock = PsiUtil.getVariableCodeBlock(variable, null);
|
||||
deferVariable(outerCodeBlock, variable, variable.getParent());
|
||||
}
|
||||
|
||||
private static void deferVariable(PsiElement outerCodeBlock, PsiVariable variable, PsiElement tempDeclarationAnchor) throws IncorrectOperationException {
|
||||
private static void deferVariable(@Nullable PsiElement outerCodeBlock,
|
||||
@NotNull PsiVariable variable,
|
||||
@Nullable PsiElement tempDeclarationAnchor,
|
||||
@NotNull ModPsiUpdater updater) throws IncorrectOperationException {
|
||||
if (outerCodeBlock == null) return;
|
||||
List<PsiReferenceExpression> outerReferences = new ArrayList<>();
|
||||
collectReferences(outerCodeBlock, variable, outerReferences);
|
||||
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(variable.getProject());
|
||||
Project project = variable.getProject();
|
||||
String tempName = suggestNewName(project, variable);
|
||||
List<String> names =
|
||||
new VariableNameGenerator(outerCodeBlock, VariableKind.LOCAL_VARIABLE).byName(variable.getName() + "1").byType(variable.getType())
|
||||
.generateAll(true);
|
||||
String tempName = names.get(0);
|
||||
PsiDeclarationStatement tempVariableDeclaration = factory.createVariableDeclarationStatement(tempName, variable.getType(), null);
|
||||
|
||||
ControlFlow controlFlow;
|
||||
@@ -149,9 +117,10 @@ public class DeferFinalAssignmentFix implements IntentionAction {
|
||||
PsiStatement finalAssignment = factory.createStatementFromText(writeReference.getText()+" = "+tempName+";", outerCodeBlock);
|
||||
if (!insertToDefinitelyReachedPlace(outerCodeBlock, finalAssignment, controlFlow, minOffset, outerReferences)) return;
|
||||
|
||||
outerCodeBlock.addAfter(tempVariableDeclaration, tempDeclarationAnchor);
|
||||
tempVariableDeclaration = (PsiDeclarationStatement)outerCodeBlock.addAfter(tempVariableDeclaration, tempDeclarationAnchor);
|
||||
|
||||
replaceReferences(outerReferences, factory.createExpressionFromText(tempName, outerCodeBlock));
|
||||
updater.rename(((PsiVariable)tempVariableDeclaration.getDeclaredElements()[0]), names);
|
||||
}
|
||||
|
||||
|
||||
@@ -198,30 +167,4 @@ public class DeferFinalAssignmentFix implements IntentionAction {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String suggestNewName(Project project, PsiVariable variable) {
|
||||
// new name should not conflict with another variable at the variable declaration level and usage level
|
||||
String name = Objects.requireNonNull(variable.getName());
|
||||
// trim last digit to suggest variable names like i1, i2, i3...
|
||||
if (name.length() > 1 && Character.isDigit(name.charAt(name.length()-1))) {
|
||||
name = name.substring(0,name.length()-1);
|
||||
}
|
||||
return JavaCodeStyleManager.getInstance(project).suggestUniqueVariableName(name, variable, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
return
|
||||
variable.isValid() &&
|
||||
!(variable instanceof PsiParameter) &&
|
||||
!(variable instanceof ImplicitVariable) &&
|
||||
expression.isValid() &&
|
||||
BaseIntentionAction.canModify(variable)
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -588,7 +588,7 @@ public final class QuickFixFactoryImpl extends QuickFixFactory {
|
||||
@NotNull
|
||||
@Override
|
||||
public IntentionAction createDeferFinalAssignmentFix(@NotNull PsiVariable variable, @NotNull PsiReferenceExpression expression) {
|
||||
return new DeferFinalAssignmentFix(variable, expression);
|
||||
return new DeferFinalAssignmentFix(variable, expression).asIntention();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+2
-2
@@ -4,11 +4,11 @@ import java.io.*;
|
||||
class a {
|
||||
void f(InputStream in) {
|
||||
final int n;
|
||||
int n1;
|
||||
int n1<caret>;
|
||||
try {
|
||||
n1 = in.read();
|
||||
} catch (IOException e) {
|
||||
<caret>n1 = -1;
|
||||
n1 = -1;
|
||||
}
|
||||
n = n1;
|
||||
int y = 4;
|
||||
|
||||
+2
-2
@@ -4,10 +4,10 @@ import java.io.*;
|
||||
class a {
|
||||
void f(InputStream in) {
|
||||
final int n;
|
||||
int n1;
|
||||
int n1<caret>;
|
||||
if (in==null) {
|
||||
n1 = 2;
|
||||
<caret>n1 = 2;
|
||||
n1 = 2;
|
||||
}
|
||||
else {
|
||||
n1 =4;
|
||||
|
||||
+2
-2
@@ -4,10 +4,10 @@ import java.io.*;
|
||||
class a {
|
||||
void f(InputStream in) {
|
||||
final int n;
|
||||
int n1;
|
||||
int n1<caret>;
|
||||
if (in==null) {
|
||||
n1 = 2;
|
||||
<caret>n1 = 2;
|
||||
n1 = 2;
|
||||
int h = n1;
|
||||
}
|
||||
else {
|
||||
|
||||
+2
-2
@@ -4,10 +4,10 @@ import java.io.*;
|
||||
class a {
|
||||
final int n;
|
||||
a(InputStream in) {
|
||||
int n1;
|
||||
int n1<caret>;
|
||||
if (in==null) {
|
||||
n1 = 2;
|
||||
<caret>n1 = 2;
|
||||
n1 = 2;
|
||||
int h = n1;
|
||||
}
|
||||
else {
|
||||
|
||||
+2
-2
@@ -4,9 +4,9 @@ import java.io.*;
|
||||
class a {
|
||||
void f(int k) {
|
||||
final int i;
|
||||
int i1;
|
||||
int i1<caret>;
|
||||
i1 = 4;
|
||||
i1 = 4;
|
||||
<caret>i1 = 4;
|
||||
i = i1;
|
||||
f(i);
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,9 +4,9 @@ import java.io.*;
|
||||
class a {
|
||||
final int n;
|
||||
{
|
||||
int n1;
|
||||
int n1<caret>;
|
||||
n1 =3;
|
||||
n1 =3;
|
||||
<caret>n1 =3;
|
||||
n = n1;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,9 +4,9 @@ import java.io.*;
|
||||
class a {
|
||||
final int n;
|
||||
a(int n) {
|
||||
int n1;
|
||||
int n1<caret>;
|
||||
n1 =n;
|
||||
n1 =n;
|
||||
<caret>n1 =n;
|
||||
this.n = n1;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -4,11 +4,11 @@ import java.io.*;
|
||||
class a {
|
||||
void f(InputStream in) {
|
||||
final int n;
|
||||
int n1;
|
||||
int n1<caret>;
|
||||
try {
|
||||
n1 = in.read();
|
||||
} catch (IOException e) {
|
||||
<caret>n1 = -1;
|
||||
n1 = -1;
|
||||
f(in);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user