introduce parameter: allow to introduce parameter from code block (IDEA-81166)

This commit is contained in:
Anna Kozlova
2014-12-10 16:05:56 +01:00
parent a23fdf8c97
commit dfc7e8cb61
10 changed files with 417 additions and 50 deletions
@@ -21,6 +21,7 @@ import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.AnnotatedMembersSearch;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.NullableFunction;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
@@ -43,6 +44,42 @@ public class FunctionalInterfaceSuggester {
});
}
public static Collection<? extends PsiType> suggestFunctionalInterfaces(final @NotNull PsiMethod method) {
if (method.isConstructor()) {
return Collections.emptyList();
}
return suggestFunctionalInterfaces(method, new NullableFunction<PsiClass, PsiType>() {
@Nullable
@Override
public PsiType fun(PsiClass aClass) {
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(aClass);
if (interfaceMethod != null) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
final PsiParameter[] interfaceMethodParameters = interfaceMethod.getParameterList().getParameters();
if (parameters.length != interfaceMethodParameters.length) {
return null;
}
for (int i = 0; i < interfaceMethodParameters.length; i++) {
if (!TypeConversionUtil.isAssignable(parameters[i].getType(), interfaceMethodParameters[i].getType())) {
return null;
}
}
final PsiType returnType = method.getReturnType();
if (!TypeConversionUtil.isAssignable(interfaceMethod.getReturnType(), returnType)) {
return null;
}
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(aClass.getProject());
final PsiType type = elementFactory.createType(aClass, PsiSubstitutor.EMPTY);
return type;
}
return null;
}
});
}
private static <T extends PsiElement> Collection<? extends PsiType> suggestFunctionalInterfaces(final @NotNull T element, final NullableFunction<PsiClass, PsiType> acceptanceChecker) {
final Project project = element.getProject();
final PsiClass functionalInterfaceClass = JavaPsiFacade.getInstance(project).findClass(CommonClassNames.JAVA_LANG_FUNCTIONAL_INTERFACE,
@@ -622,7 +622,7 @@ public class ExtractMethodProcessor implements MatchProvider {
final List<PsiExpression> map = ContainerUtil.map(filter, new Function<PsiStatement, PsiExpression>() {
@Override
public PsiExpression fun(PsiStatement statement) {
return ((PsiReturnStatement) statement).getReturnValue();
return ((PsiReturnStatement)statement).getReturnValue();
}
});
return map.toArray(new PsiExpression[map.size()]);
@@ -630,7 +630,7 @@ public class ExtractMethodProcessor implements MatchProvider {
private Nullness initNullness() {
if (!PsiUtil.isLanguageLevel5OrHigher(myElements[0]) || PsiUtil.resolveClassInType(myReturnType) == null) return null;
final PsiMethod emptyMethod = (PsiMethod)myTargetClass.copy().add(generateEmptyMethod(getThrownExceptions(), isStatic(), "name"));
final PsiMethod emptyMethod = (PsiMethod)myTargetClass.copy().add(generateEmptyMethod("name"));
prepareMethodBody(emptyMethod, false);
final NullableNotNullManager manager = NullableNotNullManager.getInstance(myProject);
final PsiClass nullableAnnotationClass = JavaPsiFacade.getInstance(myProject)
@@ -833,7 +833,7 @@ public class ExtractMethodProcessor implements MatchProvider {
public void doExtract() throws IncorrectOperationException {
PsiMethod newMethod = generateEmptyMethod(getThrownExceptions(), isStatic());
PsiMethod newMethod = generateEmptyMethod();
myExpression = myInputVariables.replaceWrappedReferences(myElements, myExpression);
renameInputVariables();
@@ -1239,7 +1239,7 @@ public class ExtractMethodProcessor implements MatchProvider {
return match.replace(myExtractedMethod, methodCallExpression, myOutputVariable);
}
private void deleteExtracted() throws IncorrectOperationException {
protected void deleteExtracted() throws IncorrectOperationException {
if (myEnclosingBlockStatement == null) {
myElements[0].getParent().deleteChildRange(myElements[0], myElements[myElements.length - 1]);
}
@@ -1284,20 +1284,18 @@ public class ExtractMethodProcessor implements MatchProvider {
return myReturnType;
}
private PsiMethod generateEmptyMethod(PsiClassType[] exceptions, boolean isStatic) throws IncorrectOperationException {
return generateEmptyMethod(exceptions, isStatic, myMethodName);
private PsiMethod generateEmptyMethod() throws IncorrectOperationException {
return generateEmptyMethod(myMethodName);
}
private PsiMethod generateEmptyMethod(PsiClassType[] exceptions,
boolean isStatic,
String methodName) throws IncorrectOperationException {
public PsiMethod generateEmptyMethod(String methodName) throws IncorrectOperationException {
PsiMethod newMethod;
if (myIsChainedConstructor) {
newMethod = myElementFactory.createConstructor();
}
else {
newMethod = myElementFactory.createMethod(methodName, myReturnType);
PsiUtil.setModifierProperty(newMethod, PsiModifier.STATIC, isStatic);
PsiUtil.setModifierProperty(newMethod, PsiModifier.STATIC, isStatic());
}
PsiUtil.setModifierProperty(newMethod, myMethodVisibility, true);
if (getTypeParameterList() != null) {
@@ -1336,7 +1334,7 @@ public class ExtractMethodProcessor implements MatchProvider {
}
PsiReferenceList throwsList = newMethod.getThrowsList();
for (PsiClassType exception : exceptions) {
for (PsiClassType exception : getThrownExceptions()) {
throwsList.add(JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory().createReferenceElementByType(exception));
}
@@ -38,7 +38,6 @@ import com.intellij.refactoring.JavaRefactoringSettings;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.ui.JBColor;
import com.intellij.usageView.UsageInfo;
import gnu.trove.TIntArrayList;
import gnu.trove.TIntProcedure;
import org.jetbrains.annotations.NotNull;
@@ -66,7 +65,6 @@ public class InplaceIntroduceParameterPopup extends AbstractJavaInplaceIntroduce
InplaceIntroduceParameterPopup(final Project project,
final Editor editor,
final List<UsageInfo> classMemberRefs,
final TypeSelectorManagerImpl typeSelectorManager,
final PsiExpression expr,
final PsiLocalVariable localVar,
@@ -25,12 +25,18 @@
package com.intellij.refactoring.introduceParameter;
import com.intellij.codeInsight.CodeInsightUtil;
import com.intellij.codeInsight.FunctionalInterfaceSuggester;
import com.intellij.codeInsight.completion.JavaCompletionUtil;
import com.intellij.codeInsight.navigation.NavigationUtil;
import com.intellij.ide.util.PsiClassListCellRenderer;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.*;
@@ -40,17 +46,24 @@ import com.intellij.openapi.ui.popup.JBPopupAdapter;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.SuggestedNameInfo;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.IntroduceHandlerBase;
import com.intellij.refactoring.IntroduceParameterRefactoring;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.extractMethod.AbstractExtractDialog;
import com.intellij.refactoring.extractMethod.ExtractMethodProcessor;
import com.intellij.refactoring.extractMethod.InputVariables;
import com.intellij.refactoring.extractMethod.PrepareFailedException;
import com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer;
import com.intellij.refactoring.introduceField.ElementToWorkOn;
import com.intellij.refactoring.ui.MethodCellRenderer;
@@ -58,15 +71,19 @@ import com.intellij.refactoring.ui.NameSuggestionsGenerator;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.refactoring.util.VariableData;
import com.intellij.refactoring.util.occurrences.ExpressionOccurrenceManager;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.components.JBList;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PairConsumer;
import gnu.trove.TIntArrayList;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
@@ -75,8 +92,7 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.*;
import java.util.List;
@@ -86,7 +102,7 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
private JBPopup myEnclosingMethodsPopup;
private InplaceIntroduceParameterPopup myInplaceIntroduceParameterPopup;
public void invoke(@NotNull final Project project, final Editor editor, PsiFile file, DataContext dataContext) {
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file, DataContext dataContext) {
PsiDocumentManager.getInstance(project).commitAllDocuments();
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
ElementToWorkOn.processElementToWorkOn(editor, file, REFACTORING_NAME, HelpID.INTRODUCE_PARAMETER, project, new ElementToWorkOn.ElementsProcessor<ElementToWorkOn>() {
@@ -97,7 +113,10 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
@Override
public void pass(final ElementToWorkOn elementToWorkOn) {
if (elementToWorkOn == null) return;
if (elementToWorkOn == null) {
introduceStrategy(project, editor, file);
return;
}
final PsiExpression expr = elementToWorkOn.getExpression();
final PsiLocalVariable localVar = elementToWorkOn.getLocalVariable();
@@ -173,30 +192,36 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
if (!CommonRefactoringUtil.checkReadOnlyStatus(project, method)) return false;
final Introducer introducer = new Introducer(project, expr, localVar, editor);
final boolean unitTestMode = ApplicationManager.getApplication().isUnitTestMode();
if (validEnclosingMethods.size() == 1 || unitTestMode) {
final PsiMethod methodToIntroduceParameterTo = validEnclosingMethods.get(0);
if (methodToIntroduceParameterTo.findDeepestSuperMethod() == null || unitTestMode) {
introducer.introduceParameter(methodToIntroduceParameterTo, methodToIntroduceParameterTo);
return true;
}
final AbstractInplaceIntroducer inplaceIntroducer = AbstractInplaceIntroducer.getActiveIntroducer(editor);
if (inplaceIntroducer instanceof InplaceIntroduceParameterPopup) {
final InplaceIntroduceParameterPopup introduceParameterPopup = (InplaceIntroduceParameterPopup)inplaceIntroducer;
introducer.introduceParameter(introduceParameterPopup.getMethodToIntroduceParameter(),
introduceParameterPopup.getMethodToSearchFor());
return true;
}
chooseMethodToIntroduceParameter(editor, validEnclosingMethods, introducer);
chooseMethodToIntroduceParameter(editor, validEnclosingMethods, new PairConsumer<PsiMethod, PsiMethod>() {
@Override
public void consume(PsiMethod methodToSearchIn, PsiMethod methodToSearchFor) {
introducer.introduceParameter(methodToSearchIn, methodToSearchFor);
}
});
return true;
}
private void chooseMethodToIntroduceParameter(final Editor editor,
final List<PsiMethod> validEnclosingMethods,
final Introducer introducer) {
final AbstractInplaceIntroducer inplaceIntroducer = AbstractInplaceIntroducer.getActiveIntroducer(editor);
if (inplaceIntroducer instanceof InplaceIntroduceParameterPopup) {
final InplaceIntroduceParameterPopup introduceParameterPopup = (InplaceIntroduceParameterPopup)inplaceIntroducer;
introducer.introduceParameter(introduceParameterPopup.getMethodToIntroduceParameter(),
introduceParameterPopup.getMethodToSearchFor());
return;
final PairConsumer<PsiMethod, PsiMethod> consumer) {
final boolean unitTestMode = ApplicationManager.getApplication().isUnitTestMode();
if (validEnclosingMethods.size() == 1 || unitTestMode) {
final PsiMethod methodToIntroduceParameterTo = validEnclosingMethods.get(0);
if (methodToIntroduceParameterTo.findDeepestSuperMethod() == null || unitTestMode) {
consumer.consume(methodToIntroduceParameterTo, methodToIntroduceParameterTo);
return;
}
}
final JPanel panel = new JPanel(new BorderLayout());
final JCheckBox superMethod = new JCheckBox("Refactor super method", true);
superMethod.setMnemonic('U');
@@ -235,7 +260,7 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
? methodToSearchIn.findDeepestSuperMethod() : methodToSearchIn;
Runnable runnable = new Runnable() {
public void run() {
introducer.introduceParameter(methodToSearchIn, methodToSearchFor);
consumer.consume(methodToSearchIn, methodToSearchFor);
}
};
IdeFocusManager.findInstance().doWhenFocusSettlesDown(runnable);
@@ -377,8 +402,6 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
}
public void introduceParameter(PsiMethod method, PsiMethod methodToSearchFor) {
if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, methodToSearchFor)) return;
PsiExpression[] occurences;
if (myExpr != null) {
occurences = new ExpressionOccurrenceManager(myExpr, method, null).findExpressionOccurrences();
@@ -412,15 +435,6 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
}
}
List<UsageInfo> localVars = new ArrayList<UsageInfo>();
List<UsageInfo> classMemberRefs = new ArrayList<UsageInfo>();
List<UsageInfo> params = new ArrayList<UsageInfo>();
if (myExpr != null) {
Util.analyzeExpression(myExpr, localVars, classMemberRefs, params);
}
final String propName = myLocalVar != null ? JavaCodeStyleManager
.getInstance(myProject).variableNameToPropertyName(myLocalVar.getName(), VariableKind.LOCAL_VARIABLE) : null;
@@ -432,7 +446,7 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
if (isInplaceAvailableOnDataContext && activeIntroducer == null) {
myInplaceIntroduceParameterPopup =
new InplaceIntroduceParameterPopup(myProject, myEditor, classMemberRefs,
new InplaceIntroduceParameterPopup(myProject, myEditor,
createTypeSelectorManager(occurences, initializerType),
myExpr, myLocalVar, method, methodToSearchFor, occurences,
getParamsToRemove(method, occurences),
@@ -454,6 +468,12 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
if (myEditor != null) {
RefactoringUtil.highlightAllOccurrences(myProject, occurences, myEditor);
}
final List<UsageInfo> classMemberRefs = new ArrayList<UsageInfo>();
if (myExpr != null) {
Util.analyzeExpression(myExpr, new ArrayList<UsageInfo>(), classMemberRefs, new ArrayList<UsageInfo>());
}
final IntroduceParameterDialog dialog =
new IntroduceParameterDialog(myProject, classMemberRefs, occurences, myLocalVar, myExpr,
createNameSuggestionGenerator(myExpr, propName, myProject, enteredName),
@@ -486,4 +506,184 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase {
public AbstractInplaceIntroducer getInplaceIntroducer() {
return myInplaceIntroduceParameterPopup;
}
@TestOnly
public boolean introduceStrategy(final Project project, final Editor editor, PsiFile file) {
final SelectionModel selectionModel = editor.getSelectionModel();
if (selectionModel.hasSelection()) {
final PsiElement[] elements = CodeInsightUtil
.findStatementsInRange(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
if (elements.length > 0) {
final AbstractInplaceIntroducer inplaceIntroducer = AbstractInplaceIntroducer.getActiveIntroducer(editor);
if (inplaceIntroducer instanceof InplaceIntroduceParameterPopup) {
return false;
}
final List<PsiMethod> enclosingMethods = getEnclosingMethods(Util.getContainingMethod(elements[0]));
if (enclosingMethods.isEmpty()) {
return false;
}
final MyExtractMethodProcessor processor = new MyExtractMethodProcessor(project, editor, elements);
try {
processor.prepare();
processor.showDialog();
final PsiMethod emptyMethod = processor.generateEmptyMethod("name");
final Collection<? extends PsiType> types = FunctionalInterfaceSuggester.suggestFunctionalInterfaces(emptyMethod);
if (types.isEmpty()) {
return false;
}
if (types.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) {
final PsiType next = types.iterator().next();
functionalInterfaceSelected(next, enclosingMethods, project, editor, processor);
}
else {
final Map<PsiClass, PsiType> classes = new LinkedHashMap<PsiClass, PsiType>();
for (PsiType type : types) {
classes.put(PsiUtil.resolveClassInType(type), type);
}
final PsiClass[] psiClasses = classes.keySet().toArray(new PsiClass[classes.size()]);
NavigationUtil.getPsiElementPopup(psiClasses, new PsiClassListCellRenderer(), "Choose From Applicable Functional Interfaces",
new PsiElementProcessor<PsiClass>() {
@Override
public boolean execute(@NotNull PsiClass psiClass) {
functionalInterfaceSelected(classes.get(psiClass), enclosingMethods, project, editor, processor);
return true;
}
}).showInBestPositionFor(editor);
return true;
}
return true;
}
catch (IncorrectOperationException ignore) {}
catch (PrepareFailedException ignore) {}
}
}
return false;
}
private void functionalInterfaceSelected(final PsiType selectedType,
final List<PsiMethod> enclosingMethods,
final Project project,
final Editor editor,
final MyExtractMethodProcessor processor) {
final PairConsumer<PsiMethod, PsiMethod> consumer = new PairConsumer<PsiMethod, PsiMethod>() {
@Override
public void consume(PsiMethod methodToIntroduceParameter, PsiMethod methodToSearchFor) {
introduceWrappedCodeBlockParameter(methodToIntroduceParameter, methodToSearchFor, editor, project, selectedType, processor);
}
};
chooseMethodToIntroduceParameter(editor, enclosingMethods, consumer);
}
private void introduceWrappedCodeBlockParameter(PsiMethod methodToIntroduceParameter,
PsiMethod methodToSearchFor, Editor editor,
final Project project,
final PsiType selectedType,
final MyExtractMethodProcessor processor) {
final PsiElement[] elements = processor.getElements();
final PsiElement commonParent = PsiTreeUtil.findCommonParent(elements);
final RangeMarker marker = editor.getDocument().createRangeMarker(elements[0].getTextOffset(),
elements[elements.length - 1].getTextRange().getEndOffset());
final PsiClass wrapperClass = PsiUtil.resolveClassInType(selectedType);
LOG.assertTrue(wrapperClass != null);
final Ref<String> methodCallText = new Ref<String>();
final Ref<String> methodText = new Ref<String>();
WriteCommandAction.runWriteCommandAction(project, new Runnable() {
@Override
public void run() {
final PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(wrapperClass);
LOG.assertTrue(method != null);
final String interfaceMethodName = method.getName();
processor.setMethodName(interfaceMethodName);
processor.doExtract();
final PsiMethod extractedMethod = processor.getExtractedMethod();
methodText.set(extractedMethod.getText());
final PsiMethodCallExpression methodCall = processor.getMethodCall();
methodCallText.set(methodCall.getText());
methodCall.delete();
extractedMethod.delete();
}
});
final PsiExpression expression = JavaPsiFacade.getElementFactory(project)
.createExpressionFromText("new " + wrapperClass.getQualifiedName() + "() {" + methodText.get() + "}",
methodToIntroduceParameter);
expression.putUserData(ElementToWorkOn.PARENT, commonParent);
expression.putUserData(ElementToWorkOn.SUFFIX, "." + methodCallText.get() + ";");
expression.putUserData(ElementToWorkOn.TEXT_RANGE, marker);
new Introducer(project, expression, null, editor)
.introduceParameter(methodToIntroduceParameter, methodToSearchFor);
}
private static class MyExtractMethodProcessor extends ExtractMethodProcessor {
public MyExtractMethodProcessor(Project project, Editor editor, PsiElement[] elements) {
super(project, editor, elements, null, REFACTORING_NAME, null, null);
}
@Override
protected AbstractExtractDialog createExtractMethodDialog(boolean direct) {
return new MyAbstractExtractDialog();
}
public void setMethodName(String methodName) {
myMethodName = methodName;
}
@Override
public Boolean hasDuplicates() {
return false;
}
@Override
protected void deleteExtracted() throws IncorrectOperationException {}
private class MyAbstractExtractDialog implements AbstractExtractDialog {
@Override
public String getChosenMethodName() {
return "name";
}
@Override
public VariableData[] getChosenParameters() {
final InputVariables inputVariables = getInputVariables();
return inputVariables.getInputVariables().toArray(new VariableData[inputVariables.getInputVariables().size()]);
}
@Override
public String getVisibility() {
return PsiModifier.PUBLIC;
}
@Override
public boolean isMakeStatic() {
return false;
}
@Override
public boolean isChainedConstructor() {
return false;
}
@Override
public PsiType getReturnType() {
return null;
}
@Override
public void show() {}
@Override
public boolean isOK() {
return true;
}
}
}
}
@@ -432,11 +432,11 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
final String fakeInitializer = "intellijidearulezzz";
final int[] refIdx = new int[1];
final PsiExpression toBeExpression = createReplacement(fakeInitializer, project, prefix, suffix, parent, rangeMarker, refIdx);
final PsiElement toBeExpression = createReplacement(fakeInitializer, project, prefix, suffix, parent, rangeMarker, refIdx);
toBeExpression.accept(errorsVisitor);
if (hasErrors[0]) return null;
if (literalExpression != null) {
PsiType type = toBeExpression.getType();
if (literalExpression != null && toBeExpression instanceof PsiExpression) {
PsiType type = ((PsiExpression)toBeExpression).getType();
if (type != null && !type.equals(literalExpression.getType())) {
return null;
}
@@ -1014,7 +1014,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
}
}
private static PsiExpression createReplacement(final String refText, final Project project,
private static PsiElement createReplacement(final String refText, final Project project,
final String prefix,
final String suffix,
final PsiElement parent, final RangeMarker rangeMarker, int[] refIdx) {
@@ -1035,7 +1035,8 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
refIdx[0] = start.length();
text = start + refText + (suffix != null ? suffix : "") + end;
}
return JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText(text, parent);
final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
return parent instanceof PsiStatement || parent instanceof PsiCodeBlock ? factory.createStatementFromText(text, parent) : factory.createExpressionFromText(text, parent);
}
private boolean parentStatementNotFound(final Project project, Editor editor) {
@@ -0,0 +1,18 @@
import java.util.function.IntConsumer;
class Test {
void bar() {
foo(1, new java.util.function.IntConsumer() {
public void accept(int i) {
System.out.println(i);
System.out.println(i);
}
});
}
void foo(int i, IntConsumer anObject){
anObject.accept(i);
}
}
@@ -0,0 +1,16 @@
class Test {
void bar() {
foo(new Runnable() {
public void run() {
System.out.println("");
System.out.println("");
}
});
}
void foo(Runnable anObject){
anObject.run();
}
}
@@ -0,0 +1,12 @@
class Test {
void bar() {
foo(1);
}
void foo(int i) {
<selection>
System.out.println(i);
System.out.println(i);
</selection>
}
}
@@ -0,0 +1,12 @@
class Test {
void bar() {
foo();
}
void foo() {
<selection>
System.out.println("");
System.out.println("");
</selection>
}
}
@@ -0,0 +1,75 @@
/*
* 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.refactoring;
import com.intellij.JavaTestUtil;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.refactoring.introduceParameter.IntroduceParameterHandler;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.annotations.NotNull;
@TestDataPath("$CONTENT_ROOT/testData")
public class IntroduceFunctionalParameterTest extends LightRefactoringTestCase {
public void testSampleRunnable() throws Exception {
doTest(null);
}
public void testIntConsumer() throws Exception {
doTest(null);
}
@NotNull
@Override
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath();
}
@Override
protected LanguageLevel getLanguageLevel() {
return LanguageLevel.JDK_1_8;
}
@Override
protected Sdk getProjectJDK() {
return IdeaTestUtil.getMockJdk18();
}
private void doTest(String conflict) {
boolean enabled = true;
try {
configureByFile("/refactoring/introduceFunctionalParameter/before" + getTestName(false) + ".java");
enabled = myEditor.getSettings().isVariableInplaceRenameEnabled();
myEditor.getSettings().setVariableInplaceRenameEnabled(false);
new IntroduceParameterHandler().introduceStrategy(getProject(), getEditor(), getFile());
checkResultByFile("/refactoring/introduceFunctionalParameter/after" + getTestName(false) + ".java");
if (conflict != null) {
fail("Conflict expected");
}
}
catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
if (conflict == null) {
throw e;
}
assertEquals(conflict, e.getMessage());
} finally {
myEditor.getSettings().setVariableInplaceRenameEnabled(enabled);
}
}
}