update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / refactoring / util / InlineUtil.java
bloba9910e4dcc237abe780db7fdb6399c48863ac6ce
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.util;
18 import com.intellij.codeInsight.ChangeContextUtil;
19 import com.intellij.openapi.diagnostic.Logger;
20 import com.intellij.openapi.util.Comparing;
21 import com.intellij.openapi.util.text.StringUtil;
22 import com.intellij.psi.*;
23 import com.intellij.psi.util.PsiTreeUtil;
24 import com.intellij.psi.util.RedundantCastUtil;
25 import com.intellij.util.Function;
26 import com.intellij.util.IncorrectOperationException;
27 import org.jetbrains.annotations.NonNls;
29 import java.util.Arrays;
31 /**
32 * @author ven
34 public class InlineUtil {
35 private static final Logger LOG = Logger.getInstance("com.intellij.refactoring.util.InlineUtil");
37 private InlineUtil() {}
39 public static PsiExpression inlineVariable(PsiVariable variable, PsiExpression initializer, PsiJavaCodeReferenceElement ref)
40 throws IncorrectOperationException {
41 PsiManager manager = initializer.getManager();
43 PsiClass thisClass = RefactoringUtil.getThisClass(initializer);
44 PsiClass refParent = RefactoringUtil.getThisClass(ref);
45 final PsiType varType = variable.getType();
46 initializer = RefactoringUtil.convertInitializerToNormalExpression(initializer, varType);
48 ChangeContextUtil.encodeContextInfo(initializer, false);
49 PsiExpression expr = (PsiExpression)ref.replace(initializer);
50 PsiType exprType = expr.getType();
51 if (exprType != null && !varType.equals(exprType)) {
52 boolean matchedTypes = false;
53 //try explicit type arguments
54 final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
55 if (expr instanceof PsiCallExpression && ((PsiCallExpression)expr).getTypeArguments().length == 0) {
56 final JavaResolveResult resolveResult = ((PsiCallExpression)initializer).resolveMethodGenerics();
57 final PsiElement resolved = resolveResult.getElement();
58 if (resolved instanceof PsiMethod) {
59 final PsiTypeParameter[] typeParameters = ((PsiMethod)resolved).getTypeParameters();
60 if (typeParameters.length > 0) {
61 final PsiCallExpression copy = (PsiCallExpression)expr.copy();
62 for (final PsiTypeParameter typeParameter : typeParameters) {
63 final PsiType substituted = resolveResult.getSubstitutor().substitute(typeParameter);
64 if (substituted == null) break;
65 copy.getTypeArgumentList().add(elementFactory.createTypeElement(substituted));
67 if (varType.equals(copy.getType())) {
68 ((PsiCallExpression)expr).getTypeArgumentList().replace(copy.getTypeArgumentList());
69 if (expr instanceof PsiMethodCallExpression) {
70 final PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)expr).getMethodExpression();
71 final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
72 if (qualifierExpression == null) {
73 if (((PsiMethod)resolved).getModifierList().hasModifierProperty(PsiModifier.STATIC)) {
74 methodExpression.setQualifierExpression(elementFactory.createReferenceExpression(thisClass));
75 } else {
76 methodExpression.setQualifierExpression(createThisExpression(manager, thisClass, refParent));
80 matchedTypes = true;
86 if (!matchedTypes) {
87 if (varType instanceof PsiEllipsisType && ((PsiEllipsisType)varType).getComponentType().equals(exprType)) { //convert vararg to array
89 final PsiExpressionList argumentList = PsiTreeUtil.getParentOfType(expr, PsiExpressionList.class);
90 LOG.assertTrue(argumentList != null);
91 final PsiExpression[] arguments = argumentList.getExpressions();
93 @NonNls final StringBuilder builder = new StringBuilder("new ");
94 builder.append(exprType.getCanonicalText());
95 builder.append("[]{");
96 builder.append(StringUtil.join(Arrays.asList(arguments), new Function<PsiExpression, String>() {
97 public String fun(final PsiExpression expr) {
98 return expr.getText();
100 }, ","));
101 builder.append('}');
103 expr.replace(JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createExpressionFromText(builder.toString(), argumentList));
105 } else {
106 //try cast
107 PsiTypeCastExpression cast = (PsiTypeCastExpression)elementFactory.createExpressionFromText("(t)a", null);
108 PsiTypeElement castTypeElement = cast.getCastType();
109 assert castTypeElement != null;
110 castTypeElement.replace(variable.getTypeElement());
111 final PsiExpression operand = cast.getOperand();
112 assert operand != null;
113 operand.replace(expr);
114 PsiExpression exprCopy = (PsiExpression)expr.copy();
115 cast = (PsiTypeCastExpression)expr.replace(cast);
116 if (!RedundantCastUtil.isCastRedundant(cast)) {
117 expr = cast;
119 else {
120 PsiElement toReplace = cast;
121 while (toReplace.getParent() instanceof PsiParenthesizedExpression) {
122 toReplace = toReplace.getParent();
124 expr = (PsiExpression)toReplace.replace(exprCopy);
130 ChangeContextUtil.clearContextInfo(initializer);
132 PsiThisExpression thisAccessExpr = createThisExpression(manager, thisClass, refParent);
134 return (PsiExpression)ChangeContextUtil.decodeContextInfo(expr, thisClass, thisAccessExpr);
137 private static PsiThisExpression createThisExpression(PsiManager manager, PsiClass thisClass, PsiClass refParent) {
138 PsiThisExpression thisAccessExpr = null;
139 if (Comparing.equal(thisClass, refParent))
142 thisAccessExpr = RefactoringUtil.createThisExpression(manager, null);
145 else
148 if (!(thisClass instanceof PsiAnonymousClass)) {
149 thisAccessExpr = RefactoringUtil.createThisExpression(manager, thisClass);
152 return thisAccessExpr;
155 public static void tryToInlineArrayCreationForVarargs(final PsiExpression expr) {
156 if (expr instanceof PsiNewExpression && ((PsiNewExpression)expr).getArrayInitializer() != null) {
157 if (expr.getParent() instanceof PsiExpressionList) {
158 final PsiExpressionList exprList = (PsiExpressionList)expr.getParent();
159 if (exprList.getParent() instanceof PsiCall) {
160 if (isSafeToInlineVarargsArgument((PsiCall)exprList.getParent())) {
161 inlineArrayCreationForVarargs(((PsiNewExpression)expr));
168 public static void inlineArrayCreationForVarargs(final PsiNewExpression arrayCreation) {
169 PsiExpressionList argumentList = (PsiExpressionList)arrayCreation.getParent();
170 if (argumentList == null) return;
171 PsiExpression[] args = argumentList.getExpressions();
172 PsiArrayInitializerExpression arrayInitializer = arrayCreation.getArrayInitializer();
173 try {
174 if (arrayInitializer == null) {
175 arrayCreation.delete();
176 return;
179 PsiExpression[] initializers = arrayInitializer.getInitializers();
180 if (initializers.length > 0) {
181 argumentList.addRange(initializers[0], initializers[initializers.length - 1]);
183 args[args.length - 1].delete();
185 catch (IncorrectOperationException e) {
186 LOG.error(e);
190 private static boolean isSafeToInlineVarargsArgument(PsiCall expression) {
191 final JavaResolveResult resolveResult = expression.resolveMethodGenerics();
192 PsiElement element = resolveResult.getElement();
193 final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
194 if (element instanceof PsiMethod && ((PsiMethod)element).isVarArgs()) {
195 PsiMethod method = (PsiMethod)element;
196 PsiParameter[] parameters = method.getParameterList().getParameters();
197 PsiExpressionList argumentList = expression.getArgumentList();
198 if (argumentList != null) {
199 PsiExpression[] args = argumentList.getExpressions();
200 if (parameters.length == args.length) {
201 PsiExpression lastArg = args[args.length - 1];
202 PsiParameter lastParameter = parameters[args.length - 1];
203 PsiType lastParamType = lastParameter.getType();
204 LOG.assertTrue(lastParamType instanceof PsiEllipsisType);
205 if (lastArg instanceof PsiNewExpression) {
206 final PsiType lastArgType = lastArg.getType();
207 if (lastArgType != null && substitutor.substitute(((PsiEllipsisType)lastParamType).toArrayType()).isAssignableFrom(lastArgType)) {
208 PsiArrayInitializerExpression arrayInitializer = ((PsiNewExpression)lastArg).getArrayInitializer();
209 PsiExpression[] initializers = arrayInitializer != null ? arrayInitializer.getInitializers() : PsiExpression.EMPTY_ARRAY;
210 if (isSafeToFlatten(expression, method, initializers)) {
211 return true;
219 return false;
222 private static boolean isSafeToFlatten(PsiCall callExpression, PsiMethod oldRefMethod, PsiExpression[] arrayElements) {
223 PsiCall copy = (PsiCall)callExpression.copy();
224 PsiExpressionList copyArgumentList = copy.getArgumentList();
225 LOG.assertTrue(copyArgumentList != null);
226 PsiExpression[] args = copyArgumentList.getExpressions();
227 try {
228 args[args.length - 1].delete();
229 if (arrayElements.length > 0) {
230 copyArgumentList.addRange(arrayElements[0], arrayElements[arrayElements.length - 1]);
232 return copy.resolveMethod() == oldRefMethod;
234 catch (IncorrectOperationException e) {
235 return false;