inplace change signature: delegate in template
authorAnna.Kozlova <anna.kozlova@jetbrains.com>
Fri, 11 Nov 2016 19:37:30 +0000 (20:37 +0100)
committerAnna.Kozlova <anna.kozlova@jetbrains.com>
Fri, 11 Nov 2016 19:54:11 +0000 (20:54 +0100)
java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefineParamsDefaultValueAction.java
java/java-impl/src/com/intellij/refactoring/changeSignature/DetectedJavaChangeInfo.java
java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java
java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java
platform/lang-impl/src/com/intellij/refactoring/changeSignature/inplace/ApplyChangeSignatureAction.java
platform/lang-impl/src/com/intellij/refactoring/changeSignature/inplace/LanguageChangeSignatureDetector.java

index 4fc0e1a235df2969d027043660031fbe3899814f..aa0f250371e0d43c03d9287cab5f740153c735a7 100644 (file)
@@ -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);
index 462de5a8c22e7d3ef700fe6b1ebee482ef3f8e6c..40142be293593d9226af592270a44f4f78533d1c 100644 (file)
  */
 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();
   }
 }
index ac7da60d2e3cf276a25c51cc5517bec8ef28dc97..8eb0542cbabd963df979a435c9b05c75b283c86a 100644 (file)
@@ -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
index f98d4739be75e07ff988ae77117a646ec659c83a..1d88043954043516d2b9fb34c02717ad52846b57 100644 (file)
@@ -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;
   }
 
 
index 1fa0b434ae86203c9b2346743736c5fcb63b2d94..bada5ebd9d130aa73083ae830f368d63627b6cd7 100644 (file)
@@ -70,7 +70,7 @@ public class ApplyChangeSignatureAction extends BaseRefactoringIntentionAction {
 
     final LanguageChangeSignatureDetector<ChangeInfo> detector = LanguageChangeSignatureDetectors.INSTANCE.forLanguage(element.getLanguage());
 
-    detector.performChange(currentInfo, initialSignature);
+    detector.performChange(currentInfo, editor, initialSignature);
   }
 
   @Override
index 82b31338c8036f51631c56c82252873f8e0b45eb..93152d71831e242d2387ecc4a9c215eb85eb94fd 100644 (file)
@@ -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<C extends ChangeInfo> {
   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);