inplace change signature: delegate in template

This commit is contained in:
Anna.Kozlova
2016-11-11 20:54:11 +01:00
parent a661f20176
commit 56a13d66b9
6 changed files with 89 additions and 34 deletions
@@ -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);
@@ -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();
}
}
@@ -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
@@ -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;
}