diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefineParamsDefaultValueAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefineParamsDefaultValueAction.java index 4fc0e1a235df..aa0f250371e0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefineParamsDefaultValueAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefineParamsDefaultValueAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -41,6 +41,7 @@ import com.intellij.psi.util.PsiUtil; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -115,7 +116,7 @@ public class DefineParamsDefaultValueAction extends PsiElementBaseIntentionActio Runnable runnable = () -> { final PsiMethod prototype = (PsiMethod)containingClass.addBefore(methodPrototype, method); RefactoringUtil.fixJavadocsForParams(prototype, new HashSet<>(Arrays.asList(prototype.getParameterList().getParameters()))); - TemplateBuilderImpl builder = new TemplateBuilderImpl(prototype); + PsiCodeBlock body = prototype.getBody(); final String callArgs = @@ -135,29 +136,19 @@ public class DefineParamsDefaultValueAction extends PsiElementBaseIntentionActio body.add(JavaPsiFacade.getElementFactory(project).createStatementFromText(methodCall + callArgs, method)); body = (PsiCodeBlock)CodeStyleManager.getInstance(project).reformat(body); final PsiStatement stmt = body.getStatements()[0]; - PsiExpression expr = null; + final PsiExpression expr; if (stmt instanceof PsiReturnStatement) { expr = ((PsiReturnStatement)stmt).getReturnValue(); } else if (stmt instanceof PsiExpressionStatement) { expr = ((PsiExpressionStatement)stmt).getExpression(); } + else { + expr = null; + } if (expr instanceof PsiMethodCallExpression) { - PsiMethodCallExpression methodCallExp = (PsiMethodCallExpression)expr; - RangeMarker rangeMarker = editor.getDocument().createRangeMarker(prototype.getTextRange()); - for (PsiParameter parameter : parameters) { - final PsiExpression exprToBeDefault = - methodCallExp.getArgumentList().getExpressions()[method.getParameterList().getParameterIndex(parameter)]; - builder.replaceElement(exprToBeDefault, new TextExpression("")); - } - Template template = builder.buildTemplate(); - editor.getCaretModel().moveToOffset(rangeMarker.getStartOffset()); - - PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); - editor.getDocument().deleteString(rangeMarker.getStartOffset(), rangeMarker.getEndOffset()); - - rangeMarker.dispose(); - - CreateFromUsageBaseFix.startTemplate(editor, template, project); + PsiExpression[] args = ((PsiMethodCallExpression)expr).getArgumentList().getExpressions(); + PsiExpression[] toDefaults = ContainerUtil.map2Array(parameters, PsiExpression.class, (parameter -> args[method.getParameterList().getParameterIndex(parameter)])); + startTemplate(project, editor, toDefaults, prototype); } }; if (startInWriteAction()) { @@ -167,6 +158,26 @@ public class DefineParamsDefaultValueAction extends PsiElementBaseIntentionActio } } + public static void startTemplate(@NotNull Project project, + Editor editor, + PsiExpression[] argsToBeDelegated, + PsiMethod delegateMethod) { + TemplateBuilderImpl builder = new TemplateBuilderImpl(delegateMethod); + RangeMarker rangeMarker = editor.getDocument().createRangeMarker(delegateMethod.getTextRange()); + for (final PsiExpression exprToBeDefault : argsToBeDelegated) { + builder.replaceElement(exprToBeDefault, new TextExpression("")); + } + Template template = builder.buildTemplate(); + editor.getCaretModel().moveToOffset(rangeMarker.getStartOffset()); + + PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); + editor.getDocument().deleteString(rangeMarker.getStartOffset(), rangeMarker.getEndOffset()); + + rangeMarker.dispose(); + + CreateFromUsageBaseFix.startTemplate(editor, template, project); + } + @Nullable protected PsiParameter[] getParams(PsiElement element) { final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class); diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/DetectedJavaChangeInfo.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/DetectedJavaChangeInfo.java index 462de5a8c22e..40142be29359 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/DetectedJavaChangeInfo.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/DetectedJavaChangeInfo.java @@ -15,10 +15,13 @@ */ package com.intellij.refactoring.changeSignature; +import com.intellij.codeInsight.daemon.impl.quickfix.DefineParamsDefaultValueAction; import com.intellij.lang.findUsages.DescriptiveNameUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; @@ -28,11 +31,13 @@ import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.changeSignature.inplace.InplaceChangeSignature; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.usageView.UsageInfo; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.VisibilityUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -174,7 +179,7 @@ class DetectedJavaChangeInfo extends JavaChangeInfoImpl { getNewReturnType(), (ParameterInfoImpl[])getNewParameters(), getNewExceptions(), getNewName(), - method.getName(), false) { + method.getName(), isGenerateDelegate()) { @Override protected void fillOldParams(PsiMethod method) { super.fillOldParams(method); @@ -250,11 +255,11 @@ class DetectedJavaChangeInfo extends JavaChangeInfoImpl { return true; } - boolean perform(ChangeInfo initialChangeInfo, final String oldText, boolean silently) { + void perform(final String oldText, Editor editor, boolean silently) { final PsiMethod method = getSuperMethod(); - Project project = initialChangeInfo.getMethod().getProject(); - final PsiMethod currentMethod = (PsiMethod)initialChangeInfo.getMethod(); + Project project = getMethod().getProject(); + final PsiMethod currentMethod = getMethod(); final TextRange signatureRange = JavaChangeSignatureDetector.getSignatureRange(currentMethod); final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); final Document document = documentManager.getDocument(currentMethod.getContainingFile()); @@ -262,10 +267,40 @@ class DetectedJavaChangeInfo extends JavaChangeInfoImpl { final String currentSignature = currentMethod.getContainingFile().getText().substring(signatureRange.getStartOffset(), signatureRange.getEndOffset()); InplaceChangeSignature.temporallyRevertChanges(JavaChangeSignatureDetector.getSignatureRange(currentMethod), document, oldText, project); + PsiMethod prototype; + if (isGenerateDelegate()) { + for (JavaParameterInfo info : getNewParameters()) { + if (info.getOldIndex() == -1) { + ((ParameterInfoImpl)info).setDefaultValue("null"); //to be replaced with template expr + } + } + prototype = JavaChangeSignatureUsageProcessor.generateDelegatePrototype(this); + } + else { + prototype = null; + } createChangeSignatureProcessor(method).run(); - InplaceChangeSignature - .temporallyRevertChanges(JavaChangeSignatureDetector.getSignatureRange(currentMethod), document, currentSignature, project); - return true; + InplaceChangeSignature.temporallyRevertChanges(JavaChangeSignatureDetector.getSignatureRange(currentMethod), document, currentSignature, project); + if (prototype != null) { + WriteCommandAction.runWriteCommandAction(project, "Delegate", null, () -> { + PsiMethod delegate = currentMethod.getContainingClass().findMethodBySignature(prototype, false); + PsiExpression expression = delegate != null ? LambdaUtil.extractSingleExpressionFromBody(delegate.getBody()) : null; + if (expression instanceof PsiMethodCallExpression) { + + PsiExpression[] expressions = ((PsiMethodCallExpression)expression).getArgumentList().getExpressions(); + JavaParameterInfo[] parameters = getNewParameters(); + PsiExpression[] toBeDefault = + Arrays.stream(parameters) + .filter(param -> param.getOldIndex() == -1) + .map(info -> { + int i = ArrayUtil.find(parameters, info); + return expressions[i]; + }).toArray(PsiExpression[]::new); + DefineParamsDefaultValueAction.startTemplate(project, editor, toBeDefault, delegate); + } + }); + } + return; } final JavaMethodDescriptor descriptor = new JavaMethodDescriptor(currentMethod) { @Override @@ -291,6 +326,6 @@ class DetectedJavaChangeInfo extends JavaChangeInfoImpl { super.invokeRefactoring(processor); } }; - return dialog.showAndGet(); + dialog.showAndGet(); } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java index ac7da60d2e3c..8eb0542cbabd 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java @@ -17,6 +17,7 @@ package com.intellij.refactoring.changeSignature; import com.intellij.ide.highlighter.JavaFileType; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; @@ -45,8 +46,8 @@ public class JavaChangeSignatureDetector implements LanguageChangeSignatureDetec } @Override - public void performChange(final DetectedJavaChangeInfo changeInfo, @NotNull final String oldText) { - changeInfo.perform(changeInfo, oldText, true); + public void performChange(final DetectedJavaChangeInfo changeInfo, Editor editor, @NotNull final String oldText) { + changeInfo.perform(oldText, editor, true); } @Override diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index f98d4739be75..1d8804395404 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -705,8 +705,15 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } public static void generateDelegate(JavaChangeInfo changeInfo) throws IncorrectOperationException { + final PsiMethod delegate = generateDelegatePrototype(changeInfo); + PsiClass targetClass = changeInfo.getMethod().getContainingClass(); + LOG.assertTrue(targetClass != null); + targetClass.addBefore(delegate, changeInfo.getMethod()); + } + + public static PsiMethod generateDelegatePrototype(JavaChangeInfo changeInfo) { final PsiMethod delegate = (PsiMethod)changeInfo.getMethod().copy(); - final PsiClass targetClass = changeInfo.getMethod().getContainingClass(); + PsiClass targetClass = changeInfo.getMethod().getContainingClass(); LOG.assertTrue(targetClass != null); if (targetClass.isInterface() && delegate.getBody() == null) { delegate.getModifierList().setModifierProperty(PsiModifier.DEFAULT, true); @@ -715,7 +722,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr ChangeSignatureProcessor.makeEmptyBody(factory, delegate); final PsiCallExpression callExpression = ChangeSignatureProcessor.addDelegatingCallTemplate(delegate, changeInfo.getNewName()); addDelegateArguments(changeInfo, factory, callExpression); - targetClass.addBefore(delegate, changeInfo.getMethod()); + return delegate; } diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/inplace/ApplyChangeSignatureAction.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/inplace/ApplyChangeSignatureAction.java index 1fa0b434ae86..bada5ebd9d13 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/inplace/ApplyChangeSignatureAction.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/inplace/ApplyChangeSignatureAction.java @@ -70,7 +70,7 @@ public class ApplyChangeSignatureAction extends BaseRefactoringIntentionAction { final LanguageChangeSignatureDetector detector = LanguageChangeSignatureDetectors.INSTANCE.forLanguage(element.getLanguage()); - detector.performChange(currentInfo, initialSignature); + detector.performChange(currentInfo, editor, initialSignature); } @Override diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/inplace/LanguageChangeSignatureDetector.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/inplace/LanguageChangeSignatureDetector.java index 82b31338c803..93152d71831e 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/inplace/LanguageChangeSignatureDetector.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/inplace/LanguageChangeSignatureDetector.java @@ -15,6 +15,7 @@ */ package com.intellij.refactoring.changeSignature.inplace; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; @@ -34,7 +35,7 @@ public interface LanguageChangeSignatureDetector { boolean ignoreChanges(PsiElement element); @Nullable C createNextChangeInfo(String signature, @NotNull C currentInfo, boolean delegate); - void performChange(C changeInfo, @NotNull String oldText); + void performChange(C changeInfo, Editor editor, @NotNull String oldText); boolean isChangeSignatureAvailableOnElement(@NotNull PsiElement element, C currentInfo);