From c862b52ae8e6e638d82da1e8a9d76c928f3875a4 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 23 May 2011 18:22:04 +0400 Subject: [PATCH] introduce new array from varargs list (IDEA-68180) --- .../IntroduceVariableBase.java | 55 ++++++++++++++++++- .../ArrayFromVarargs.after.java | 8 +++ .../introduceVariable/ArrayFromVarargs.java | 7 +++ .../introduceVariable/NoArrayFromVarargs.java | 7 +++ .../NoArrayFromVarargs1.java | 7 +++ .../refactoring/IntroduceVariableTest.java | 28 ++++++++++ 6 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/refactoring/introduceVariable/ArrayFromVarargs.after.java create mode 100644 java/java-tests/testData/refactoring/introduceVariable/ArrayFromVarargs.java create mode 100644 java/java-tests/testData/refactoring/introduceVariable/NoArrayFromVarargs.java create mode 100644 java/java-tests/testData/refactoring/introduceVariable/NoArrayFromVarargs1.java diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java index 1c8f25d357e2..acabd1c64a51 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -242,8 +242,9 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme final PsiLiteralExpression endLiteralExpression = PsiTreeUtil.getParentOfType(file.findElementAt(endOffset), PsiLiteralExpression.class); final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory(); + String text = null; try { - String text = file.getText().subSequence(startOffset, endOffset).toString(); + text = file.getText().subSequence(startOffset, endOffset).toString(); String prefix = null; String suffix = null; String stripped = text; @@ -350,12 +351,62 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme } } catch (IncorrectOperationException e) { - return null; + return createArrayCreationExpression(text, startOffset, endOffset, PsiTreeUtil.getParentOfType(elementAt, PsiMethodCallExpression.class)); } return tempExpr; } + private static PsiExpression createArrayCreationExpression(String text, int startOffset, int endOffset, PsiMethodCallExpression parent) { + if (text == null || parent == null) return null; + final String[] varargsExpressions = text.split("s*,s*"); + if (varargsExpressions.length > 1) { + final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(parent.getProject()); + final PsiMethod psiMethod = parent.resolveMethod(); + if (psiMethod == null || !psiMethod.isVarArgs()) return null; + final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + final PsiParameter varargParameter = parameters[parameters.length - 1]; + final PsiType type = varargParameter.getType(); + LOG.assertTrue(type instanceof PsiEllipsisType); + final PsiArrayType psiType = (PsiArrayType)((PsiEllipsisType)type).toArrayType(); + final PsiExpression[] args = parent.getArgumentList().getExpressions(); + final PsiSubstitutor psiSubstitutor = + JavaPsiFacade.getInstance(parent.getProject()).getResolveHelper().inferTypeArguments(psiMethod.getTypeParameters(), parameters, + args, PsiSubstitutor.EMPTY, parent, false); + + if (startOffset < args[parameters.length - 1].getTextOffset()) return null; + + final PsiFile containingFile = parent.getContainingFile(); + + PsiElement startElement = containingFile.findElementAt(startOffset); + while (startElement != null && startElement.getParent() != parent.getArgumentList()) { + startElement = startElement.getParent(); + } + if (startElement == null || startOffset > startElement.getTextOffset()) return null; + + PsiElement endElement = containingFile.findElementAt(endOffset - 1); + while (endElement != null && endElement.getParent() != parent.getArgumentList()) { + endElement = endElement.getParent(); + } + if (endElement == null || endOffset < endElement.getTextRange().getEndOffset()) return null; + + final PsiType componentType = psiSubstitutor.substitute(psiType.getComponentType()); + try { + final PsiExpression expressionFromText = + elementFactory.createExpressionFromText("new " + componentType.getCanonicalText() + "[]{" + text + "}", parent); + final RangeMarker rangeMarker = + FileDocumentManager.getInstance().getDocument(containingFile.getVirtualFile()).createRangeMarker(startOffset, endOffset); + expressionFromText.putUserData(ElementToWorkOn.TEXT_RANGE, rangeMarker); + expressionFromText.putUserData(ElementToWorkOn.PARENT, parent); + return expressionFromText; + } + catch (IncorrectOperationException e) { + return null; + } + } + return null; + } + protected boolean invokeImpl(final Project project, final PsiExpression expr, final Editor editor) { if (expr != null && expr.getParent() instanceof PsiExpressionStatement) { diff --git a/java/java-tests/testData/refactoring/introduceVariable/ArrayFromVarargs.after.java b/java/java-tests/testData/refactoring/introduceVariable/ArrayFromVarargs.after.java new file mode 100644 index 000000000000..b9edd91b37ba --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/ArrayFromVarargs.after.java @@ -0,0 +1,8 @@ +import java.util.Arrays; + +class A { + public void test() { + String[] strs = {"scnd", "third"}; + System.out.println(Arrays.asList("frst", strs, "4th")); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/ArrayFromVarargs.java b/java/java-tests/testData/refactoring/introduceVariable/ArrayFromVarargs.java new file mode 100644 index 000000000000..c53adcb8f9f9 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/ArrayFromVarargs.java @@ -0,0 +1,7 @@ +import java.util.Arrays; + +class A { + public void test() { + System.out.println(Arrays.asList("frst", "scnd", "third", "4th")); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/NoArrayFromVarargs.java b/java/java-tests/testData/refactoring/introduceVariable/NoArrayFromVarargs.java new file mode 100644 index 000000000000..78041b2b6eb1 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/NoArrayFromVarargs.java @@ -0,0 +1,7 @@ +import java.util.Arrays; + +class A { + public void test() { + System.out.println(Arrays.asList("frst", "scnd", "third", "4th")); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/NoArrayFromVarargs1.java b/java/java-tests/testData/refactoring/introduceVariable/NoArrayFromVarargs1.java new file mode 100644 index 000000000000..c1098e2fd7bb --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/NoArrayFromVarargs1.java @@ -0,0 +1,7 @@ +import java.util.Arrays; + +class A { + public void test() { + System.out.println(Arrays.asList( 2 + 3, "scnd", "third", "4th")); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java index df712f6facdb..694a1eadfaa3 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java @@ -194,6 +194,34 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { doTest(new MockIntroduceVariableHandler("str", false, false, false, "boolean")); } + public void testArrayFromVarargs() throws Exception { + doTest(new MockIntroduceVariableHandler("strs", false, false, false, "java.lang.String[]")); + } + + public void testNoArrayFromVarargs() throws Exception { + try { + doTest(new MockIntroduceVariableHandler("strs", false, false, false, "java.lang.String[]")); + } + catch (Exception e) { + assertEquals(e.getMessage(), "Error message:Cannot perform refactoring.\n" + + "Selected block should represent an expression."); + return; + } + fail("Should not be able to perform refactoring"); + } + + public void testNoArrayFromVarargs1() throws Exception { + try { + doTest(new MockIntroduceVariableHandler("strs", false, false, false, "java.lang.String[]")); + } + catch (Exception e) { + assertEquals(e.getMessage(), "Error message:Cannot perform refactoring.\n" + + "Selected block should represent an expression."); + return; + } + fail("Should not be able to perform refactoring"); + } + public void testNonExpression() throws Exception { doTest(new MockIntroduceVariableHandler("sum", true, true, false, "int")); }