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
.codeInsight
.daemon
.impl
.quickfix
;
18 import com
.intellij
.codeInsight
.daemon
.impl
.HighlightInfo
;
19 import com
.intellij
.openapi
.diagnostic
.Logger
;
20 import com
.intellij
.openapi
.util
.Comparing
;
21 import com
.intellij
.openapi
.util
.TextRange
;
22 import com
.intellij
.psi
.*;
23 import com
.intellij
.psi
.infos
.CandidateInfo
;
24 import com
.intellij
.util
.IncorrectOperationException
;
25 import gnu
.trove
.THashSet
;
26 import org
.jetbrains
.annotations
.Nullable
;
28 import java
.util
.ArrayList
;
29 import java
.util
.Arrays
;
30 import java
.util
.List
;
36 public abstract class ArgumentFixerActionFactory
{
37 private static final Logger LOG
= Logger
.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.ArgumentFixerActionFactory");
40 protected abstract PsiExpression
getModifiedArgument(PsiExpression expression
, final PsiType toType
) throws IncorrectOperationException
;
42 public void registerCastActions(CandidateInfo
[] candidates
, PsiCall call
, HighlightInfo highlightInfo
, final TextRange fixRange
) {
43 if (candidates
.length
== 0) return;
44 List
<CandidateInfo
> methodCandidates
= new ArrayList
<CandidateInfo
>(Arrays
.asList(candidates
));
45 PsiExpressionList list
= call
.getArgumentList();
46 PsiExpression
[] expressions
= list
.getExpressions();
47 if (expressions
.length
== 0) return;
48 // filter out not castable candidates
50 for (int i
= methodCandidates
.size() - 1; i
>= 0; i
--) {
51 CandidateInfo candidate
= methodCandidates
.get(i
);
52 PsiMethod method
= (PsiMethod
) candidate
.getElement();
53 PsiSubstitutor substitutor
= candidate
.getSubstitutor();
54 assert method
!= null;
55 PsiParameter
[] parameters
= method
.getParameterList().getParameters();
56 if (expressions
.length
!= parameters
.length
) {
57 methodCandidates
.remove(i
);
60 for (int j
= 0; j
< parameters
.length
; j
++) {
61 PsiParameter parameter
= parameters
[j
];
62 PsiExpression expression
= expressions
[j
];
63 // check if we can cast to this method
64 PsiType exprType
= expression
.getType();
65 PsiType parameterType
= substitutor
.substitute(parameter
.getType());
67 || parameterType
== null
68 || !areTypesConvertible(exprType
, parameterType
, call
)) {
69 methodCandidates
.remove(i
);
75 if (methodCandidates
.isEmpty()) return;
78 for (int i
= 0; i
< expressions
.length
; i
++) {
79 PsiExpression expression
= expressions
[i
];
80 PsiType exprType
= expression
.getType();
81 Set
<String
> suggestedCasts
= new THashSet
<String
>();
82 // find to which type we can cast this param to get valid method call
83 for (CandidateInfo candidate
: methodCandidates
) {
84 PsiMethod method
= (PsiMethod
)candidate
.getElement();
85 PsiSubstitutor substitutor
= candidate
.getSubstitutor();
86 assert method
!= null;
87 PsiParameter
[] parameters
= method
.getParameterList().getParameters();
88 PsiType originalParameterType
= parameters
[i
].getType();
89 PsiType parameterType
= substitutor
.substitute(originalParameterType
);
90 if (parameterType
instanceof PsiWildcardType
) continue;
91 if (!GenericsUtil
.isFromExternalTypeLanguage(parameterType
)) continue;
92 if (suggestedCasts
.contains(parameterType
.getCanonicalText())) continue;
93 // strict compare since even widening cast may help
94 if (Comparing
.equal(exprType
, parameterType
)) continue;
95 PsiCall newCall
= (PsiCall
) call
.copy();
96 PsiExpression modifiedExpression
= getModifiedArgument(expression
, parameterType
);
97 if (modifiedExpression
== null) continue;
98 newCall
.getArgumentList().getExpressions()[i
].replace(modifiedExpression
);
99 JavaResolveResult resolveResult
= newCall
.resolveMethodGenerics();
100 if (resolveResult
.getElement() != null && resolveResult
.isValidResult()) {
101 suggestedCasts
.add(parameterType
.getCanonicalText());
102 QuickFixAction
.registerQuickFixAction(highlightInfo
, fixRange
, createFix(list
, i
, parameterType
),null);
107 catch (IncorrectOperationException e
) {
112 public abstract boolean areTypesConvertible(final PsiType exprType
, final PsiType parameterType
, final PsiElement context
);
114 public abstract MethodArgumentFix
createFix(final PsiExpressionList list
, final int i
, final PsiType parameterType
);