mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +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) {
|
||||
List<PsiExpression> array = new ArrayList<PsiExpression>();
|
||||
addExpressionOccurrences(RefactoringUtil.unparenthesizeExpression(expr), array, scope);
|
||||
if (!array.contains(expr)) array.add(expr);
|
||||
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.TextAttributes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Pass;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
@@ -164,7 +165,8 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
|
||||
|
||||
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)) {
|
||||
PsiStatement statement = (PsiStatement)element.getParent();
|
||||
if (statement.getParent() instanceof PsiCodeBlock) {
|
||||
@@ -252,7 +254,16 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
|
||||
if (expr.getParent() instanceof PsiParenthesizedExpression) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ public class ElementToWorkOn {
|
||||
public static final Key<String> PREFIX = Key.create("prefix");
|
||||
public static final Key<String> SUFFIX = Key.create("suffix");
|
||||
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) {
|
||||
myLocalVariable = localVariable;
|
||||
|
||||
@@ -199,8 +199,10 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
if (elementAtEnd == null) return null;
|
||||
|
||||
PsiExpression tempExpr;
|
||||
final PsiElement elementAt = PsiTreeUtil.findCommonParent(elementAtStart, elementAtEnd);
|
||||
if (PsiTreeUtil.getParentOfType(elementAt, PsiExpression.class, false) == null) return null;
|
||||
PsiElement elementAt = PsiTreeUtil.findCommonParent(elementAtStart, elementAtEnd);
|
||||
if (PsiTreeUtil.getParentOfType(elementAt, PsiExpression.class, false) == null) {
|
||||
elementAt = null;
|
||||
}
|
||||
final PsiLiteralExpression literalExpression = PsiTreeUtil.getParentOfType(elementAt, 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);
|
||||
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 int[] refIdx = new int[1];
|
||||
@@ -567,18 +581,21 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme
|
||||
final String prefix,
|
||||
final String suffix,
|
||||
final PsiElement parent, final RangeMarker rangeMarker, int[] refIdx) {
|
||||
final String allText = parent.getContainingFile().getText();
|
||||
final TextRange parentRange = parent.getTextRange();
|
||||
String text = refText;
|
||||
if (parent != null) {
|
||||
final String allText = parent.getContainingFile().getText();
|
||||
final TextRange parentRange = parent.getTextRange();
|
||||
|
||||
String beg = allText.substring(parentRange.getStartOffset(), rangeMarker.getStartOffset());
|
||||
if (StringUtil.stripQuotesAroundValue(beg).trim().length() == 0 && prefix == null) beg = "";
|
||||
String beg = allText.substring(parentRange.getStartOffset(), rangeMarker.getStartOffset());
|
||||
if (StringUtil.stripQuotesAroundValue(beg).trim().length() == 0 && prefix == null) beg = "";
|
||||
|
||||
String end = allText.substring(rangeMarker.getEndOffset(), parentRange.getEndOffset());
|
||||
if (StringUtil.stripQuotesAroundValue(end).trim().length() == 0 && suffix == null) end = "";
|
||||
String end = allText.substring(rangeMarker.getEndOffset(), parentRange.getEndOffset());
|
||||
if (StringUtil.stripQuotesAroundValue(end).trim().length() == 0 && suffix == null) end = "";
|
||||
|
||||
final String start = beg + (prefix != null ? prefix : "");
|
||||
refIdx[0] = start.length();
|
||||
final String text = start + refText + (suffix != null ? suffix : "") + end;
|
||||
final String start = beg + (prefix != null ? prefix : "");
|
||||
refIdx[0] = start.length();
|
||||
text = start + refText + (suffix != null ? suffix : "") + end;
|
||||
}
|
||||
return JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText(text, parent);
|
||||
}
|
||||
|
||||
|
||||
@@ -307,6 +307,7 @@ public class RefactoringUtil {
|
||||
|
||||
public static PsiElement getParentExpressionAnchorElement(PsiElement place) {
|
||||
PsiElement parent = place.getUserData(ElementToWorkOn.PARENT);
|
||||
if (place.getUserData(ElementToWorkOn.OUT_OF_CODE_BLOCK) != null) return parent;
|
||||
if (parent == null) parent = place;
|
||||
while (true) {
|
||||
if (isExpressionAnchorElement(parent)) return parent;
|
||||
@@ -545,6 +546,7 @@ public class RefactoringUtil {
|
||||
public static PsiElement getAnchorElementForMultipleExpressions(PsiExpression[] occurrences, PsiElement scope) {
|
||||
PsiElement anchor = null;
|
||||
for (PsiExpression occurrence : occurrences) {
|
||||
// if (!occurrence.isPhysical()) continue;
|
||||
if (scope != null && !PsiTreeUtil.isAncestor(scope, occurrence, false)) {
|
||||
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");
|
||||
}
|
||||
|
||||
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) {
|
||||
new MockIntroduceFieldHandler(initializationPlace, declareStatic).invoke(getProject(), myEditor, myFile, null);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user