update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / refactoring / extractMethod / ExtractMethodUtil.java
blob2bf67e2c712f10e1c8bca69a5fe4df2f91cbd0c7
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.refactoring.extractMethod;
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.openapi.util.Key;
20 import com.intellij.psi.*;
21 import com.intellij.psi.search.SearchScope;
22 import com.intellij.psi.search.searches.ClassInheritorsSearch;
23 import com.intellij.psi.search.searches.ReferencesSearch;
24 import com.intellij.psi.util.PsiTreeUtil;
25 import com.intellij.psi.util.RedundantCastUtil;
26 import com.intellij.util.IncorrectOperationException;
27 import com.intellij.util.Processor;
28 import com.intellij.util.containers.HashMap;
30 import java.util.Map;
32 /**
33 * @author ven
35 public class ExtractMethodUtil {
36 private static final Key<PsiMethod> RESOLVE_TARGET_KEY = Key.create("RESOLVE_TARGET_KEY");
37 private static final Logger LOG = Logger.getInstance("com.intellij.refactoring.extractMethod.ExtractMethodUtil");
39 private ExtractMethodUtil() { }
41 static Map<PsiMethodCallExpression, PsiMethod> encodeOverloadTargets(final PsiClass targetClass,
42 final SearchScope processConflictsScope,
43 final String overloadName,
44 final PsiElement extractedFragment) {
45 final Map<PsiMethodCallExpression, PsiMethod> ret = new HashMap<PsiMethodCallExpression, PsiMethod>();
46 encodeInClass(targetClass, overloadName, extractedFragment, ret);
48 ClassInheritorsSearch.search(targetClass, processConflictsScope, true).forEach(new Processor<PsiClass>() {
49 public boolean process(PsiClass inheritor) {
50 encodeInClass(inheritor, overloadName, extractedFragment, ret);
51 return true;
53 });
55 return ret;
58 private static void encodeInClass(final PsiClass aClass,
59 final String overloadName,
60 final PsiElement extractedFragment,
61 final Map<PsiMethodCallExpression, PsiMethod> ret) {
62 final PsiMethod[] overloads = aClass.findMethodsByName(overloadName, false);
63 for (final PsiMethod overload : overloads) {
64 for (final PsiReference ref : ReferencesSearch.search(overload)) {
65 final PsiElement element = ref.getElement();
66 final PsiElement parent = element.getParent();
67 if (parent instanceof PsiMethodCallExpression) {
68 final PsiMethodCallExpression call = (PsiMethodCallExpression)parent;
69 if (PsiTreeUtil.isAncestor(extractedFragment, element, false)) {
70 call.putCopyableUserData(RESOLVE_TARGET_KEY, overload);
71 } else {
72 //we assume element won't be invalidated as a result of extraction
73 ret.put(call, overload);
80 public static void decodeOverloadTargets(Map<PsiMethodCallExpression, PsiMethod> oldResolves, final PsiMethod extracted,
81 final PsiElement oldFragment) {
82 final PsiCodeBlock body = extracted.getBody();
83 assert body != null;
84 final JavaRecursiveElementVisitor visitor = new JavaRecursiveElementVisitor() {
86 @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) {
87 super.visitMethodCallExpression(expression);
88 final PsiMethod target = expression.getCopyableUserData(RESOLVE_TARGET_KEY);
89 if (target != null) {
90 expression.putCopyableUserData(RESOLVE_TARGET_KEY, null);
91 try {
92 assertSameResolveTarget(target, expression, extracted);
94 catch (IncorrectOperationException e) {
95 LOG.error(e);
100 body.accept(visitor);
101 oldFragment.accept(visitor);
103 for (final Map.Entry<PsiMethodCallExpression, PsiMethod> entry : oldResolves.entrySet()) {
104 try {
105 assertSameResolveTarget(entry.getValue(), entry.getKey(), extracted);
107 catch (IncorrectOperationException e) {
108 LOG.error(e);
113 private static void assertSameResolveTarget(final PsiMethod oldTarget, final PsiMethodCallExpression call, final PsiMethod extracted)
114 throws IncorrectOperationException {
115 final PsiMethod newTarget = call.resolveMethod();
116 final PsiManager manager = extracted.getManager();
117 final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
118 if (!manager.areElementsEquivalent(oldTarget, newTarget)) {
119 final PsiParameter[] oldParameters = oldTarget.getParameterList().getParameters();
120 final PsiMethodCallExpression copy = (PsiMethodCallExpression)call.copy();
121 final PsiExpression[] args = copy.getArgumentList().getExpressions();
122 for (int i = 0; i < args.length; i++) {
123 PsiExpression arg = args[i];
124 PsiType paramType = i < oldParameters.length ? oldParameters[i].getType() : oldParameters[oldParameters.length - 1].getType();
125 final PsiTypeCastExpression cast = (PsiTypeCastExpression)factory.createExpressionFromText("(a)b", null);
126 final PsiTypeElement typeElement = cast.getCastType();
127 assert typeElement != null;
128 typeElement.replace(factory.createTypeElement(paramType));
129 final PsiExpression operand = cast.getOperand();
130 assert operand != null;
131 operand.replace(arg);
132 arg.replace(cast);
135 for (int i = 0; i < copy.getArgumentList().getExpressions().length; i++) {
136 PsiExpression oldarg = call.getArgumentList().getExpressions()[i];
137 PsiTypeCastExpression cast = (PsiTypeCastExpression)copy.getArgumentList().getExpressions()[i];
138 if (!RedundantCastUtil.isCastRedundant(cast)) {
139 oldarg.replace(cast);