| /* |
| * Copyright 2000-2010 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. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* |
| * User: anna |
| * Date: 10-Jun-2010 |
| */ |
| package com.intellij.codeInsight.daemon.impl.quickfix; |
| |
| import com.intellij.codeInsight.daemon.QuickFixBundle; |
| import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil; |
| import com.intellij.codeInsight.intention.IntentionAction; |
| import com.intellij.openapi.editor.Editor; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.psi.*; |
| import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy; |
| import com.intellij.psi.search.PsiSearchHelper; |
| import com.intellij.psi.util.PsiUtil; |
| import com.intellij.refactoring.typeMigration.TypeMigrationLabeler; |
| import com.intellij.refactoring.typeMigration.TypeMigrationProcessor; |
| import com.intellij.refactoring.typeMigration.TypeMigrationRules; |
| import com.intellij.usageView.UsageViewUtil; |
| import com.intellij.util.IncorrectOperationException; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| public class VariableTypeFromCallFix implements IntentionAction { |
| private final PsiType myExpressionType; |
| private final PsiVariable myVar; |
| |
| private VariableTypeFromCallFix(@NotNull PsiClassType type, @NotNull PsiVariable var) { |
| myExpressionType = type; |
| myVar = var; |
| } |
| |
| @Override |
| @NotNull |
| public String getText() { |
| return QuickFixBundle.message("fix.variable.type.text", |
| UsageViewUtil.getType(myVar), |
| myVar.getName(), |
| myExpressionType.getCanonicalText()); |
| } |
| |
| @Override |
| @NotNull |
| public String getFamilyName() { |
| return QuickFixBundle.message("fix.variable.type.family"); |
| } |
| |
| @Override |
| public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { |
| return true; |
| } |
| |
| @Override |
| public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) throws IncorrectOperationException { |
| final TypeMigrationRules rules = new TypeMigrationRules(TypeMigrationLabeler.getElementType(myVar)); |
| rules.setMigrationRootType(myExpressionType); |
| rules.setBoundScope(PsiSearchHelper.SERVICE.getInstance(project).getUseScope(myVar)); |
| |
| TypeMigrationProcessor.runHighlightingTypeMigration(project, editor, rules, myVar); |
| } |
| |
| @Override |
| public boolean startInWriteAction() { |
| return true; |
| } |
| |
| |
| @NotNull |
| public static List<IntentionAction> getQuickFixActions(@NotNull PsiMethodCallExpression methodCall, |
| @NotNull PsiExpressionList list) { |
| final JavaResolveResult result = methodCall.getMethodExpression().advancedResolve(false); |
| PsiMethod method = (PsiMethod) result.getElement(); |
| final PsiSubstitutor substitutor = result.getSubstitutor(); |
| PsiExpression[] expressions = list.getExpressions(); |
| if (method == null || method.getParameterList().getParametersCount() != expressions.length) return Collections.emptyList(); |
| final PsiParameter[] parameters = method.getParameterList().getParameters(); |
| List<IntentionAction> actions = new ArrayList<IntentionAction>(); |
| for (int i = 0; i < expressions.length; i++) { |
| final PsiExpression expression = expressions[i]; |
| PsiType expressionType = expression.getType(); |
| if (expressionType instanceof PsiPrimitiveType) { |
| expressionType = ((PsiPrimitiveType)expressionType).getBoxedType(expression); |
| } |
| if (expressionType == null) continue; |
| |
| final PsiParameter parameter = parameters[i]; |
| final PsiType formalParamType = parameter.getType(); |
| final PsiType parameterType = substitutor.substitute(formalParamType); |
| if (parameterType.isAssignableFrom(expressionType)) continue; |
| |
| final PsiExpression qualifierExpression = methodCall.getMethodExpression().getQualifierExpression(); |
| if (qualifierExpression instanceof PsiReferenceExpression) { |
| final PsiElement resolved = ((PsiReferenceExpression)qualifierExpression).resolve(); |
| if (resolved instanceof PsiVariable) { |
| final PsiType varType = ((PsiVariable)resolved).getType(); |
| final PsiClass varClass = PsiUtil.resolveClassInType(varType); |
| final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(expression.getProject()).getResolveHelper(); |
| if (varClass != null) { |
| final PsiSubstitutor psiSubstitutor = resolveHelper.inferTypeArguments(varClass.getTypeParameters(), |
| parameters, |
| expressions, PsiSubstitutor.EMPTY, resolved, |
| DefaultParameterTypeInferencePolicy.INSTANCE); |
| final PsiClassType appropriateVarType = JavaPsiFacade.getElementFactory(expression.getProject()).createType(varClass, psiSubstitutor); |
| if (!varType.equals(appropriateVarType)) { |
| actions.add(new VariableTypeFromCallFix(appropriateVarType, (PsiVariable)resolved)); |
| } |
| break; |
| } |
| } |
| } |
| actions.addAll(getParameterTypeChangeFixes(method, expression, parameterType)); |
| } |
| return actions; |
| } |
| |
| private static List<IntentionAction> getParameterTypeChangeFixes(@NotNull PsiMethod method, |
| @NotNull PsiExpression expression, |
| PsiType parameterType) { |
| if (!(expression instanceof PsiReferenceExpression)) { |
| return Collections.emptyList(); |
| } |
| List<IntentionAction> result = new ArrayList<IntentionAction>(); |
| final PsiManager manager = method.getManager(); |
| if (manager.isInProject(method)) { |
| final PsiMethod[] superMethods = method.findDeepestSuperMethods(); |
| for (PsiMethod superMethod : superMethods) { |
| if (!manager.isInProject(superMethod)) return Collections.emptyList(); |
| } |
| final PsiElement resolve = ((PsiReferenceExpression)expression).resolve(); |
| if (resolve instanceof PsiVariable) { |
| result.addAll(HighlightUtil.getChangeVariableTypeFixes((PsiVariable)resolve, parameterType)); |
| } |
| } |
| return result; |
| } |
| } |