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
.analysis
;
18 import com
.intellij
.codeInsight
.daemon
.HighlightDisplayKey
;
19 import com
.intellij
.codeInsight
.daemon
.JavaErrorMessages
;
20 import com
.intellij
.codeInsight
.daemon
.impl
.HighlightInfo
;
21 import com
.intellij
.codeInsight
.daemon
.impl
.HighlightInfoType
;
22 import com
.intellij
.codeInsight
.daemon
.impl
.JavaHightlightInfoTypes
;
23 import com
.intellij
.codeInsight
.daemon
.impl
.quickfix
.*;
24 import com
.intellij
.codeInsight
.intention
.EmptyIntentionAction
;
25 import com
.intellij
.codeInsight
.intention
.IntentionAction
;
26 import com
.intellij
.codeInsight
.intention
.QuickFixFactory
;
27 import com
.intellij
.codeInspection
.InspectionProfile
;
28 import com
.intellij
.codeInspection
.LocalInspectionTool
;
29 import com
.intellij
.codeInspection
.ex
.InspectionManagerEx
;
30 import com
.intellij
.codeInspection
.ex
.LocalInspectionToolWrapper
;
31 import com
.intellij
.codeInspection
.uncheckedWarnings
.UncheckedWarningLocalInspection
;
32 import com
.intellij
.openapi
.diagnostic
.Logger
;
33 import com
.intellij
.openapi
.project
.IndexNotReadyException
;
34 import com
.intellij
.openapi
.project
.Project
;
35 import com
.intellij
.openapi
.util
.Comparing
;
36 import com
.intellij
.openapi
.util
.TextRange
;
37 import com
.intellij
.pom
.java
.LanguageLevel
;
38 import com
.intellij
.profile
.codeInspection
.InspectionProjectProfileManager
;
39 import com
.intellij
.psi
.*;
40 import com
.intellij
.psi
.search
.GlobalSearchScope
;
41 import com
.intellij
.psi
.search
.searches
.SuperMethodsSearch
;
42 import com
.intellij
.psi
.util
.*;
43 import com
.intellij
.util
.containers
.HashMap
;
44 import com
.intellij
.util
.containers
.HashSet
;
45 import gnu
.trove
.THashMap
;
46 import org
.jetbrains
.annotations
.NonNls
;
47 import org
.jetbrains
.annotations
.NotNull
;
48 import org
.jetbrains
.annotations
.Nullable
;
56 public class GenericsHighlightUtil
{
57 private static final Logger LOG
= Logger
.getInstance("#com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil");
58 private static final String GENERICS_ARE_NOT_SUPPORTED
= JavaErrorMessages
.message("generics.are.not.supported");
59 private static final QuickFixFactory QUICK_FIX_FACTORY
= QuickFixFactory
.getInstance();
61 private GenericsHighlightUtil() {}
63 public static HighlightInfo
checkInferredTypeArguments(PsiMethod genericMethod
,
64 PsiMethodCallExpression call
,
65 PsiSubstitutor substitutor
) {
66 PsiTypeParameter
[] typeParameters
= genericMethod
.getTypeParameters();
67 for (PsiTypeParameter typeParameter
: typeParameters
) {
68 PsiType substituted
= substitutor
.substitute(typeParameter
);
69 if (substituted
== null) return null;
70 substituted
= PsiUtil
.captureToplevelWildcards(substituted
, call
);
71 PsiClassType
[] extendsTypes
= typeParameter
.getExtendsListTypes();
72 for (PsiClassType type
: extendsTypes
) {
73 PsiType extendsType
= substitutor
.substitute(type
);
74 if (!TypeConversionUtil
.isAssignable(extendsType
, substituted
, false)) {
75 PsiClass boundClass
= extendsType
instanceof PsiClassType ?
((PsiClassType
)extendsType
).resolve() : null;
77 @NonNls String messageKey
= boundClass
== null || typeParameter
.isInterface() == boundClass
.isInterface()
78 ?
"generics.inferred.type.for.type.parameter.is.not.within.its.bound.extend"
79 : "generics.inferred.type.for.type.parameter.is.not.within.its.bound.implement";
81 String description
= JavaErrorMessages
.message(
83 HighlightUtil
.formatClass(typeParameter
),
84 HighlightUtil
.formatType(extendsType
),
85 HighlightUtil
.formatType(substituted
)
88 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, call
, description
);
96 public static HighlightInfo
checkParameterizedReferenceTypeArguments(PsiElement resolved
,
97 final PsiJavaCodeReferenceElement referenceElement
,
98 final PsiSubstitutor substitutor
) {
99 if (!(resolved
instanceof PsiTypeParameterListOwner
)) return null;
100 final PsiTypeParameterListOwner typeParameterListOwner
= (PsiTypeParameterListOwner
)resolved
;
101 return checkReferenceTypeArgumentList(typeParameterListOwner
, referenceElement
.getParameterList(), substitutor
, true);
104 public static HighlightInfo
checkReferenceTypeArgumentList(final PsiTypeParameterListOwner typeParameterListOwner
,
105 final PsiReferenceParameterList referenceParameterList
,
106 final PsiSubstitutor substitutor
,
107 boolean registerIntentions
) {
108 if (referenceParameterList
!= null && !PsiUtil
.isLanguageLevel5OrHigher(referenceParameterList
)) {
109 if (referenceParameterList
.getTypeParameterElements().length
> 0) {
110 HighlightInfo info
= HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, referenceParameterList
, GENERICS_ARE_NOT_SUPPORTED
);
111 QuickFixAction
.registerQuickFixAction(info
, new ShowModulePropertiesFix(referenceParameterList
));
112 QuickFixAction
.registerQuickFixAction(info
, new IncreaseLanguageLevelFix(LanguageLevel
.JDK_1_5
));
117 final PsiTypeParameter
[] typeParameters
= typeParameterListOwner
.getTypeParameters();
118 final int targetParametersNum
= typeParameters
.length
;
119 final int refParametersNum
= referenceParameterList
== null ?
0 : referenceParameterList
.getTypeParameterElements().length
;
120 if (targetParametersNum
!= refParametersNum
&& refParametersNum
!= 0) {
121 final String description
;
122 if (targetParametersNum
== 0) {
123 description
= JavaErrorMessages
.message(
124 "generics.type.or.method.does.not.have.type.parameters",
125 typeParameterListOwnerCategoryDescription(typeParameterListOwner
),
126 typeParameterListOwnerDescription(typeParameterListOwner
)
130 description
= JavaErrorMessages
.message(
131 "generics.wrong.number.of.type.arguments", refParametersNum
, targetParametersNum
135 final HighlightInfo highlightInfo
= HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, referenceParameterList
, description
);
136 if (registerIntentions
) {
137 PsiElement pparent
= referenceParameterList
.getParent().getParent();
138 if (pparent
instanceof PsiTypeElement
) {
139 PsiElement variable
= pparent
.getParent();
140 if (variable
instanceof PsiVariable
) {
141 VariableParameterizedTypeFix
.registerIntentions(highlightInfo
, (PsiVariable
)variable
, referenceParameterList
);
145 return highlightInfo
;
149 if (targetParametersNum
> 0 && refParametersNum
!= 0) {
150 final PsiTypeElement
[] referenceElements
= referenceParameterList
.getTypeParameterElements();
151 for (int i
= 0; i
< typeParameters
.length
; i
++) {
152 PsiTypeParameter classParameter
= typeParameters
[i
];
153 final PsiTypeElement typeElement
= referenceElements
[i
];
154 final PsiType type
= typeElement
.getType();
155 if (!(type
instanceof PsiClassType
)) continue;
156 final PsiClass referenceClass
= ((PsiClassType
)type
).resolve();
157 if (referenceClass
== null) continue;
158 final PsiClassType
[] bounds
= classParameter
.getSuperTypes();
159 for (PsiClassType type1
: bounds
) {
160 PsiType bound
= substitutor
.substitute(type1
);
161 if (!TypeConversionUtil
.isAssignable(bound
, type
, false)) {
162 PsiClass boundClass
= bound
instanceof PsiClassType ?
((PsiClassType
)bound
).resolve() : null;
164 @NonNls final String messageKey
= boundClass
== null || referenceClass
.isInterface() == boundClass
.isInterface()
165 ?
"generics.type.parameter.is.not.within.its.bound.extend"
166 : "generics.type.parameter.is.not.within.its.bound.implement";
168 String description
= JavaErrorMessages
.message(messageKey
,
169 HighlightUtil
.formatClass(referenceClass
),
170 HighlightUtil
.formatType(bound
));
172 final HighlightInfo highlightInfo
= HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
,
175 if (bound
instanceof PsiClassType
) {
176 QuickFixAction
.registerQuickFixAction(highlightInfo
, QUICK_FIX_FACTORY
.createExtendsListFix(referenceClass
, (PsiClassType
)bound
, true),
179 return highlightInfo
;
188 private static String
typeParameterListOwnerDescription(final PsiTypeParameterListOwner typeParameterListOwner
) {
189 if (typeParameterListOwner
instanceof PsiClass
) {
190 return HighlightUtil
.formatClass((PsiClass
)typeParameterListOwner
);
192 else if (typeParameterListOwner
instanceof PsiMethod
) {
193 return HighlightUtil
.formatMethod((PsiMethod
)typeParameterListOwner
);
196 LOG
.error("Unknown " + typeParameterListOwner
);
201 private static String
typeParameterListOwnerCategoryDescription(final PsiTypeParameterListOwner typeParameterListOwner
) {
202 if (typeParameterListOwner
instanceof PsiClass
) {
203 return JavaErrorMessages
.message("generics.holder.type");
205 else if (typeParameterListOwner
instanceof PsiMethod
) {
206 return JavaErrorMessages
.message("generics.holder.method");
209 LOG
.error("Unknown " + typeParameterListOwner
);
214 public static HighlightInfo
checkElementInTypeParameterExtendsList(PsiReferenceList referenceList
, JavaResolveResult resolveResult
, PsiElement element
) {
215 PsiClass aClass
= (PsiClass
)referenceList
.getParent();
216 final PsiJavaCodeReferenceElement
[] referenceElements
= referenceList
.getReferenceElements();
217 PsiClass extendFrom
= (PsiClass
)resolveResult
.getElement();
218 if (extendFrom
== null) return null;
219 HighlightInfo errorResult
= null;
220 if (!extendFrom
.isInterface() && referenceElements
.length
!= 0 && element
!= referenceElements
[0]) {
221 final String description
= HighlightClassUtil
.INTERFACE_EXPECTED
;
222 errorResult
= HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, element
, description
);
224 JavaPsiFacade
.getInstance(aClass
.getProject()).getElementFactory().createType(extendFrom
, resolveResult
.getSubstitutor());
225 QuickFixAction
.registerQuickFixAction(errorResult
, new MoveBoundClassToFrontFix(aClass
, type
), null);
227 else if (referenceElements
.length
!= 0 && element
!= referenceElements
[0] && referenceElements
[0].resolve() instanceof PsiTypeParameter
) {
228 final String description
= JavaErrorMessages
.message("type.parameter.cannot.be.followed.by.other.bounds");
229 errorResult
= HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, element
, description
);
231 JavaPsiFacade
.getInstance(aClass
.getProject()).getElementFactory().createType(extendFrom
, resolveResult
.getSubstitutor());
232 IntentionAction fix
= QUICK_FIX_FACTORY
.createExtendsListFix(aClass
, type
, false);
233 QuickFixAction
.registerQuickFixAction(errorResult
, fix
, null);
237 public static HighlightInfo
checkInterfaceMultipleInheritance(PsiClass aClass
) {
238 if (aClass
instanceof PsiTypeParameter
) return null;
239 final PsiClassType
[] types
= aClass
.getSuperTypes();
240 if (types
.length
< 2) return null;
241 Map
<PsiClass
, PsiSubstitutor
> inheritedClasses
= new HashMap
<PsiClass
, PsiSubstitutor
>();
242 final TextRange textRange
= HighlightNamesUtil
.getClassDeclarationTextRange(aClass
);
243 return checkInterfaceMultipleInheritance(aClass
,
244 PsiSubstitutor
.EMPTY
, inheritedClasses
,
245 new HashSet
<PsiClass
>(), textRange
);
248 private static HighlightInfo
checkInterfaceMultipleInheritance(PsiClass aClass
,
249 PsiSubstitutor derivedSubstitutor
,
250 Map
<PsiClass
, PsiSubstitutor
> inheritedClasses
,
251 Set
<PsiClass
> visited
,
252 TextRange textRange
) {
253 final PsiClassType
[] superTypes
= aClass
.getSuperTypes();
254 for (PsiClassType superType
: superTypes
) {
255 final PsiClassType
.ClassResolveResult result
= superType
.resolveGenerics();
256 final PsiClass superClass
= result
.getElement();
257 if (superClass
== null || visited
.contains(superClass
)) continue;
258 PsiSubstitutor superTypeSubstitutor
= result
.getSubstitutor();
259 superTypeSubstitutor
= MethodSignatureUtil
.combineSubstitutors(superTypeSubstitutor
, derivedSubstitutor
);
261 final PsiSubstitutor inheritedSubstitutor
= inheritedClasses
.get(superClass
);
262 if (inheritedSubstitutor
!= null) {
263 final PsiTypeParameter
[] typeParameters
= superClass
.getTypeParameters();
264 for (PsiTypeParameter typeParameter
: typeParameters
) {
265 PsiType type1
= inheritedSubstitutor
.substitute(typeParameter
);
266 PsiType type2
= superTypeSubstitutor
.substitute(typeParameter
);
268 if (!Comparing
.equal(type1
, type2
)) {
269 String description
= JavaErrorMessages
.message("generics.cannot.be.inherited.with.different.type.arguments",
270 HighlightUtil
.formatClass(superClass
),
271 HighlightUtil
.formatType(type1
),
272 HighlightUtil
.formatType(type2
));
273 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, textRange
, description
);
277 inheritedClasses
.put(superClass
, superTypeSubstitutor
);
278 visited
.add(superClass
);
279 final HighlightInfo highlightInfo
= checkInterfaceMultipleInheritance(superClass
, superTypeSubstitutor
, inheritedClasses
, visited
, textRange
);
280 visited
.remove(superClass
);
282 if (highlightInfo
!= null) return highlightInfo
;
287 public static HighlightInfo
checkOverrideEquivalentMethods(final PsiClass aClass
) {
288 final Collection
<HierarchicalMethodSignature
> signaturesWithSupers
= aClass
.getVisibleSignatures();
289 PsiManager manager
= aClass
.getManager();
290 Map
<MethodSignature
, MethodSignatureBackedByPsiMethod
> sameErasureMethods
=
291 new THashMap
<MethodSignature
, MethodSignatureBackedByPsiMethod
>(MethodSignatureUtil
.METHOD_PARAMETERS_ERASURE_EQUALITY
);
293 for (HierarchicalMethodSignature signature
: signaturesWithSupers
) {
294 HighlightInfo info
= checkSameErasureNotSubsignatureInner(signature
, manager
, aClass
, sameErasureMethods
);
295 if (info
!= null) return info
;
301 private static HighlightInfo
checkSameErasureNotSubsignatureInner(final HierarchicalMethodSignature signature
,
302 final PsiManager manager
,
303 final PsiClass aClass
,
304 final Map
<MethodSignature
, MethodSignatureBackedByPsiMethod
> sameErasureMethods
) {
305 PsiMethod method
= signature
.getMethod();
306 JavaPsiFacade facade
= JavaPsiFacade
.getInstance(manager
.getProject());
307 if (!facade
.getResolveHelper().isAccessible(method
, aClass
, null)) return null;
308 MethodSignature signatureToErase
= method
.getSignature(PsiSubstitutor
.EMPTY
);
309 MethodSignatureBackedByPsiMethod sameErasure
= sameErasureMethods
.get(signatureToErase
);
311 if (sameErasure
!= null) {
312 info
= checkSameErasureNotSubsignatureOrSameClass(sameErasure
, signature
, aClass
, method
);
313 if (info
!= null) return info
;
315 sameErasureMethods
.put(signatureToErase
, signature
);
316 List
<HierarchicalMethodSignature
> supers
= signature
.getSuperSignatures();
317 for (HierarchicalMethodSignature superSignature
: supers
) {
318 info
= checkSameErasureNotSubsignatureInner(superSignature
, manager
, aClass
, sameErasureMethods
);
319 if (info
!= null) return info
;
324 private static HighlightInfo
checkSameErasureNotSubsignatureOrSameClass(final MethodSignatureBackedByPsiMethod signatureToCheck
,
325 final HierarchicalMethodSignature superSignature
,
326 final PsiClass aClass
,
327 final PsiMethod superMethod
) {
328 final PsiMethod checkMethod
= signatureToCheck
.getMethod();
329 if (superMethod
.equals(checkMethod
)) return null;
330 PsiClass checkContainingClass
= checkMethod
.getContainingClass();
331 LOG
.assertTrue(checkContainingClass
!= null);
332 PsiClass superContainingClass
= superMethod
.getContainingClass();
333 boolean checkEqualsSuper
= checkContainingClass
.equals(superContainingClass
);
334 if (checkMethod
.isConstructor()) {
335 if (!superMethod
.isConstructor() || !checkEqualsSuper
) return null;
337 else if (superMethod
.isConstructor()) return null;
339 if (checkMethod
.hasModifierProperty(PsiModifier
.STATIC
) && !checkEqualsSuper
) {
343 final PsiType retErasure1
= TypeConversionUtil
.erasure(checkMethod
.getReturnType());
344 final PsiType retErasure2
= TypeConversionUtil
.erasure(superMethod
.getReturnType());
345 if (!Comparing
.equal(retErasure1
, retErasure2
) &&
346 !TypeConversionUtil
.isVoidType(retErasure1
) &&
347 !TypeConversionUtil
.isVoidType(retErasure2
) &&
348 !(checkEqualsSuper
&& Arrays
.equals(superSignature
.getParameterTypes(), signatureToCheck
.getParameterTypes()))) {
352 if (!checkEqualsSuper
&& MethodSignatureUtil
.isSubsignature(superSignature
, signatureToCheck
)) {
355 if (aClass
.equals(checkContainingClass
)) {
356 boolean sameClass
= aClass
.equals(superContainingClass
);
357 return getSameErasureMessage(sameClass
, checkMethod
, superMethod
, HighlightNamesUtil
.getMethodDeclarationTextRange(checkMethod
));
360 return getSameErasureMessage(false, checkMethod
, superMethod
, HighlightNamesUtil
.getClassDeclarationTextRange(aClass
));
364 private static HighlightInfo
getSameErasureMessage(final boolean sameClass
, final PsiMethod method
, final PsiMethod superMethod
,
365 TextRange textRange
) {
366 @NonNls final String key
= sameClass ?
"generics.methods.have.same.erasure" : "generics.methods.have.same.erasure.override";
367 String description
= JavaErrorMessages
.message(key
, HighlightMethodUtil
.createClashMethodMessage(method
, superMethod
, !sameClass
));
368 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, textRange
, description
);
371 public static HighlightInfo
checkTypeParameterInstantiation(PsiNewExpression expression
) {
372 PsiJavaCodeReferenceElement classReference
= expression
.getClassOrAnonymousClassReference();
373 if (classReference
== null) return null;
374 final JavaResolveResult result
= classReference
.advancedResolve(false);
375 final PsiElement element
= result
.getElement();
376 if (element
instanceof PsiTypeParameter
) {
377 String description
= JavaErrorMessages
.message("generics.type.parameter.cannot.be.instantiated",
378 HighlightUtil
.formatClass((PsiTypeParameter
)element
));
379 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, classReference
, description
);
384 public static HighlightInfo
checkWildcardUsage(PsiTypeElement typeElement
) {
385 PsiType type
= typeElement
.getType();
386 if (type
instanceof PsiWildcardType
) {
387 if (typeElement
.getParent() instanceof PsiReferenceParameterList
) {
388 PsiElement parent
= typeElement
.getParent().getParent();
389 LOG
.assertTrue(parent
instanceof PsiJavaCodeReferenceElement
, parent
);
390 PsiElement refParent
= parent
.getParent();
391 if (refParent
instanceof PsiAnonymousClass
) refParent
= refParent
.getParent();
392 if (refParent
instanceof PsiNewExpression
) {
393 PsiNewExpression newExpression
= (PsiNewExpression
)refParent
;
394 if (!(newExpression
.getType() instanceof PsiArrayType
)) {
395 String description
= JavaErrorMessages
.message("wildcard.type.cannot.be.instantiated", HighlightUtil
.formatType(type
));
396 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, typeElement
, description
);
399 else if (refParent
instanceof PsiReferenceList
) {
400 PsiElement refPParent
= refParent
.getParent();
401 if (!(refPParent
instanceof PsiTypeParameter
) || refParent
!= ((PsiTypeParameter
)refPParent
).getExtendsList()) {
402 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
,
404 JavaErrorMessages
.message("generics.wildcard.not.expected"));
409 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
,
411 JavaErrorMessages
.message("generics.wildcards.may.be.used.only.as.reference.parameters"));
418 public static HighlightInfo
checkReferenceTypeUsedAsTypeArgument(PsiTypeElement typeElement
) {
419 final PsiType type
= typeElement
.getType();
420 if (type
instanceof PsiPrimitiveType
||
421 type
instanceof PsiWildcardType
&& ((PsiWildcardType
)type
).getBound() instanceof PsiPrimitiveType
) {
422 final PsiElement element
= new PsiMatcherImpl(typeElement
)
423 .parent(PsiMatchers
.hasClass(PsiReferenceParameterList
.class))
424 .parent(PsiMatchers
.hasClass(PsiJavaCodeReferenceElement
.class))
426 if (element
== null) return null;
428 String description
= JavaErrorMessages
.message("generics.type.argument.cannot.be.of.primitive.type");
429 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, typeElement
, description
);
435 //precondition: TypeConversionUtil.isAssignable(lType, rType) || expressionAssignable
436 public static HighlightInfo
checkRawToGenericAssignment(PsiType lType
, PsiType rType
, @NotNull final PsiElement elementToHighlight
) {
437 if (!PsiUtil
.isLanguageLevel5OrHigher(elementToHighlight
)) return null;
438 final HighlightDisplayKey key
= HighlightDisplayKey
.find(UncheckedWarningLocalInspection
.SHORT_NAME
);
439 if (!InspectionProjectProfileManager
.getInstance(elementToHighlight
.getProject()).getInspectionProfile().isToolEnabled(key
,
440 elementToHighlight
)) return null;
441 if (!isRawToGeneric(lType
, rType
)) return null;
442 String description
= JavaErrorMessages
.message("generics.unchecked.assignment",
443 HighlightUtil
.formatType(rType
),
444 HighlightUtil
.formatType(lType
));
446 return createUncheckedWarning(elementToHighlight
, key
, description
, elementToHighlight
);
449 private static boolean isRawToGeneric(PsiType lType
, PsiType rType
) {
450 if (lType
instanceof PsiPrimitiveType
|| rType
instanceof PsiPrimitiveType
) return false;
451 if (lType
.equals(rType
)) return false;
452 if (lType
instanceof PsiArrayType
&& rType
instanceof PsiArrayType
) {
453 return isRawToGeneric(((PsiArrayType
)lType
).getComponentType(), ((PsiArrayType
)rType
).getComponentType());
455 if (lType
instanceof PsiArrayType
|| rType
instanceof PsiArrayType
) return false;
457 if (rType
instanceof PsiIntersectionType
) {
458 for (PsiType type
: ((PsiIntersectionType
)rType
).getConjuncts()) {
459 if (isRawToGeneric(lType
, type
)) return true;
462 } else if (lType
instanceof PsiIntersectionType
) {
463 for (PsiType type
: ((PsiIntersectionType
)lType
).getConjuncts()) {
464 if (isRawToGeneric(type
, rType
)) return true;
469 if (lType
instanceof PsiCapturedWildcardType
|| rType
instanceof PsiCapturedWildcardType
) {
473 if (lType
instanceof PsiWildcardType
|| rType
instanceof PsiWildcardType
) return false;
475 boolean isValidType
= lType
instanceof PsiClassType
&& rType
instanceof PsiClassType
;
477 LOG
.error("Invalid types: rType =" + rType
+ ", lType=" + lType
);
479 PsiClassType
.ClassResolveResult lResolveResult
= ((PsiClassType
)lType
).resolveGenerics();
480 PsiClassType
.ClassResolveResult rResolveResult
= ((PsiClassType
)rType
).resolveGenerics();
481 PsiClass lClass
= lResolveResult
.getElement();
482 PsiClass rClass
= rResolveResult
.getElement();
484 if (rClass
instanceof PsiAnonymousClass
) {
485 return isRawToGeneric(lType
, ((PsiAnonymousClass
)rClass
).getBaseClassType());
488 PsiSubstitutor lSubstitutor
= lResolveResult
.getSubstitutor();
489 PsiSubstitutor rSubstitutor
= rResolveResult
.getSubstitutor();
490 if (lClass
== null || rClass
== null) return false;
491 if (lClass
instanceof PsiTypeParameter
&&
492 !InheritanceUtil
.isInheritorOrSelf(rClass
, lClass
, true)) return true;
494 if (!lClass
.getManager().areElementsEquivalent(lClass
, rClass
)) {
495 if (lClass
.isInheritor(rClass
, true)) {
496 lSubstitutor
= TypeConversionUtil
.getSuperClassSubstitutor(rClass
, lClass
, lSubstitutor
);
499 else if (rClass
.isInheritor(lClass
, true)) {
500 rSubstitutor
= TypeConversionUtil
.getSuperClassSubstitutor(lClass
, rClass
, rSubstitutor
);
508 Iterator
<PsiTypeParameter
> lIterator
= PsiUtil
.typeParametersIterator(lClass
);
509 Iterator
<PsiTypeParameter
> rIterator
= PsiUtil
.typeParametersIterator(rClass
);
510 while (lIterator
.hasNext()) {
511 if (!rIterator
.hasNext()) return false;
512 PsiTypeParameter lParameter
= lIterator
.next();
513 PsiTypeParameter rParameter
= rIterator
.next();
514 PsiType lTypeArg
= lSubstitutor
.substitute(lParameter
);
515 PsiType rTypeArg
= rSubstitutor
.substituteWithBoundsPromotion(rParameter
);
516 if (lTypeArg
== null) continue;
517 if (rTypeArg
== null) {
518 if (lTypeArg
instanceof PsiWildcardType
&& ((PsiWildcardType
) lTypeArg
).getBound() == null) {
525 if (isUncheckedTypeArgumentConversion(lTypeArg
, rTypeArg
)) return true;
530 public static HighlightInfo
checkUncheckedTypeCast(PsiTypeCastExpression typeCast
) {
531 if (!PsiUtil
.isLanguageLevel5OrHigher(typeCast
)) return null;
532 final HighlightDisplayKey key
= HighlightDisplayKey
.find(UncheckedWarningLocalInspection
.SHORT_NAME
);
533 if (!InspectionProjectProfileManager
.getInstance(typeCast
.getProject()).getInspectionProfile().isToolEnabled(key
, typeCast
)) return null;
534 final PsiTypeElement typeElement
= typeCast
.getCastType();
535 if (typeElement
== null) return null;
536 final PsiType castType
= typeElement
.getType();
537 final PsiExpression expression
= typeCast
.getOperand();
538 if (expression
== null) return null;
539 final PsiType exprType
= expression
.getType();
540 if (exprType
== null) return null;
541 if (isUncheckedCast(castType
, exprType
)) {
542 String description
= JavaErrorMessages
.message("generics.unchecked.cast",
543 HighlightUtil
.formatType(exprType
),
544 HighlightUtil
.formatType(castType
));
545 return createUncheckedWarning(expression
, key
, description
, typeCast
);
550 private static boolean isUncheckedCast(PsiType castType
, PsiType operandType
) {
551 if (TypeConversionUtil
.isAssignable(castType
, operandType
, false)) return false;
553 castType
= castType
.getDeepComponentType();
554 if (castType
instanceof PsiClassType
) {
555 final PsiClassType castClassType
= (PsiClassType
)castType
;
556 operandType
= operandType
.getDeepComponentType();
558 if (!(operandType
instanceof PsiClassType
)) return false;
559 final PsiClassType operandClassType
= (PsiClassType
)operandType
;
560 final PsiClassType
.ClassResolveResult castResult
= castClassType
.resolveGenerics();
561 final PsiClassType
.ClassResolveResult operandResult
= operandClassType
.resolveGenerics();
562 final PsiClass operandClass
= operandResult
.getElement();
563 final PsiClass castClass
= castResult
.getElement();
565 if (operandClass
== null || castClass
== null) return false;
566 if (castClass
instanceof PsiTypeParameter
) return true;
568 if (castClassType
.hasNonTrivialParameters()) {
569 if (operandClassType
.isRaw()) return true;
570 if (castClass
.isInheritor(operandClass
, true)) {
571 PsiSubstitutor castSubstitutor
= castResult
.getSubstitutor();
572 for (PsiTypeParameter typeParameter
: PsiUtil
.typeParametersIterable(castClass
)) {
573 PsiSubstitutor modifiedSubstitutor
= castSubstitutor
.put(typeParameter
, null);
574 PsiClassType otherType
=
575 JavaPsiFacade
.getInstance(typeParameter
.getProject()).getElementFactory().createType(castClass
, modifiedSubstitutor
);
576 if (TypeConversionUtil
.isAssignable(operandType
, otherType
, false)) return true;
587 private static boolean isUncheckedTypeArgumentConversion (PsiType lTypeArg
, PsiType rTypeArg
) {
588 if (lTypeArg
instanceof PsiPrimitiveType
|| rTypeArg
instanceof PsiPrimitiveType
) return false;
589 if (lTypeArg
.equals(rTypeArg
)) return false;
590 if (lTypeArg
instanceof PsiCapturedWildcardType
) {
591 //ignore capture conversion
592 return isUncheckedTypeArgumentConversion(((PsiCapturedWildcardType
)lTypeArg
).getWildcard(), rTypeArg
);
594 if (rTypeArg
instanceof PsiCapturedWildcardType
) {
595 //ignore capture conversion
596 return isUncheckedTypeArgumentConversion(lTypeArg
, ((PsiCapturedWildcardType
)rTypeArg
).getWildcard());
599 if (lTypeArg
instanceof PsiWildcardType
|| rTypeArg
instanceof PsiWildcardType
) {
600 return !lTypeArg
.isAssignableFrom(rTypeArg
);
603 if (lTypeArg
instanceof PsiArrayType
&& rTypeArg
instanceof PsiArrayType
) {
604 return isUncheckedTypeArgumentConversion(((PsiArrayType
)rTypeArg
).getComponentType(), ((PsiArrayType
)lTypeArg
).getComponentType());
606 if (lTypeArg
instanceof PsiArrayType
|| rTypeArg
instanceof PsiArrayType
) return false;
607 if (lTypeArg
instanceof PsiIntersectionType
) {
608 for (PsiType type
: ((PsiIntersectionType
)lTypeArg
).getConjuncts()) {
609 if (!isUncheckedTypeArgumentConversion(type
, rTypeArg
)) return false;
613 if (!(lTypeArg
instanceof PsiClassType
)) {
614 LOG
.error("left: "+lTypeArg
+ "; "+lTypeArg
.getClass());
616 if (rTypeArg
instanceof PsiIntersectionType
) {
617 for (PsiType type
: ((PsiIntersectionType
)rTypeArg
).getConjuncts()) {
618 if (!isUncheckedTypeArgumentConversion(lTypeArg
, type
)) return false;
622 if (!(rTypeArg
instanceof PsiClassType
)) {
623 LOG
.error("right :"+rTypeArg
+ "; "+rTypeArg
.getClass());
625 return ((PsiClassType
)lTypeArg
).resolve() instanceof PsiTypeParameter
||
626 ((PsiClassType
)rTypeArg
).resolve() instanceof PsiTypeParameter
;
629 public static HighlightInfo
checkUncheckedCall(JavaResolveResult resolveResult
, PsiCall call
) {
630 if (!PsiUtil
.isLanguageLevel5OrHigher(call
)) return null;
631 final HighlightDisplayKey key
= HighlightDisplayKey
.find(UncheckedWarningLocalInspection
.SHORT_NAME
);
632 if (!InspectionProjectProfileManager
.getInstance(call
.getProject()).getInspectionProfile().isToolEnabled(key
, call
)) return null;
634 final PsiMethod method
= (PsiMethod
)resolveResult
.getElement();
635 if (method
== null) return null;
636 final PsiSubstitutor substitutor
= resolveResult
.getSubstitutor();
637 final PsiParameter
[] parameters
= method
.getParameterList().getParameters();
638 for (final PsiParameter parameter
: parameters
) {
639 final PsiType parameterType
= parameter
.getType();
640 if (parameterType
.accept(new PsiTypeVisitor
<Boolean
>() {
641 public Boolean
visitPrimitiveType(PsiPrimitiveType primitiveType
) {
642 return Boolean
.FALSE
;
645 public Boolean
visitArrayType(PsiArrayType arrayType
) {
646 return arrayType
.getComponentType().accept(this);
649 public Boolean
visitClassType(PsiClassType classType
) {
650 PsiClass psiClass
= classType
.resolve();
651 if (psiClass
instanceof PsiTypeParameter
) {
652 return substitutor
.substitute((PsiTypeParameter
)psiClass
) == null ? Boolean
.TRUE
: Boolean
.FALSE
;
654 PsiType
[] parameters
= classType
.getParameters();
655 for (PsiType parameter
: parameters
) {
656 if (parameter
.accept(this).booleanValue()) return Boolean
.TRUE
;
659 return Boolean
.FALSE
;
662 public Boolean
visitWildcardType(PsiWildcardType wildcardType
) {
663 PsiType bound
= wildcardType
.getBound();
664 if (bound
!= null) return bound
.accept(this);
665 return Boolean
.FALSE
;
668 public Boolean
visitEllipsisType(PsiEllipsisType ellipsisType
) {
669 return ellipsisType
.getComponentType().accept(this);
672 final PsiElementFactory elementFactory
= JavaPsiFacade
.getInstance(method
.getProject()).getElementFactory();
673 PsiType type
= elementFactory
.createType(method
.getContainingClass(), substitutor
);
674 String description
= JavaErrorMessages
.message("generics.unchecked.call.to.member.of.raw.type",
675 HighlightUtil
.formatMethod(method
),
676 HighlightUtil
.formatType(type
));
677 PsiElement element
= call
instanceof PsiMethodCallExpression
678 ?
((PsiMethodCallExpression
)call
).getMethodExpression()
680 return createUncheckedWarning(call
, key
, description
, element
);
686 private static HighlightInfo
createUncheckedWarning(PsiElement context
, HighlightDisplayKey key
, String description
, PsiElement elementToHighlight
) {
687 final InspectionProfile inspectionProfile
=
688 InspectionProjectProfileManager
.getInstance(context
.getProject()).getInspectionProfile();
689 final LocalInspectionTool tool
=
690 ((LocalInspectionToolWrapper
)inspectionProfile
.getInspectionTool(UncheckedWarningLocalInspection
.SHORT_NAME
, elementToHighlight
)).getTool();
691 if (InspectionManagerEx
.inspectionResultSuppressed(context
, tool
)) return null;
692 HighlightInfo highlightInfo
= HighlightInfo
.createHighlightInfo(JavaHightlightInfoTypes
.UNCHECKED_WARNING
, elementToHighlight
, description
);
693 QuickFixAction
.registerQuickFixAction(highlightInfo
, new GenerifyFileFix(elementToHighlight
.getContainingFile()), key
);
694 return highlightInfo
;
697 public static HighlightInfo
checkForeachLoopParameterType(PsiForeachStatement statement
) {
698 final PsiParameter parameter
= statement
.getIterationParameter();
699 final PsiExpression expression
= statement
.getIteratedValue();
700 if (expression
== null) return null;
701 final PsiType itemType
= getCollectionItemType(expression
);
702 if (itemType
== null) {
703 String description
= JavaErrorMessages
.message("foreach.not.applicable",
704 HighlightUtil
.formatType(expression
.getType()));
705 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, expression
, description
);
707 final int start
= parameter
.getTextRange().getStartOffset();
708 final int end
= expression
.getTextRange().getEndOffset();
709 final PsiType parameterType
= parameter
.getType();
710 HighlightInfo highlightInfo
= HighlightUtil
.checkAssignability(parameterType
, itemType
, null, new TextRange(start
, end
));
711 if (highlightInfo
!= null) {
712 HighlightUtil
.registerChangeVariableTypeFixes(parameter
, itemType
, highlightInfo
);
714 highlightInfo
= checkRawToGenericAssignment(parameterType
, itemType
, statement
.getIterationParameter());
716 return highlightInfo
;
720 private static PsiType
getCollectionItemType(PsiExpression expression
) {
721 final PsiType type
= expression
.getType();
722 if (type
== null) return null;
723 if (type
instanceof PsiArrayType
) {
724 return ((PsiArrayType
)type
).getComponentType();
726 if (type
instanceof PsiClassType
) {
727 final PsiClassType
.ClassResolveResult resolveResult
= ((PsiClassType
)type
).resolveGenerics();
728 PsiClass aClass
= resolveResult
.getElement();
729 if (aClass
== null) return null;
730 final PsiManager manager
= aClass
.getManager();
731 final String qName
= aClass
.getQualifiedName();
732 PsiSubstitutor substitutor
= resolveResult
.getSubstitutor();
733 JavaPsiFacade facade
= JavaPsiFacade
.getInstance(manager
.getProject());
735 PsiClass myClass
= facade
.findClass(qName
, expression
.getResolveScope());
736 if (myClass
!= null && myClass
!= aClass
) {
738 PsiTypeParameter thisTypeParameter
= getIterableTypeParameter(facade
, myClass
);
739 if (thisTypeParameter
== null) return null;
740 PsiTypeParameter thatTypeParameter
= getIterableTypeParameter(facade
, aClass
);
741 if (thatTypeParameter
!= null) { //it can be null if we reference collection in JDK1.4 module from JDK5 source
742 substitutor
= substitutor
.put(thisTypeParameter
, substitutor
.substitute(thatTypeParameter
));
747 PsiTypeParameter typeParameter
= getIterableTypeParameter(facade
, aClass
);
748 if (typeParameter
== null) return null;
749 PsiClass owner
= (PsiClass
)typeParameter
.getOwner();
750 if (owner
== null) return null;
751 PsiSubstitutor superClassSubstitutor
= TypeConversionUtil
.getClassSubstitutor(owner
, aClass
, PsiSubstitutor
.EMPTY
);
752 if (superClassSubstitutor
== null) return null;
753 PsiType itemType
= superClassSubstitutor
.substitute(typeParameter
);
754 itemType
= substitutor
.substitute(itemType
);
755 return itemType
== null ? PsiType
.getJavaLangObject(manager
, aClass
.getResolveScope()) : itemType
;
761 private static PsiTypeParameter
getIterableTypeParameter(final JavaPsiFacade facade
, final PsiClass context
) {
762 PsiClass iterable
= facade
.findClass("java.lang.Iterable", context
.getResolveScope());
763 if (iterable
== null) return null;
764 PsiTypeParameter
[] typeParameters
= iterable
.getTypeParameters();
765 if (typeParameters
.length
!= 1) return null;
766 return typeParameters
[0];
770 public static HighlightInfo
checkAccessStaticFieldFromEnumConstructor(PsiReferenceExpression expr
, JavaResolveResult result
) {
771 final PsiElement resolved
= result
.getElement();
773 if (!(resolved
instanceof PsiField
)) return null;
774 if (!((PsiModifierListOwner
)resolved
).hasModifierProperty(PsiModifier
.STATIC
)) return null;
775 final PsiMember constructorOrInitializer
= PsiUtil
.findEnclosingConstructorOrInitializer(expr
);
776 if (constructorOrInitializer
== null) return null;
777 if (constructorOrInitializer
.hasModifierProperty(PsiModifier
.STATIC
)) return null;
778 final PsiClass aClass
= constructorOrInitializer
.getContainingClass();
779 if (aClass
== null) return null;
780 if (!aClass
.isEnum()) return null;
781 final PsiField field
= (PsiField
)resolved
;
782 if (field
.getContainingClass() != aClass
) return null;
783 final PsiType type
= field
.getType();
785 //TODO is access to enum constant is allowed ?
786 if (type
instanceof PsiClassType
&& ((PsiClassType
)type
).resolve() == aClass
) return null;
788 if (PsiUtil
.isCompileTimeConstant(field
)) return null;
790 String description
= JavaErrorMessages
.message(
791 "illegal.to.access.static.member.from.enum.constructor.or.instance.initializer",
792 HighlightMessageUtil
.getSymbolName(resolved
, result
.getSubstitutor())
795 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, expr
, description
);
799 public static HighlightInfo
checkEnumInstantiation(PsiNewExpression expression
) {
800 final PsiType type
= expression
.getType();
801 if (type
instanceof PsiClassType
) {
802 final PsiClass aClass
= ((PsiClassType
)type
).resolve();
803 if (aClass
!= null && aClass
.isEnum()) {
804 String description
= JavaErrorMessages
.message("enum.types.cannot.be.instantiated");
805 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, expression
, description
);
812 public static HighlightInfo
checkGenericArrayCreation(PsiElement element
, PsiType type
) {
813 if (type
instanceof PsiArrayType
) {
814 PsiType componentType
= type
.getDeepComponentType();
815 if (componentType
instanceof PsiClassType
) {
816 final PsiClassType classType
= (PsiClassType
)componentType
;
817 PsiType
[] parameters
= classType
.getParameters();
818 for (PsiType parameter
: parameters
) {
819 if (!(parameter
instanceof PsiWildcardType
) || ((PsiWildcardType
)parameter
).getBound() != null) {
820 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
,
822 JavaErrorMessages
.message("generic.array.creation"));
825 final PsiClass resolved
= ((PsiClassType
)PsiUtil
.convertAnonymousToBaseType(classType
)).resolve();
826 if (resolved
instanceof PsiTypeParameter
) {
827 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
,
829 JavaErrorMessages
.message("generic.array.creation"));
837 private static final MethodSignature ourValuesEnumSyntheticMethod
= MethodSignatureUtil
.createMethodSignature("values",
839 PsiTypeParameter
.EMPTY_ARRAY
,
840 PsiSubstitutor
.EMPTY
);
842 public static boolean isEnumSyntheticMethod(MethodSignature methodSignature
, Project project
) {
843 if (methodSignature
.equals(ourValuesEnumSyntheticMethod
)) return true;
844 final PsiType javaLangString
= PsiType
.getJavaLangString(PsiManager
.getInstance(project
), GlobalSearchScope
.allScope(project
));
845 final MethodSignature valueOfMethod
= MethodSignatureUtil
.createMethodSignature("valueOf", new PsiType
[]{javaLangString
}, PsiTypeParameter
.EMPTY_ARRAY
,
846 PsiSubstitutor
.EMPTY
);
847 return valueOfMethod
.equals(methodSignature
);
850 public static HighlightInfo
checkTypeParametersList(PsiTypeParameterList parameterList
) {
851 PsiTypeParameter
[] typeParameters
= parameterList
.getTypeParameters();
852 if (typeParameters
.length
== 0) return null;
853 if (!PsiUtil
.isLanguageLevel5OrHigher(parameterList
)) {
854 HighlightInfo info
= HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, parameterList
, GENERICS_ARE_NOT_SUPPORTED
);
855 QuickFixAction
.registerQuickFixAction(info
, new ShowModulePropertiesFix(parameterList
));
856 QuickFixAction
.registerQuickFixAction(info
, new IncreaseLanguageLevelFix(LanguageLevel
.JDK_1_5
));
859 final PsiElement parent
= parameterList
.getParent();
860 if (parent
instanceof PsiClass
&& ((PsiClass
)parent
).isEnum()) {
861 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
,
863 JavaErrorMessages
.message("generics.enum.may.not.have.type.parameters"));
865 if (parent
instanceof PsiAnnotationMethod
) {
866 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, parameterList
, JavaErrorMessages
.message("generics.annotation.members.may.not.have.type.parameters"));
868 else if (parent
instanceof PsiClass
&& ((PsiClass
)parent
).isAnnotationType()) {
869 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, parameterList
, JavaErrorMessages
.message("annotation.may.not.have.type.parameters"));
872 for (int i
= 0; i
< typeParameters
.length
; i
++) {
873 final PsiTypeParameter typeParameter1
= typeParameters
[i
];
874 String name1
= typeParameter1
.getName();
875 for (int j
= i
+1; j
< typeParameters
.length
; j
++) {
876 final PsiTypeParameter typeParameter2
= typeParameters
[j
];
877 String name2
= typeParameter2
.getName();
878 if (Comparing
.strEqual(name1
, name2
)) {
879 String message
= JavaErrorMessages
.message("generics.duplicate.type.parameter", name1
);
880 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, typeParameter2
, message
);
887 public static HighlightInfo
checkCatchParameterIsClass(PsiParameter parameter
) {
888 if (parameter
.getDeclarationScope() instanceof PsiCatchSection
) {
889 PsiType type
= parameter
.getType();
890 if (type
instanceof PsiClassType
) {
891 PsiClass aClass
= ((PsiClassType
)type
).resolve();
892 if (aClass
instanceof PsiTypeParameter
) {
893 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
,
894 parameter
.getTypeElement(),
895 JavaErrorMessages
.message("generics.cannot.catch.type.parameters"));
903 public static HighlightInfo
checkInstanceOfGenericType(PsiInstanceOfExpression expression
) {
904 final PsiTypeElement checkTypeElement
= expression
.getCheckType();
905 if (checkTypeElement
== null) return null;
906 PsiElement ref
= checkTypeElement
.getInnermostComponentReferenceElement();
907 while (ref
instanceof PsiJavaCodeReferenceElement
) {
908 final HighlightInfo result
= isIllegalForInstanceOf((PsiJavaCodeReferenceElement
)ref
, checkTypeElement
);
909 if (result
!= null) return result
;
910 ref
= ((PsiQualifiedReference
)ref
).getQualifier();
915 private static HighlightInfo
isIllegalForInstanceOf(PsiJavaCodeReferenceElement ref
, final PsiTypeElement typeElement
) {
916 final PsiElement resolved
= ref
.resolve();
917 if (resolved
instanceof PsiTypeParameter
) {
918 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, ref
, JavaErrorMessages
.message("generics.cannot.instanceof.type.parameters"));
921 final PsiType
[] parameters
= ref
.getTypeParameters();
922 for (PsiType parameterType
: parameters
) {
923 if (parameterType
!= null &&
924 !(parameterType
instanceof PsiWildcardType
&& ((PsiWildcardType
)parameterType
).getBound() == null)) {
925 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, typeElement
, JavaErrorMessages
.message("illegal.generic.type.for.instanceof"));
932 public static HighlightInfo
checkClassObjectAccessExpression(PsiClassObjectAccessExpression expression
) {
933 PsiType type
= expression
.getOperand().getType();
934 if (type
instanceof PsiClassType
) {
935 PsiClass aClass
= ((PsiClassType
)type
).resolve();
936 if (aClass
instanceof PsiTypeParameter
) {
937 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
,
938 expression
.getOperand(),
939 JavaErrorMessages
.message("cannot.select.dot.class.from.type.variable"));
947 public static HighlightInfo
checkOverrideAnnotation(PsiMethod method
) {
948 PsiModifierList list
= method
.getModifierList();
949 final PsiAnnotation overrideAnnotation
= list
.findAnnotation("java.lang.Override");
950 if (overrideAnnotation
== null) {
954 MethodSignatureBackedByPsiMethod superMethod
= SuperMethodsSearch
.search(method
, null, true, false).findFirst();
955 if (superMethod
== null) {
956 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, overrideAnnotation
,
957 JavaErrorMessages
.message("method.doesnot.override.super"));
959 LanguageLevel languageLevel
= PsiUtil
.getLanguageLevel(method
);
960 PsiClass superClass
= superMethod
.getMethod().getContainingClass();
961 if (languageLevel
.equals(LanguageLevel
.JDK_1_5
) &&
962 superClass
!= null &&
963 superClass
.isInterface()) {
964 HighlightInfo info
= HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, overrideAnnotation
, JavaErrorMessages
.message("override.not.allowed.in.interfaces"));
965 QuickFixAction
.registerQuickFixAction(info
, new IncreaseLanguageLevelFix(LanguageLevel
.JDK_1_6
));
970 catch (IndexNotReadyException e
) {
975 static void checkEnumConstantForConstructorProblems(PsiEnumConstant enumConstant
, final HighlightInfoHolder holder
) {
976 PsiClass containingClass
= enumConstant
.getContainingClass();
977 if (enumConstant
.getInitializingClass() == null) {
978 HighlightInfo highlightInfo
= HighlightClassUtil
.checkInstantiationOfAbstractClass(containingClass
, enumConstant
.getNameIdentifier());
979 if (highlightInfo
!= null) {
980 holder
.add(highlightInfo
);
983 highlightInfo
= HighlightClassUtil
.checkClassWithAbstractMethods(enumConstant
.getContainingClass(), enumConstant
.getNameIdentifier().getTextRange());
984 if (highlightInfo
!= null) {
985 holder
.add(highlightInfo
);
989 PsiClassType type
= JavaPsiFacade
.getInstance(enumConstant
.getProject()).getElementFactory().createType(containingClass
);
991 HighlightMethodUtil
.checkConstructorCall(type
.resolveGenerics(), enumConstant
, type
, null, holder
);
994 public static HighlightInfo
checkEnumSuperConstructorCall(PsiMethodCallExpression expr
) {
995 PsiReferenceExpression methodExpression
= expr
.getMethodExpression();
996 final PsiElement refNameElement
= methodExpression
.getReferenceNameElement();
997 if (refNameElement
!= null && PsiKeyword
.SUPER
.equals(refNameElement
.getText())) {
998 final PsiMember constructor
= PsiUtil
.findEnclosingConstructorOrInitializer(expr
);
999 if (constructor
instanceof PsiMethod
&& constructor
.getContainingClass().isEnum()) {
1000 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
,
1002 JavaErrorMessages
.message("call.to.super.is.not.allowed.in.enum.constructor"));
1008 public static HighlightInfo
checkVarArgParameterIsLast(PsiParameter parameter
) {
1009 PsiElement declarationScope
= parameter
.getDeclarationScope();
1010 if (declarationScope
instanceof PsiMethod
) {
1011 PsiParameter
[] params
= ((PsiMethod
)declarationScope
).getParameterList().getParameters();
1012 if (parameter
.isVarArgs()) {
1013 if (!PsiUtil
.getLanguageLevel(parameter
).hasEnumKeywordAndAutoboxing()) {
1014 HighlightInfo info
= HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, parameter
, JavaErrorMessages
.message("varargs.prior.15"));
1015 QuickFixAction
.registerQuickFixAction(info
, new IncreaseLanguageLevelFix(LanguageLevel
.JDK_1_5
));
1019 if (params
[params
.length
- 1] != parameter
) {
1020 HighlightInfo info
= HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, parameter
,
1021 JavaErrorMessages
.message("vararg.not.last.parameter"));
1022 QuickFixAction
.registerQuickFixAction(info
, new MakeVarargParameterLastFix(parameter
), null);
1030 public static List
<HighlightInfo
> checkEnumConstantModifierList(PsiModifierList modifierList
) {
1031 List
<HighlightInfo
> list
= null;
1032 PsiElement
[] children
= modifierList
.getChildren();
1033 for (PsiElement child
: children
) {
1034 if (child
instanceof PsiKeyword
) {
1036 list
= new ArrayList
<HighlightInfo
>();
1038 list
.add(HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
,
1040 JavaErrorMessages
.message("modifiers.for.enum.constants")));
1046 public static HighlightInfo
checkGenericCallWithRawArguments(JavaResolveResult resolveResult
, PsiCallExpression callExpression
) {
1047 final PsiMethod method
= (PsiMethod
)resolveResult
.getElement();
1048 if (method
== null) return null;
1049 final PsiSubstitutor substitutor
= resolveResult
.getSubstitutor();
1050 final PsiExpressionList argumentList
= callExpression
.getArgumentList();
1051 if (argumentList
== null) return null;
1052 final PsiExpression
[] expressions
= argumentList
.getExpressions();
1053 final PsiParameter
[] parameters
= method
.getParameterList().getParameters();
1054 for (int i
= 0; i
< expressions
.length
; i
++) {
1055 PsiParameter parameter
= parameters
[Math
.min(i
, parameters
.length
- 1)];
1056 final PsiExpression expression
= expressions
[i
];
1057 final PsiType parameterType
= substitutor
.substitute(parameter
.getType());
1058 final PsiType expressionType
= substitutor
.substitute(expression
.getType());
1059 if (expressionType
!= null) {
1060 final HighlightInfo highlightInfo
= checkRawToGenericAssignment(parameterType
, expressionType
, expression
);
1061 if (highlightInfo
!= null) return highlightInfo
;
1067 public static HighlightInfo
checkParametersOnRaw(PsiReferenceParameterList refParamList
) {
1068 if (refParamList
.getTypeArguments().length
== 0) return null;
1069 JavaResolveResult resolveResult
= null;
1070 PsiElement parent
= refParamList
.getParent();
1071 if (parent
instanceof PsiJavaCodeReferenceElement
) {
1072 resolveResult
= ((PsiJavaCodeReferenceElement
)parent
).advancedResolve(false);
1073 } else if (parent
instanceof PsiCallExpression
) {
1074 resolveResult
= ((PsiCallExpression
)parent
).resolveMethodGenerics();
1076 if (resolveResult
!= null) {
1077 PsiElement element
= resolveResult
.getElement();
1078 if (!(element
instanceof PsiTypeParameterListOwner
)) return null;
1079 if (((PsiModifierListOwner
)element
).hasModifierProperty(PsiModifier
.STATIC
)) return null;
1080 PsiClass containingClass
= ((PsiMember
)element
).getContainingClass();
1081 if (containingClass
!= null && PsiUtil
.isRawSubstitutor(containingClass
, resolveResult
.getSubstitutor())) {
1082 final String message
= element
instanceof PsiClass
1083 ? JavaErrorMessages
.message("generics.type.arguments.on.raw.type")
1084 : JavaErrorMessages
.message("generics.type.arguments.on.raw.method");
1086 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, refParamList
, message
);
1092 public static HighlightInfo
checkCannotInheritFromEnum(PsiClass superClass
, PsiElement elementToHighlight
) {
1093 HighlightInfo errorResult
= null;
1094 if (Comparing
.strEqual("java.lang.Enum",superClass
.getQualifiedName())) {
1095 String message
= JavaErrorMessages
.message("classes.extends.enum");
1096 errorResult
= HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, elementToHighlight
, message
);
1100 public static HighlightInfo
checkGenericCannotExtendException(PsiReferenceList list
) {
1101 PsiElement parent
= list
.getParent();
1102 if (!(parent
instanceof PsiClass
)) return null;
1103 PsiClass aClass
= (PsiClass
)parent
;
1105 if (!aClass
.hasTypeParameters() || aClass
.getExtendsList() != list
) return null;
1106 PsiJavaCodeReferenceElement
[] referenceElements
= list
.getReferenceElements();
1107 PsiClass throwableClass
= null;
1108 for (PsiJavaCodeReferenceElement referenceElement
: referenceElements
) {
1109 PsiElement resolved
= referenceElement
.resolve();
1110 if (!(resolved
instanceof PsiClass
)) continue;
1111 if (throwableClass
== null) {
1112 throwableClass
= JavaPsiFacade
.getInstance(aClass
.getProject()).findClass("java.lang.Throwable", aClass
.getResolveScope());
1114 if (InheritanceUtil
.isInheritorOrSelf((PsiClass
)resolved
, throwableClass
, true)) {
1115 String message
= JavaErrorMessages
.message("generic.extend.exception");
1116 HighlightInfo highlightInfo
= HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, referenceElement
, message
);
1117 PsiClassType classType
= JavaPsiFacade
.getInstance(aClass
.getProject()).getElementFactory().createType((PsiClass
)resolved
);
1118 QuickFixAction
.registerQuickFixAction(highlightInfo
, QUICK_FIX_FACTORY
.createExtendsListFix(aClass
, classType
, false));
1119 return highlightInfo
;
1125 public static HighlightInfo
checkUncheckedOverriding (PsiMethod overrider
, final List
<HierarchicalMethodSignature
> superMethodSignatures
) {
1126 if (!PsiUtil
.isLanguageLevel5OrHigher(overrider
)) return null;
1127 final HighlightDisplayKey key
= HighlightDisplayKey
.find(UncheckedWarningLocalInspection
.SHORT_NAME
);
1128 final InspectionProfile inspectionProfile
=
1129 InspectionProjectProfileManager
.getInstance(overrider
.getProject()).getInspectionProfile();
1130 if (!inspectionProfile
.isToolEnabled(key
, overrider
)) return null;
1131 final LocalInspectionTool tool
=
1132 ((LocalInspectionToolWrapper
)inspectionProfile
.getInspectionTool(UncheckedWarningLocalInspection
.SHORT_NAME
, overrider
)).getTool();
1133 if (InspectionManagerEx
.inspectionResultSuppressed(overrider
, tool
)) return null;
1134 final MethodSignature signature
= overrider
.getSignature(PsiSubstitutor
.EMPTY
);
1135 for (MethodSignatureBackedByPsiMethod superSignature
: superMethodSignatures
) {
1136 PsiMethod baseMethod
= superSignature
.getMethod();
1137 PsiSubstitutor substitutor
= MethodSignatureUtil
.getSuperMethodSignatureSubstitutor(signature
, superSignature
);
1138 if (substitutor
== null) substitutor
= superSignature
.getSubstitutor();
1139 if (PsiUtil
.isRawSubstitutor(baseMethod
, superSignature
.getSubstitutor())) continue;
1140 final PsiType baseReturnType
= substitutor
.substitute(baseMethod
.getReturnType());
1141 final PsiType overriderReturnType
= overrider
.getReturnType();
1142 if (baseReturnType
== null || overriderReturnType
== null) return null;
1143 if (isRawToGeneric(baseReturnType
, overriderReturnType
)) {
1144 final String message
= JavaErrorMessages
.message("unchecked.overriding.incompatible.return.type",
1145 HighlightUtil
.formatType(overriderReturnType
),
1146 HighlightUtil
.formatType(baseReturnType
));
1148 final PsiTypeElement returnTypeElement
= overrider
.getReturnTypeElement();
1149 LOG
.assertTrue(returnTypeElement
!= null);
1150 final HighlightInfo highlightInfo
= HighlightInfo
.createHighlightInfo(JavaHightlightInfoTypes
.UNCHECKED_WARNING
, returnTypeElement
, message
);
1151 QuickFixAction
.registerQuickFixAction(highlightInfo
,
1152 new EmptyIntentionAction(JavaErrorMessages
.message("unchecked.overriding")),
1155 return highlightInfo
;
1161 public static HighlightInfo
checkEnumMustNotBeLocal(final PsiClass aClass
) {
1162 if (!aClass
.isEnum()) return null;
1163 PsiElement parent
= aClass
.getParent();
1164 if (!(parent
instanceof PsiClass
|| parent
instanceof PsiFile
)) {
1165 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
,
1166 HighlightNamesUtil
.getClassDeclarationTextRange(aClass
),
1167 JavaErrorMessages
.message("local.enum"));
1172 public static HighlightInfo
checkSelectStaticClassFromParameterizedType(final PsiElement resolved
, final PsiJavaCodeReferenceElement ref
) {
1173 if (resolved
instanceof PsiClass
&& ((PsiClass
)resolved
).hasModifierProperty(PsiModifier
.STATIC
)) {
1174 final PsiElement qualifier
= ref
.getQualifier();
1175 if (qualifier
instanceof PsiJavaCodeReferenceElement
) {
1176 final PsiReferenceParameterList parameterList
= ((PsiJavaCodeReferenceElement
)qualifier
).getParameterList();
1177 if (parameterList
!= null && parameterList
.getTypeArguments().length
> 0) {
1178 final String message
= JavaErrorMessages
.message("generics.select.static.class.from.parameterized.type",
1179 HighlightUtil
.formatClass((PsiClass
)resolved
));
1180 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, parameterList
, message
);
1187 public static HighlightInfo
checkCannotInheritFromTypeParameter(final PsiClass superClass
, final PsiJavaCodeReferenceElement toHighlight
) {
1188 if (superClass
instanceof PsiTypeParameter
) {
1189 return HighlightInfo
.createHighlightInfo(HighlightInfoType
.ERROR
, toHighlight
,
1190 JavaErrorMessages
.message("class.cannot.inherit.from.its.type.parameter"));