mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
join declaration and assignment (IDEA-92226; IDEA-123689)
This commit is contained in:
+46
-37
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.editorActions;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
@@ -64,13 +65,51 @@ public class DeclarationJoinLinesHandler implements JoinLinesHandlerDelegate {
|
||||
}
|
||||
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory();
|
||||
final PsiExpression initializerExpression = getInitializerExpression(var, assignment);
|
||||
if (initializerExpression == null) return -1;
|
||||
|
||||
PsiExpressionStatement statement = (PsiExpressionStatement)assignment.getParent();
|
||||
|
||||
int startOffset = decl.getTextRange().getStartOffset();
|
||||
try {
|
||||
PsiDeclarationStatement newDecl = factory.createVariableDeclarationStatement(var.getName(), var.getType(), initializerExpression);
|
||||
PsiVariable newVar = (PsiVariable)newDecl.getDeclaredElements()[0];
|
||||
if (var.getModifierList().getText().length() > 0) {
|
||||
PsiUtil.setModifierProperty(newVar, PsiModifier.FINAL, true);
|
||||
}
|
||||
newVar.getModifierList().replace(var.getModifierList());
|
||||
PsiVariable variable = (PsiVariable)newDecl.getDeclaredElements()[0];
|
||||
final int offsetBeforeEQ = variable.getNameIdentifier().getTextRange().getEndOffset();
|
||||
final int offsetAfterEQ = variable.getInitializer().getTextRange().getStartOffset() + 1;
|
||||
newDecl = (PsiDeclarationStatement)CodeStyleManager.getInstance(psiManager).reformatRange(newDecl, offsetBeforeEQ, offsetAfterEQ);
|
||||
|
||||
PsiElement child = statement.getLastChild();
|
||||
while (child instanceof PsiComment || child instanceof PsiWhiteSpace) {
|
||||
child = child.getPrevSibling();
|
||||
}
|
||||
if (child != null && child.getNextSibling() != null) {
|
||||
newDecl.addRangeBefore(child.getNextSibling(), statement.getLastChild(), null);
|
||||
}
|
||||
|
||||
decl.replace(newDecl);
|
||||
statement.delete();
|
||||
return startOffset + newDecl.getTextRange().getEndOffset() - newDecl.getTextRange().getStartOffset();
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static PsiExpression getInitializerExpression(PsiLocalVariable var,
|
||||
PsiAssignmentExpression assignment) {
|
||||
PsiExpression initializerExpression;
|
||||
final IElementType originalOpSign = assignment.getOperationTokenType();
|
||||
if (originalOpSign == JavaTokenType.EQ) {
|
||||
initializerExpression = assignment.getRExpression();
|
||||
}
|
||||
else {
|
||||
if (var.getInitializer() == null) return -1;
|
||||
if (var.getInitializer() == null) return null;
|
||||
String opSign = null;
|
||||
if (originalOpSign == JavaTokenType.ANDEQ) {
|
||||
opSign = "&";
|
||||
@@ -107,46 +146,16 @@ public class DeclarationJoinLinesHandler implements JoinLinesHandlerDelegate {
|
||||
}
|
||||
|
||||
try {
|
||||
initializerExpression =
|
||||
factory.createExpressionFromText(var.getInitializer().getText() + opSign + assignment.getRExpression().getText(), var);
|
||||
initializerExpression = (PsiExpression)CodeStyleManager.getInstance(psiManager).reformat(initializerExpression);
|
||||
final Project project = var.getProject();
|
||||
final String initializerText = var.getInitializer().getText() + opSign + assignment.getRExpression().getText();
|
||||
initializerExpression = JavaPsiFacade.getElementFactory(project).createExpressionFromText(initializerText, var);
|
||||
initializerExpression = (PsiExpression)CodeStyleManager.getInstance(project).reformat(initializerExpression);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
return -1;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
PsiExpressionStatement statement = (PsiExpressionStatement)assignment.getParent();
|
||||
|
||||
int startOffset = decl.getTextRange().getStartOffset();
|
||||
try {
|
||||
PsiDeclarationStatement newDecl = factory.createVariableDeclarationStatement(var.getName(), var.getType(), initializerExpression);
|
||||
PsiVariable newVar = (PsiVariable)newDecl.getDeclaredElements()[0];
|
||||
if (var.getModifierList().getText().length() > 0) {
|
||||
PsiUtil.setModifierProperty(newVar, PsiModifier.FINAL, true);
|
||||
}
|
||||
newVar.getModifierList().replace(var.getModifierList());
|
||||
PsiVariable variable = (PsiVariable)newDecl.getDeclaredElements()[0];
|
||||
final int offsetBeforeEQ = variable.getNameIdentifier().getTextRange().getEndOffset();
|
||||
final int offsetAfterEQ = variable.getInitializer().getTextRange().getStartOffset() + 1;
|
||||
newDecl = (PsiDeclarationStatement)CodeStyleManager.getInstance(psiManager).reformatRange(newDecl, offsetBeforeEQ, offsetAfterEQ);
|
||||
|
||||
PsiElement child = statement.getLastChild();
|
||||
while (child instanceof PsiComment || child instanceof PsiWhiteSpace) {
|
||||
child = child.getPrevSibling();
|
||||
}
|
||||
if (child != null && child.getNextSibling() != null) {
|
||||
newDecl.addRangeBefore(child.getNextSibling(), statement.getLastChild(), null);
|
||||
}
|
||||
|
||||
decl.replace(newDecl);
|
||||
statement.delete();
|
||||
return startOffset + newDecl.getTextRange().getEndOffset() - newDecl.getTextRange().getStartOffset();
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
return -1;
|
||||
}
|
||||
return initializerExpression;
|
||||
}
|
||||
}
|
||||
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.
|
||||
*/
|
||||
package com.intellij.codeInsight.intention.impl;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.editorActions.DeclarationJoinLinesHandler;
|
||||
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class JoinDeclarationAndAssignmentAction extends PsiElementBaseIntentionAction {
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return CodeInsightBundle.message("intention.join.declaration.family");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
|
||||
|
||||
if (element instanceof PsiCompiledElement) return false;
|
||||
if (!element.getManager().isInProject(element)) return false;
|
||||
if (!element.getLanguage().isKindOf(JavaLanguage.INSTANCE)) return false;
|
||||
|
||||
if (getPair(element) != null) {
|
||||
setText(CodeInsightBundle.message("intention.join.declaration.text"));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Pair<PsiLocalVariable, PsiAssignmentExpression> getPair(PsiElement element) {
|
||||
PsiAssignmentExpression assignmentExpression = PsiTreeUtil.getParentOfType(element, PsiAssignmentExpression.class);
|
||||
PsiDeclarationStatement declarationStatement = PsiTreeUtil.getParentOfType(element, PsiDeclarationStatement.class);
|
||||
if (declarationStatement != null) {
|
||||
assignmentExpression = getAssignmentStatement(declarationStatement);
|
||||
} else if (assignmentExpression != null) {
|
||||
declarationStatement = getDeclarationStatement(assignmentExpression);
|
||||
}
|
||||
|
||||
if (declarationStatement != null && assignmentExpression != null) {
|
||||
final PsiExpression lExpression = assignmentExpression.getLExpression();
|
||||
final PsiExpression rExpression = assignmentExpression.getRExpression();
|
||||
if (lExpression instanceof PsiReferenceExpression && rExpression != null) {
|
||||
final PsiElement resolve = ((PsiReferenceExpression)lExpression).resolve();
|
||||
if (resolve instanceof PsiLocalVariable && resolve.getParent() == declarationStatement) {
|
||||
final PsiLocalVariable variable = (PsiLocalVariable)resolve;
|
||||
if (ReferencesSearch.search(variable, new LocalSearchScope(rExpression), false).findFirst() != null) {
|
||||
return null;
|
||||
}
|
||||
return Pair.create(variable, assignmentExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static PsiAssignmentExpression getAssignmentStatement(PsiDeclarationStatement statement) {
|
||||
final PsiElement element = PsiTreeUtil.skipSiblingsForward(statement, PsiWhiteSpace.class);
|
||||
if (element instanceof PsiExpressionStatement) {
|
||||
final PsiExpression expression = ((PsiExpressionStatement)element).getExpression();
|
||||
if (expression instanceof PsiAssignmentExpression) {
|
||||
return (PsiAssignmentExpression)expression;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static PsiDeclarationStatement getDeclarationStatement(PsiAssignmentExpression assignmentExpression) {
|
||||
final PsiElement parent = assignmentExpression.getParent();
|
||||
if (parent instanceof PsiExpressionStatement) {
|
||||
final PsiElement element = PsiTreeUtil.skipSiblingsBackward(parent, PsiWhiteSpace.class);
|
||||
if (element instanceof PsiDeclarationStatement) {
|
||||
return (PsiDeclarationStatement)element;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
|
||||
|
||||
final Pair<PsiLocalVariable, PsiAssignmentExpression> pair = getPair(element);
|
||||
final PsiLocalVariable variable = pair.getFirst();
|
||||
final PsiAssignmentExpression assignmentExpression = pair.getSecond();
|
||||
final PsiExpression initializerExpression = DeclarationJoinLinesHandler.getInitializerExpression(variable, assignmentExpression);
|
||||
variable.setInitializer(initializerExpression);
|
||||
assignmentExpression.delete();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Join declaration and assignment" "true"
|
||||
class Test {
|
||||
{
|
||||
String ss = "hello";
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Join declaration and assignment" "true"
|
||||
class Test {
|
||||
{
|
||||
String ss = "hello", a = "";
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// "Join declaration and assignment" "true"
|
||||
class Test {
|
||||
{
|
||||
String ss = "hello" + "world";
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Join declaration and assignment" "true"
|
||||
class Test {
|
||||
{
|
||||
String s<caret>s = "";
|
||||
ss = "hello";
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Join declaration and assignment" "false"
|
||||
class Test {
|
||||
{
|
||||
String s<caret>s = "";
|
||||
System.out.println(ss);
|
||||
ss = "hello";
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Join declaration and assignment" "true"
|
||||
class Test {
|
||||
{
|
||||
String s<caret>s = "", a = "";
|
||||
ss = "hello";
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Join declaration and assignment" "true"
|
||||
class Test {
|
||||
{
|
||||
String ss = "hello";
|
||||
ss +<caret>= "world";
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Join declaration and assignment" "false"
|
||||
class Test {
|
||||
{
|
||||
String ss = "hello";
|
||||
ss +<caret>= ss;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.
|
||||
*/
|
||||
package com.intellij.codeInsight.intention;
|
||||
|
||||
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
|
||||
|
||||
public class JoinDeclarationTest extends LightQuickFixParameterizedTestCase {
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/joinDeclaration";
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,6 @@
|
||||
package com.intellij.codeInsight.intention;
|
||||
|
||||
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
|
||||
import com.intellij.codeInsight.intention.impl.SplitIfAction;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||
|
||||
public class SplitDeclarationTest extends LightQuickFixParameterizedTestCase {
|
||||
|
||||
|
||||
@@ -151,7 +151,9 @@ i18nize.dialog.template.link.label=Edit I18n template
|
||||
i18nize.dialog.error.property.already.defined.message=Property ''{0}'' already exists in the file ''{1}''
|
||||
i18nize.dialog.error.property.already.defined.title=Property Already Exists
|
||||
intention.split.declaration.family=Split Declaration
|
||||
intention.join.declaration.family=Join Declaration and Assignment
|
||||
intention.split.declaration.text=Split into separate declarations
|
||||
intention.join.declaration.text=Join declaration and assignment
|
||||
intention.split.declaration.assignment.text=Split into declaration and assignment
|
||||
intention.add.override.annotation=Add '@Override' Annotation
|
||||
intention.add.override.annotation.family=Add Override Annotation
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class X {
|
||||
void f() {
|
||||
int i = 0;
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
public class X {
|
||||
void f() {
|
||||
<spot>int i;
|
||||
i = 0;</spot>
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts a local variable declaration and consequence assignment to the same variable into one declaration
|
||||
</body>
|
||||
</html>
|
||||
@@ -744,6 +744,10 @@
|
||||
<className>com.intellij.codeInsight.intention.impl.SplitDeclarationAction</className>
|
||||
<category>Declaration</category>
|
||||
</intentionAction>
|
||||
<intentionAction>
|
||||
<className>com.intellij.codeInsight.intention.impl.JoinDeclarationAndAssignmentAction</className>
|
||||
<category>Declaration</category>
|
||||
</intentionAction>
|
||||
<intentionAction>
|
||||
<className>com.intellij.codeInsight.intention.impl.PushConditionInCallAction</className>
|
||||
<category>Declaration</category>
|
||||
|
||||
Reference in New Issue
Block a user