mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 11:53:49 +07:00
introduce field: extract error expression on class level ( IDEA-41570 )
This commit is contained in:
@@ -157,6 +157,7 @@ public class CodeInsightUtil {
|
|||||||
public static PsiExpression[] findExpressionOccurrences(PsiElement scope, PsiExpression expr) {
|
public static PsiExpression[] findExpressionOccurrences(PsiElement scope, PsiExpression expr) {
|
||||||
List<PsiExpression> array = new ArrayList<PsiExpression>();
|
List<PsiExpression> array = new ArrayList<PsiExpression>();
|
||||||
addExpressionOccurrences(RefactoringUtil.unparenthesizeExpression(expr), array, scope);
|
addExpressionOccurrences(RefactoringUtil.unparenthesizeExpression(expr), array, scope);
|
||||||
|
if (!array.contains(expr)) array.add(expr);
|
||||||
return array.toArray(new PsiExpression[array.size()]);
|
return array.toArray(new PsiExpression[array.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
|
|||||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.util.Pair;
|
||||||
import com.intellij.openapi.util.Pass;
|
import com.intellij.openapi.util.Pass;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import com.intellij.openapi.wm.WindowManager;
|
import com.intellij.openapi.wm.WindowManager;
|
||||||
@@ -164,7 +165,8 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
|
|||||||
|
|
||||||
PsiElement anchor = getNormalizedAnchor(anchorElement);
|
PsiElement anchor = getNormalizedAnchor(anchorElement);
|
||||||
|
|
||||||
boolean tempDeleteSelf = false;
|
final Boolean outOfCodeBlockExtraction = selectedExpr.getUserData(ElementToWorkOn.OUT_OF_CODE_BLOCK);
|
||||||
|
boolean tempDeleteSelf = outOfCodeBlockExtraction != null;
|
||||||
if (element.getParent() instanceof PsiExpressionStatement && anchor.equals(anchorElement)) {
|
if (element.getParent() instanceof PsiExpressionStatement && anchor.equals(anchorElement)) {
|
||||||
PsiStatement statement = (PsiStatement)element.getParent();
|
PsiStatement statement = (PsiStatement)element.getParent();
|
||||||
if (statement.getParent() instanceof PsiCodeBlock) {
|
if (statement.getParent() instanceof PsiCodeBlock) {
|
||||||
@@ -252,7 +254,16 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
|
|||||||
if (expr.getParent() instanceof PsiParenthesizedExpression) {
|
if (expr.getParent() instanceof PsiParenthesizedExpression) {
|
||||||
expr = (PsiExpression)expr.getParent();
|
expr = (PsiExpression)expr.getParent();
|
||||||
}
|
}
|
||||||
if (deleteSelf) {
|
if (outOfCodeBlockExtraction != null) {
|
||||||
|
final int endOffset = selectedExpr.getUserData(ElementToWorkOn.TEXT_RANGE).getEndOffset();
|
||||||
|
PsiElement endElement = element.getContainingFile().findElementAt(endOffset);
|
||||||
|
while (true) {
|
||||||
|
final PsiElement parent = endElement.getParent();
|
||||||
|
if (parent instanceof PsiClass) break;
|
||||||
|
endElement = parent;
|
||||||
|
}
|
||||||
|
element.getParent().deleteChildRange(element, PsiTreeUtil.skipSiblingsBackward(endElement, PsiWhiteSpace.class));
|
||||||
|
} else if (deleteSelf) {
|
||||||
element.getParent().delete();
|
element.getParent().delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public class ElementToWorkOn {
|
|||||||
public static final Key<String> PREFIX = Key.create("prefix");
|
public static final Key<String> PREFIX = Key.create("prefix");
|
||||||
public static final Key<String> SUFFIX = Key.create("suffix");
|
public static final Key<String> SUFFIX = Key.create("suffix");
|
||||||
public static final Key<RangeMarker> TEXT_RANGE = Key.create("range");
|
public static final Key<RangeMarker> TEXT_RANGE = Key.create("range");
|
||||||
|
public static final Key<Boolean> OUT_OF_CODE_BLOCK= Key.create("out_of_code_block");
|
||||||
|
|
||||||
private ElementToWorkOn(PsiLocalVariable localVariable, PsiExpression expr) {
|
private ElementToWorkOn(PsiLocalVariable localVariable, PsiExpression expr) {
|
||||||
myLocalVariable = localVariable;
|
myLocalVariable = localVariable;
|
||||||
|
|||||||
@@ -199,8 +199,10 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
|||||||
if (elementAtEnd == null) return null;
|
if (elementAtEnd == null) return null;
|
||||||
|
|
||||||
PsiExpression tempExpr;
|
PsiExpression tempExpr;
|
||||||
final PsiElement elementAt = PsiTreeUtil.findCommonParent(elementAtStart, elementAtEnd);
|
PsiElement elementAt = PsiTreeUtil.findCommonParent(elementAtStart, elementAtEnd);
|
||||||
if (PsiTreeUtil.getParentOfType(elementAt, PsiExpression.class, false) == null) return null;
|
if (PsiTreeUtil.getParentOfType(elementAt, PsiExpression.class, false) == null) {
|
||||||
|
elementAt = null;
|
||||||
|
}
|
||||||
final PsiLiteralExpression literalExpression = PsiTreeUtil.getParentOfType(elementAt, PsiLiteralExpression.class);
|
final PsiLiteralExpression literalExpression = PsiTreeUtil.getParentOfType(elementAt, PsiLiteralExpression.class);
|
||||||
|
|
||||||
final PsiLiteralExpression startLiteralExpression = PsiTreeUtil.getParentOfType(elementAtStart, PsiLiteralExpression.class);
|
final PsiLiteralExpression startLiteralExpression = PsiTreeUtil.getParentOfType(elementAtStart, PsiLiteralExpression.class);
|
||||||
@@ -286,7 +288,19 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
|||||||
FileDocumentManager.getInstance().getDocument(file.getVirtualFile()).createRangeMarker(startOffset, endOffset);
|
FileDocumentManager.getInstance().getDocument(file.getVirtualFile()).createRangeMarker(startOffset, endOffset);
|
||||||
tempExpr.putUserData(ElementToWorkOn.TEXT_RANGE, rangeMarker);
|
tempExpr.putUserData(ElementToWorkOn.TEXT_RANGE, rangeMarker);
|
||||||
|
|
||||||
tempExpr.putUserData(ElementToWorkOn.PARENT, parent);
|
if (parent != null) {
|
||||||
|
tempExpr.putUserData(ElementToWorkOn.PARENT, parent);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PsiErrorElement errorElement = PsiTreeUtil.getNextSiblingOfType(elementAtStart, PsiErrorElement.class);
|
||||||
|
if (errorElement == null) {
|
||||||
|
errorElement = PsiTreeUtil.getParentOfType(elementAtStart, PsiErrorElement.class);
|
||||||
|
}
|
||||||
|
if (errorElement == null) return null;
|
||||||
|
if (!(errorElement.getParent() instanceof PsiClass)) return null;
|
||||||
|
tempExpr.putUserData(ElementToWorkOn.PARENT, errorElement);
|
||||||
|
tempExpr.putUserData(ElementToWorkOn.OUT_OF_CODE_BLOCK, Boolean.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
final String fakeInitializer = "intellijidearulezzz";
|
final String fakeInitializer = "intellijidearulezzz";
|
||||||
final int[] refIdx = new int[1];
|
final int[] refIdx = new int[1];
|
||||||
@@ -567,18 +581,21 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
|||||||
final String prefix,
|
final String prefix,
|
||||||
final String suffix,
|
final String suffix,
|
||||||
final PsiElement parent, final RangeMarker rangeMarker, int[] refIdx) {
|
final PsiElement parent, final RangeMarker rangeMarker, int[] refIdx) {
|
||||||
final String allText = parent.getContainingFile().getText();
|
String text = refText;
|
||||||
final TextRange parentRange = parent.getTextRange();
|
if (parent != null) {
|
||||||
|
final String allText = parent.getContainingFile().getText();
|
||||||
|
final TextRange parentRange = parent.getTextRange();
|
||||||
|
|
||||||
String beg = allText.substring(parentRange.getStartOffset(), rangeMarker.getStartOffset());
|
String beg = allText.substring(parentRange.getStartOffset(), rangeMarker.getStartOffset());
|
||||||
if (StringUtil.stripQuotesAroundValue(beg).trim().length() == 0 && prefix == null) beg = "";
|
if (StringUtil.stripQuotesAroundValue(beg).trim().length() == 0 && prefix == null) beg = "";
|
||||||
|
|
||||||
String end = allText.substring(rangeMarker.getEndOffset(), parentRange.getEndOffset());
|
String end = allText.substring(rangeMarker.getEndOffset(), parentRange.getEndOffset());
|
||||||
if (StringUtil.stripQuotesAroundValue(end).trim().length() == 0 && suffix == null) end = "";
|
if (StringUtil.stripQuotesAroundValue(end).trim().length() == 0 && suffix == null) end = "";
|
||||||
|
|
||||||
final String start = beg + (prefix != null ? prefix : "");
|
final String start = beg + (prefix != null ? prefix : "");
|
||||||
refIdx[0] = start.length();
|
refIdx[0] = start.length();
|
||||||
final String text = start + refText + (suffix != null ? suffix : "") + end;
|
text = start + refText + (suffix != null ? suffix : "") + end;
|
||||||
|
}
|
||||||
return JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText(text, parent);
|
return JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText(text, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -307,6 +307,7 @@ public class RefactoringUtil {
|
|||||||
|
|
||||||
public static PsiElement getParentExpressionAnchorElement(PsiElement place) {
|
public static PsiElement getParentExpressionAnchorElement(PsiElement place) {
|
||||||
PsiElement parent = place.getUserData(ElementToWorkOn.PARENT);
|
PsiElement parent = place.getUserData(ElementToWorkOn.PARENT);
|
||||||
|
if (place.getUserData(ElementToWorkOn.OUT_OF_CODE_BLOCK) != null) return parent;
|
||||||
if (parent == null) parent = place;
|
if (parent == null) parent = place;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (isExpressionAnchorElement(parent)) return parent;
|
if (isExpressionAnchorElement(parent)) return parent;
|
||||||
@@ -545,6 +546,7 @@ public class RefactoringUtil {
|
|||||||
public static PsiElement getAnchorElementForMultipleExpressions(PsiExpression[] occurrences, PsiElement scope) {
|
public static PsiElement getAnchorElementForMultipleExpressions(PsiExpression[] occurrences, PsiElement scope) {
|
||||||
PsiElement anchor = null;
|
PsiElement anchor = null;
|
||||||
for (PsiExpression occurrence : occurrences) {
|
for (PsiExpression occurrence : occurrences) {
|
||||||
|
// if (!occurrence.isPhysical()) continue;
|
||||||
if (scope != null && !PsiTreeUtil.isAncestor(scope, occurrence, false)) {
|
if (scope != null && !PsiTreeUtil.isAncestor(scope, occurrence, false)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
class Test {
|
||||||
|
public final int anInt = 2 + 2;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Test {
|
||||||
|
public final Class aClass = Class.forName(Test.class.getName);
|
||||||
|
|
||||||
|
void foo() {
|
||||||
|
Class clazz = aClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class Test {
|
||||||
|
public final int anInt = Integer.parseInt("");
|
||||||
|
|
||||||
|
void foo() {int i = anInt;}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
class Test {
|
||||||
|
public final int anInt = Integer.parseInt("");
|
||||||
|
int i = anInt;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Test {
|
||||||
|
public final Integer integer = new Integer(0);
|
||||||
|
|
||||||
|
void foo() {
|
||||||
|
Integer i = integer;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
class Test {
|
||||||
|
public final int anInt = Integer.parseInt("");
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
class Test {
|
||||||
|
2 <caret> + 2
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Test {
|
||||||
|
<selection>Class.forName(Test.class.getName)</selection>
|
||||||
|
|
||||||
|
void foo() {
|
||||||
|
Class clazz = Class.forName(Test.class.getName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
class Test {
|
||||||
|
Integer.pa<caret>rseInt("")
|
||||||
|
void foo() {int i = Integer.parseInt("");}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
class Test {
|
||||||
|
int i = Integer.parseInt("");
|
||||||
|
Integer.pa<caret>rseInt("")
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
class Test {
|
||||||
|
<selection>new Integer(0)</selection>
|
||||||
|
|
||||||
|
void foo() {
|
||||||
|
Integer i = new Integer(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
class Test {
|
||||||
|
Integer.pa<caret>rseInt("")
|
||||||
|
}
|
||||||
@@ -33,6 +33,43 @@ public class IntroduceFieldInSameClassTest extends LightCodeInsightTestCase {
|
|||||||
checkResultByFile("/refactoring/introduceField/afterOuterClass.java");
|
checkResultByFile("/refactoring/introduceField/afterOuterClass.java");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testOnClassLevelNoDuplicates() throws Exception {
|
||||||
|
configureByFile("/refactoring/introduceField/beforeOnClassLevelNoDuplicates.java");
|
||||||
|
performRefactoring(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, false);
|
||||||
|
checkResultByFile("/refactoring/introduceField/afterOnClassLevelNoDuplicates.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOnClassLevelDuplicates() throws Exception {
|
||||||
|
configureByFile("/refactoring/introduceField/beforeOnClassLevelDuplicates.java");
|
||||||
|
performRefactoring(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, false);
|
||||||
|
checkResultByFile("/refactoring/introduceField/afterOnClassLevelDuplicates.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOnClassLevelDuplicates1() throws Exception {
|
||||||
|
configureByFile("/refactoring/introduceField/beforeOnClassLevelDuplicates1.java");
|
||||||
|
performRefactoring(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, false);
|
||||||
|
checkResultByFile("/refactoring/introduceField/afterOnClassLevelDuplicates1.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOnClassLevelBinary() throws Exception {
|
||||||
|
configureByFile("/refactoring/introduceField/beforeOnClassLevelBinary.java");
|
||||||
|
performRefactoring(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, false);
|
||||||
|
checkResultByFile("/refactoring/introduceField/afterOnClassLevelBinary.java");
|
||||||
|
}
|
||||||
|
//multiple error elements on class level corresponding to the extracted fragment ------------------
|
||||||
|
public void testOnClassLevelNewExpression() throws Exception {
|
||||||
|
configureByFile("/refactoring/introduceField/beforeOnClassLevelNewExpression.java");
|
||||||
|
performRefactoring(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, false);
|
||||||
|
checkResultByFile("/refactoring/introduceField/afterOnClassLevelNewExpression.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOnClassLevelClassForName() throws Exception {
|
||||||
|
configureByFile("/refactoring/introduceField/beforeOnClassLevelClassForName.java");
|
||||||
|
performRefactoring(BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION, false);
|
||||||
|
checkResultByFile("/refactoring/introduceField/afterOnClassLevelClassForName.java");
|
||||||
|
}
|
||||||
|
//-------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
private static void performRefactoring(final BaseExpressionToFieldHandler.InitializationPlace initializationPlace, final boolean declareStatic) {
|
private static void performRefactoring(final BaseExpressionToFieldHandler.InitializationPlace initializationPlace, final boolean declareStatic) {
|
||||||
new MockIntroduceFieldHandler(initializationPlace, declareStatic).invoke(getProject(), myEditor, myFile, null);
|
new MockIntroduceFieldHandler(initializationPlace, declareStatic).invoke(getProject(), myEditor, myFile, null);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user