d95ce00d89b92f9dea37b876e90630b86fd7350a
[idea/community.git] / java / java-analysis-impl / src / com / intellij / codeInsight / daemon / impl / analysis / HighlightVisitorImpl.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.codeInsight.daemon.impl.analysis;
17
18 import com.intellij.codeHighlighting.Pass;
19 import com.intellij.codeInsight.daemon.JavaErrorMessages;
20 import com.intellij.codeInsight.daemon.impl.*;
21 import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil.Feature;
22 import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
23 import com.intellij.codeInsight.intention.QuickFixFactory;
24 import com.intellij.lang.injection.InjectedLanguageManager;
25 import com.intellij.openapi.application.ApplicationManager;
26 import com.intellij.openapi.editor.Document;
27 import com.intellij.openapi.editor.colors.TextAttributesScheme;
28 import com.intellij.openapi.progress.ProgressIndicator;
29 import com.intellij.openapi.progress.ProgressManager;
30 import com.intellij.openapi.project.IndexNotReadyException;
31 import com.intellij.openapi.project.Project;
32 import com.intellij.openapi.projectRoots.JavaSdkVersion;
33 import com.intellij.openapi.projectRoots.JavaVersionService;
34 import com.intellij.openapi.util.Pair;
35 import com.intellij.openapi.util.TextRange;
36 import com.intellij.pom.java.LanguageLevel;
37 import com.intellij.psi.*;
38 import com.intellij.psi.controlFlow.ControlFlowUtil;
39 import com.intellij.psi.impl.source.javadoc.PsiDocMethodOrFieldRef;
40 import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
41 import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
42 import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
43 import com.intellij.psi.infos.CandidateInfo;
44 import com.intellij.psi.infos.MethodCandidateInfo;
45 import com.intellij.psi.javadoc.PsiDocComment;
46 import com.intellij.psi.javadoc.PsiDocTagValue;
47 import com.intellij.psi.util.*;
48 import com.intellij.util.ObjectUtils;
49 import com.intellij.util.containers.MostlySingularMultiMap;
50 import gnu.trove.THashMap;
51 import gnu.trove.THashSet;
52 import gnu.trove.TObjectIntHashMap;
53 import org.jetbrains.annotations.NotNull;
54 import org.jetbrains.annotations.Nullable;
55
56 import java.util.Collection;
57 import java.util.List;
58 import java.util.Map;
59 import java.util.Set;
60
61 public class HighlightVisitorImpl extends JavaElementVisitor implements HighlightVisitor {
62   @NotNull
63   private final PsiResolveHelper myResolveHelper;
64
65   private HighlightInfoHolder myHolder;
66
67   private RefCountHolder myRefCountHolder;
68
69   // map codeBlock->List of PsiReferenceExpression of uninitialized final variables
70   private final Map<PsiElement, Collection<PsiReferenceExpression>> myUninitializedVarProblems = new THashMap<>();
71   // map codeBlock->List of PsiReferenceExpression of extra initialization of final variable
72   private final Map<PsiElement, Collection<ControlFlowUtil.VariableInfo>> myFinalVarProblems = new THashMap<>();
73
74   // value==1: no info if the parameter was reassigned (but the parameter is present in current file), value==2: parameter was reassigned
75   private final TObjectIntHashMap<PsiParameter> myReassignedParameters = new TObjectIntHashMap<>();
76
77   private final Map<String, Pair<PsiImportStaticReferenceElement, PsiClass>> mySingleImportedClasses = new THashMap<>();
78   private final Map<String, Pair<PsiImportStaticReferenceElement, PsiField>> mySingleImportedFields = new THashMap<>();
79   private PsiFile myFile;
80   private final PsiElementVisitor REGISTER_REFERENCES_VISITOR = new PsiRecursiveElementWalkingVisitor() {
81     @Override public void visitElement(PsiElement element) {
82       super.visitElement(element);
83       for (PsiReference reference : element.getReferences()) {
84         PsiElement resolved = reference.resolve();
85         if (resolved instanceof PsiNamedElement) {
86           myRefCountHolder.registerLocallyReferenced((PsiNamedElement)resolved);
87           if (resolved instanceof PsiMember) {
88             myRefCountHolder.registerReference(reference, new CandidateInfo(resolved, PsiSubstitutor.EMPTY));
89           }
90         }
91       }
92     }
93   };
94   private final Map<PsiClass, MostlySingularMultiMap<MethodSignature, PsiMethod>> myDuplicateMethods = new THashMap<>();
95   private final Set<PsiClass> myOverrideEquivalentMethodsVisitedClasses = new THashSet<>();
96   private LanguageLevel myLanguageLevel;
97   private JavaSdkVersion myJavaSdkVersion;
98
99   private static class Holder {
100     private static final boolean CHECK_ELEMENT_LEVEL = ApplicationManager.getApplication().isUnitTestMode() || ApplicationManager.getApplication().isInternal();
101   }
102
103   protected HighlightVisitorImpl(@NotNull PsiResolveHelper resolveHelper) {
104     myResolveHelper = resolveHelper;
105   }
106
107   @NotNull
108   private MostlySingularMultiMap<MethodSignature, PsiMethod> getDuplicateMethods(@NotNull PsiClass aClass) {
109     MostlySingularMultiMap<MethodSignature, PsiMethod> signatures = myDuplicateMethods.get(aClass);
110     if (signatures == null) {
111       signatures = new MostlySingularMultiMap<>();
112       for (PsiMethod method : aClass.getMethods()) {
113         if (method instanceof ExternallyDefinedPsiElement) continue; // ignore aspectj-weaved methods; they are checked elsewhere
114         MethodSignature signature = method.getSignature(PsiSubstitutor.EMPTY);
115         signatures.add(signature, method);
116       }
117
118       myDuplicateMethods.put(aClass, signatures);
119     }
120     return signatures;
121   }
122
123   @Override
124   @NotNull
125   public HighlightVisitorImpl clone() {
126     return new HighlightVisitorImpl(myResolveHelper);
127   }
128
129   @Override
130   public int order() {
131     return 0;
132   }
133
134   @Override
135   public boolean suitableForFile(@NotNull PsiFile file) {
136     // both PsiJavaFile and PsiCodeFragment must match
137     return file instanceof PsiImportHolder && !InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file);
138   }
139
140   @Override
141   public void visit(@NotNull PsiElement element) {
142     if (Holder.CHECK_ELEMENT_LEVEL) {
143       ((CheckLevelHighlightInfoHolder)myHolder).enterLevel(element);
144       element.accept(this);
145       ((CheckLevelHighlightInfoHolder)myHolder).enterLevel(null);
146     }
147     else {
148       element.accept(this);
149     }
150   }
151
152   private void registerReferencesFromInjectedFragments(@NotNull PsiElement element) {
153     InjectedLanguageManager.getInstance(myFile.getProject()).enumerateEx(element, myFile, false,
154                                                                          (injectedPsi, places) -> injectedPsi.accept(REGISTER_REFERENCES_VISITOR)
155     );
156   }
157
158   @Override
159   public boolean analyze(@NotNull final PsiFile file,
160                          final boolean updateWholeFile,
161                          @NotNull final HighlightInfoHolder holder,
162                          @NotNull final Runnable highlight) {
163     myFile = file;
164     myHolder = Holder.CHECK_ELEMENT_LEVEL ? new CheckLevelHighlightInfoHolder(file, holder) : holder;
165     boolean success = true;
166     try {
167       myLanguageLevel = PsiUtil.getLanguageLevel(file);
168       myJavaSdkVersion = ObjectUtils.notNull(JavaVersionService.getInstance().getJavaSdkVersion(file), JavaSdkVersion.fromLanguageLevel(myLanguageLevel));
169       if (updateWholeFile) {
170         final Project project = file.getProject();
171         DaemonCodeAnalyzerEx daemonCodeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(project);
172         final FileStatusMap fileStatusMap = daemonCodeAnalyzer.getFileStatusMap();
173         final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
174         if (progress == null) throw new IllegalStateException("Must be run under progress");
175         final RefCountHolder refCountHolder = RefCountHolder.get(file);
176         myRefCountHolder = refCountHolder;
177         final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
178         TextRange dirtyScope = ObjectUtils.notNull(document == null ? null : fileStatusMap.getFileDirtyScope(document, Pass.UPDATE_ALL), file.getTextRange());
179         success = refCountHolder.analyze(file, dirtyScope, progress, () -> {
180           highlight.run();
181           progress.checkCanceled();
182           PostHighlightingVisitor highlightingVisitor = new PostHighlightingVisitor(file, document, refCountHolder);
183           highlightingVisitor.collectHighlights(holder, progress);
184         });
185       }
186       else {
187         myRefCountHolder = null;
188         highlight.run();
189       }
190     }
191     finally {
192       myUninitializedVarProblems.clear();
193       myFinalVarProblems.clear();
194       mySingleImportedClasses.clear();
195       mySingleImportedFields.clear();
196       myReassignedParameters.clear();
197
198       myRefCountHolder = null;
199       myFile = null;
200       myHolder = null;
201       myDuplicateMethods.clear();
202       myOverrideEquivalentMethodsVisitedClasses.clear();
203     }
204
205     return success;
206   }
207
208   @Override
209   public void visitElement(PsiElement element) {
210     if (myRefCountHolder != null && myFile instanceof ServerPageFile) {
211       // in JSP, XmlAttributeValue may contain java references
212       try {
213         for (PsiReference reference : element.getReferences()) {
214           if (reference instanceof PsiJavaReference) {
215             PsiJavaReference psiJavaReference = (PsiJavaReference)reference;
216             myRefCountHolder.registerReference(psiJavaReference, psiJavaReference.advancedResolve(false));
217           }
218         }
219       }
220       catch (IndexNotReadyException ignored) { }
221     }
222
223     if (!(myFile instanceof ServerPageFile)) {
224       myHolder.add(DefaultHighlightUtil.checkBadCharacter(element));
225     }
226   }
227
228   @Override
229   public void visitAnnotation(PsiAnnotation annotation) {
230     super.visitAnnotation(annotation);
231     if (!myHolder.hasErrorResults()) myHolder.add(checkFeature(annotation, Feature.ANNOTATIONS));
232     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkApplicability(annotation, myLanguageLevel, myFile));
233     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkAnnotationType(annotation));
234     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkMissingAttributes(annotation));
235     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkTargetAnnotationDuplicates(annotation));
236     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkDuplicateAnnotations(annotation, myLanguageLevel));
237     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkForeignInnerClassesUsed(annotation));
238     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkFunctionalInterface(annotation, myLanguageLevel));
239     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkRepeatableAnnotation(annotation));
240     if (CommonClassNames.JAVA_LANG_OVERRIDE.equals(annotation.getQualifiedName())) {
241       PsiAnnotationOwner owner = annotation.getOwner();
242       PsiElement parent = owner instanceof PsiModifierList ? ((PsiModifierList)owner).getParent() : null;
243       if (parent instanceof PsiMethod) {
244         myHolder.add(GenericsHighlightUtil.checkOverrideAnnotation((PsiMethod)parent, annotation, myLanguageLevel));
245       }
246     }
247   }
248
249   @Override
250   public void visitAnnotationArrayInitializer(PsiArrayInitializerMemberValue initializer) {
251     PsiMethod method = null;
252     PsiElement parent = initializer.getParent();
253     if (parent instanceof PsiNameValuePair) {
254       method = (PsiMethod)parent.getReference().resolve();
255     }
256     else if (PsiUtil.isAnnotationMethod(parent)) {
257       method = (PsiMethod)parent;
258     }
259     if (method != null) {
260       PsiType type = method.getReturnType();
261       if (type instanceof PsiArrayType) {
262         type = ((PsiArrayType)type).getComponentType();
263         PsiAnnotationMemberValue[] initializers = initializer.getInitializers();
264         for (PsiAnnotationMemberValue initializer1 : initializers) {
265           myHolder.add(AnnotationsHighlightUtil.checkMemberValueType(initializer1, type));
266         }
267       }
268     }
269   }
270
271   @Override
272   public void visitAnnotationMethod(PsiAnnotationMethod method) {
273     PsiType returnType = method.getReturnType();
274     PsiAnnotationMemberValue value = method.getDefaultValue();
275     if (returnType != null && value != null) {
276       myHolder.add(AnnotationsHighlightUtil.checkMemberValueType(value, returnType));
277     }
278
279     myHolder.add(AnnotationsHighlightUtil.checkValidAnnotationType(method.getReturnType(), method.getReturnTypeElement()));
280     final PsiClass aClass = method.getContainingClass();
281     myHolder.add(AnnotationsHighlightUtil.checkCyclicMemberType(method.getReturnTypeElement(), aClass));
282     myHolder.add(AnnotationsHighlightUtil.checkClashesWithSuperMethods(method));
283
284     if (!myHolder.hasErrorResults() && aClass != null) {
285       myHolder.add(HighlightMethodUtil.checkDuplicateMethod(aClass, method, getDuplicateMethods(aClass)));
286     }
287   }
288
289   @Override
290   public void visitArrayInitializerExpression(PsiArrayInitializerExpression expression) {
291     super.visitArrayInitializerExpression(expression);
292     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkArrayInitializerApplicable(expression));
293     if (!(expression.getParent() instanceof PsiNewExpression)) {
294       if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkGenericArrayCreation(expression, expression.getType()));
295     }
296   }
297
298   @Override
299   public void visitAssignmentExpression(PsiAssignmentExpression assignment) {
300     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentCompatibleTypes(assignment));
301     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentOperatorApplicable(assignment));
302     if (!myHolder.hasErrorResults()) visitExpression(assignment);
303   }
304
305   @Override
306   public void visitPolyadicExpression(PsiPolyadicExpression expression) {
307     super.visitPolyadicExpression(expression);
308     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkPolyadicOperatorApplicable(expression));
309   }
310
311   @Override
312   public void visitLambdaExpression(PsiLambdaExpression expression) {
313     myHolder.add(checkFeature(expression, Feature.LAMBDA_EXPRESSIONS));
314     if (!myHolder.hasErrorResults()) {
315       if (LambdaUtil.isValidLambdaContext(expression.getParent())) {
316         final PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
317         if (functionalInterfaceType != null) {
318           final String notFunctionalMessage = LambdaHighlightingUtil.checkInterfaceFunctional(functionalInterfaceType);
319           if (notFunctionalMessage != null) {
320             HighlightInfo result =
321               HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(notFunctionalMessage)
322                 .create();
323             myHolder.add(result);
324           }
325           else {
326             final PsiElement parent = PsiUtil.skipParenthesizedExprUp(expression.getParent());
327             final PsiCallExpression callExpression = parent instanceof PsiExpressionList && parent.getParent() instanceof PsiCallExpression ?
328                                                      (PsiCallExpression)parent.getParent() : null;
329             final JavaResolveResult containingCallResolveResult = callExpression != null ? callExpression.resolveMethodGenerics() : null;
330             final String errorMessage;
331             if (containingCallResolveResult instanceof MethodCandidateInfo) {
332               errorMessage = ((MethodCandidateInfo)containingCallResolveResult).getParentInferenceErrorMessage((PsiExpressionList)parent);
333             }
334             else {
335               errorMessage = null;
336             }
337             if (errorMessage != null) {
338               HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
339                 .range(expression).descriptionAndTooltip(errorMessage).create();
340               myHolder.add(result);
341             }
342             else {
343               final Map<PsiElement, String> returnErrors = LambdaUtil
344                 .checkReturnTypeCompatible(expression, LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType));
345               if (returnErrors != null) {
346                 for (Map.Entry<PsiElement, String> entry : returnErrors.entrySet()) {
347                   myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
348                                  .range(entry.getKey())
349                                  .descriptionAndTooltip(entry.getValue()).create());
350                 }
351               }
352               else {
353                 final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
354                 final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
355                 if (interfaceMethod != null) {
356                   final PsiParameter[] parameters = interfaceMethod.getParameterList().getParameters();
357                   HighlightInfo result = LambdaHighlightingUtil
358                     .checkParametersCompatible(expression, parameters, LambdaUtil.getSubstitutor(interfaceMethod, resolveResult));
359                   if (result != null) {
360                     myHolder.add(result);
361                   }
362                   else {
363                     checkFunctionalInterfaceTypeAccessible(expression, functionalInterfaceType);
364                   }
365                 }
366               }
367             }
368           }
369         }
370         else if (LambdaUtil.getFunctionalInterfaceType(expression, true) != null) {
371           myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip("Cannot infer functional interface type").create());
372         }
373       }
374       else {
375         HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression)
376           .descriptionAndTooltip("Lambda expression not expected here").create();
377         myHolder.add(result);
378       }
379       if (!myHolder.hasErrorResults()) {
380         final PsiElement body = expression.getBody();
381         if (body instanceof PsiCodeBlock) {
382           myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement((PsiCodeBlock)body));
383         }
384       }
385     }
386   }
387
388   @Override
389   public void visitBreakStatement(PsiBreakStatement statement) {
390     super.visitBreakStatement(statement);
391     if (!myHolder.hasErrorResults()) {
392       myHolder.add(HighlightUtil.checkLabelDefined(statement.getLabelIdentifier(), statement.findExitedStatement()));
393     }
394     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkBreakOutsideLoop(statement));
395   }
396
397   @Override
398   public void visitClass(PsiClass aClass) {
399     super.visitClass(aClass);
400     if (aClass instanceof PsiSyntheticClass) return;
401     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkInterfaceMultipleInheritance(aClass));
402     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.areSupersAccessible(aClass));
403     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkDuplicateTopLevelClass(aClass));
404     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumMustNotBeLocal(aClass));
405     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumWithoutConstantsCantHaveAbstractMethods(aClass));
406     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkImplicitThisReferenceBeforeSuper(aClass, myJavaSdkVersion));
407     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassAndPackageConflict(aClass));
408     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkPublicClassInRightFile(aClass));
409     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkTypeParameterOverrideEquivalentMethods(aClass, myLanguageLevel));
410   }
411
412   @Override
413   public void visitClassInitializer(PsiClassInitializer initializer) {
414     super.visitClassInitializer(initializer);
415     if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkInitializerCompleteNormally(initializer));
416     if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement(initializer.getBody()));
417     if (!myHolder.hasErrorResults()) {
418       myHolder.add(HighlightClassUtil.checkThingNotAllowedInInterface(initializer, initializer.getContainingClass()));
419     }
420   }
421
422   @Override
423   public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
424     super.visitClassObjectAccessExpression(expression);
425     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkClassObjectAccessExpression(expression));
426   }
427
428   @Override
429   public void visitComment(PsiComment comment) {
430     super.visitComment(comment);
431     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnclosedComment(comment));
432     if (myRefCountHolder != null && !myHolder.hasErrorResults()) registerReferencesFromInjectedFragments(comment);
433   }
434
435   @Override
436   public void visitContinueStatement(PsiContinueStatement statement) {
437     super.visitContinueStatement(statement);
438     if (!myHolder.hasErrorResults()) {
439       myHolder.add(HighlightUtil.checkLabelDefined(statement.getLabelIdentifier(), statement.findContinuedStatement()));
440     }
441     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkContinueOutsideLoop(statement));
442   }
443
444   @Override
445   public void visitJavaToken(PsiJavaToken token) {
446     super.visitJavaToken(token);
447     if (!myHolder.hasErrorResults()
448         && token.getTokenType() == JavaTokenType.RBRACE
449         && token.getParent() instanceof PsiCodeBlock) {
450
451       final PsiElement gParent = token.getParent().getParent();
452       final PsiCodeBlock codeBlock;
453       final PsiType returnType;
454       if (gParent instanceof PsiMethod) {
455         PsiMethod method = (PsiMethod)gParent;
456         codeBlock = method.getBody();
457         returnType = method.getReturnType();
458       }
459       else if (gParent instanceof PsiLambdaExpression) {
460         final PsiElement body = ((PsiLambdaExpression)gParent).getBody();
461         if (!(body instanceof PsiCodeBlock)) return;
462         codeBlock = (PsiCodeBlock)body;
463         returnType = LambdaUtil.getFunctionalInterfaceReturnType((PsiLambdaExpression)gParent);
464       }
465       else {
466         return;
467       }
468       myHolder.add(HighlightControlFlowUtil.checkMissingReturnStatement(codeBlock, returnType));
469     }
470   }
471
472   @Override
473   public void visitDocComment(PsiDocComment comment) {
474     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnclosedComment(comment));
475   }
476
477   @Override
478   public void visitDocTagValue(PsiDocTagValue value) {
479     PsiReference reference = value.getReference();
480     if (reference != null) {
481       PsiElement element = reference.resolve();
482       final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
483       if (element instanceof PsiMethod) {
484         myHolder.add(HighlightNamesUtil.highlightMethodName((PsiMethod)element, ((PsiDocMethodOrFieldRef)value).getNameElement(), false,
485                                                             colorsScheme));
486       }
487       else if (element instanceof PsiParameter) {
488         myHolder.add(HighlightNamesUtil.highlightVariableName((PsiVariable)element, value.getNavigationElement(), colorsScheme));
489       }
490     }
491   }
492
493   @Override
494   public void visitEnumConstant(PsiEnumConstant enumConstant) {
495     super.visitEnumConstant(enumConstant);
496     if (!myHolder.hasErrorResults()) GenericsHighlightUtil.checkEnumConstantForConstructorProblems(enumConstant, myHolder, myJavaSdkVersion);
497     if (!myHolder.hasErrorResults()) registerConstructorCall(enumConstant);
498     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnhandledExceptions(enumConstant, null));
499   }
500
501   @Override
502   public void visitEnumConstantInitializer(PsiEnumConstantInitializer enumConstantInitializer) {
503     super.visitEnumConstantInitializer(enumConstantInitializer);
504     if (!myHolder.hasErrorResults()) {
505       TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(enumConstantInitializer);
506       myHolder.add(HighlightClassUtil.checkClassMustBeAbstract(enumConstantInitializer, textRange));
507     }
508   }
509
510   @Override
511   public void visitExpression(PsiExpression expression) {
512     ProgressManager.checkCanceled(); // visitLiteralExpression is invoked very often in array initializers
513
514     super.visitExpression(expression);
515     PsiType type = expression.getType();
516     if (myHolder.add(HighlightUtil.checkMustBeBoolean(expression, type))) return;
517
518     if (expression instanceof PsiArrayAccessExpression) {
519       myHolder.add(HighlightUtil.checkValidArrayAccessExpression((PsiArrayAccessExpression)expression));
520     }
521
522     PsiElement parent = expression.getParent();
523     if (parent instanceof PsiNewExpression
524         && ((PsiNewExpression)parent).getQualifier() != expression
525         && ((PsiNewExpression)parent).getArrayInitializer() != expression) {
526       // like in 'new String["s"]'
527       myHolder.add(HighlightUtil.checkAssignability(PsiType.INT, expression.getType(), expression, expression));
528     }
529     if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkCannotWriteToFinal(expression,myFile));
530     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkVariableExpected(expression));
531     if (!myHolder.hasErrorResults()) myHolder.addAll(HighlightUtil.checkArrayInitializer(expression, type));
532     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTernaryOperatorConditionIsBoolean(expression, type));
533     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssertOperatorTypes(expression, type));
534     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSynchronizedExpressionType(expression, type, myFile));
535     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkConditionalExpressionBranchTypesMatch(expression, type));
536     if (!myHolder.hasErrorResults()
537         && parent instanceof PsiThrowStatement
538         && ((PsiThrowStatement)parent).getException() == expression) {
539       myHolder.add(HighlightUtil.checkMustBeThrowable(type, expression, true));
540     }
541
542     if (!myHolder.hasErrorResults()) {
543       myHolder.add(AnnotationsHighlightUtil.checkConstantExpression(expression));
544     }
545     if (!myHolder.hasErrorResults() && parent instanceof PsiForeachStatement && ((PsiForeachStatement)parent).getIteratedValue() == expression) {
546       myHolder.add(GenericsHighlightUtil.checkForeachExpressionTypeIsIterable(expression));
547     }
548   }
549
550   @Override
551   public void visitExpressionList(PsiExpressionList list) {
552     super.visitExpressionList(list);
553     PsiElement parent = list.getParent();
554     if (parent instanceof PsiMethodCallExpression) {
555       PsiMethodCallExpression expression = (PsiMethodCallExpression)parent;
556       if (expression.getArgumentList() == list) {
557         PsiReferenceExpression referenceExpression = expression.getMethodExpression();
558         JavaResolveResult result;
559         JavaResolveResult[] results;
560         try {
561           results = resolveOptimised(referenceExpression);
562           result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
563         }
564         catch (IndexNotReadyException e) {
565           return;
566         }
567         PsiElement resolved = result.getElement();
568
569         if ((!result.isAccessible() || !result.isStaticsScopeCorrect()) &&
570             !HighlightMethodUtil.isDummyConstructorCall(expression, myResolveHelper, list, referenceExpression) &&
571             // this check is for fake expression from JspMethodCallImpl
572             referenceExpression.getParent() == expression) {
573           try {
574             if (PsiTreeUtil.findChildrenOfType(expression.getArgumentList(), PsiLambdaExpression.class).isEmpty()) {
575               myHolder.add(HighlightMethodUtil.checkAmbiguousMethodCallArguments(referenceExpression, results, list, resolved, result, expression, myResolveHelper, list));
576             }
577           }
578           catch (IndexNotReadyException ignored) { }
579         }
580       }
581     }
582   }
583
584   @Override
585   public void visitField(PsiField field) {
586     super.visitField(field);
587     if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkFinalFieldInitialized(field));
588   }
589
590   @Override
591   public void visitForStatement(PsiForStatement statement) {
592     myHolder.add(HighlightUtil.checkForStatement(statement));
593   }
594
595   @Override
596   public void visitForeachStatement(PsiForeachStatement statement) {
597     myHolder.add(checkFeature(statement, Feature.FOR_EACH));
598   }
599
600   @Override
601   public void visitImportStaticStatement(PsiImportStaticStatement statement) {
602     myHolder.add(checkFeature(statement, Feature.STATIC_IMPORTS));
603   }
604
605   @Override
606   public void visitIdentifier(final PsiIdentifier identifier) {
607     TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
608
609     PsiElement parent = identifier.getParent();
610     if (parent instanceof PsiVariable) {
611       PsiVariable variable = (PsiVariable)parent;
612       myHolder.add(HighlightUtil.checkVariableAlreadyDefined(variable));
613
614       if (variable.getInitializer() == null) {
615         final PsiElement child = variable.getLastChild();
616         if (child instanceof PsiErrorElement && child.getPrevSibling() == identifier) return;
617       }
618
619       boolean isMethodParameter = variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiMethod;
620       if (isMethodParameter) {
621         myReassignedParameters.put((PsiParameter)variable, 1); // mark param as present in current file
622       }
623       else {
624         // method params are highlighted in visitMethod since we should make sure the method body was visited before
625         if (HighlightControlFlowUtil.isReassigned(variable, myFinalVarProblems)) {
626           myHolder.add(HighlightNamesUtil.highlightReassignedVariable(variable, identifier));
627         }
628         else {
629           myHolder.add(HighlightNamesUtil.highlightVariableName(variable, identifier, colorsScheme));
630         }
631       }
632     }
633     else if (parent instanceof PsiClass) {
634       PsiClass aClass = (PsiClass)parent;
635       if (aClass.isAnnotationType()) {
636         myHolder.add(checkFeature(identifier, Feature.ANNOTATIONS));
637       }
638
639       myHolder.add(HighlightClassUtil.checkClassAlreadyImported(aClass, identifier));
640       if (!(parent instanceof PsiAnonymousClass) && aClass.getNameIdentifier() == identifier) {
641         myHolder.add(HighlightNamesUtil.highlightClassName(aClass, identifier, colorsScheme));
642       }
643       if (!myHolder.hasErrorResults() && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
644         myHolder.add(GenericsHighlightUtil.checkUnrelatedDefaultMethods(aClass, identifier));
645       }
646
647       if (!myHolder.hasErrorResults()) {
648         myHolder.add(GenericsHighlightUtil.checkUnrelatedConcrete(aClass, identifier));
649       }
650     }
651     else if (parent instanceof PsiMethod) {
652       PsiMethod method = (PsiMethod)parent;
653       if (method.isConstructor()) {
654         myHolder.add(HighlightMethodUtil.checkConstructorName(method));
655       }
656       myHolder.add(HighlightNamesUtil.highlightMethodName(method, identifier, true, colorsScheme));
657       final PsiClass aClass = method.getContainingClass();
658       if (aClass != null) {
659         myHolder.add(GenericsHighlightUtil.checkDefaultMethodOverrideEquivalentToObjectNonPrivate(myLanguageLevel, aClass, method, identifier));
660       }
661     }
662
663     myHolder.add(HighlightUtil.checkUnderscore(identifier, myLanguageLevel));
664
665     super.visitIdentifier(identifier);
666   }
667
668   @Override
669   public void visitImportStatement(final PsiImportStatement statement) {
670     if (!myHolder.hasErrorResults()) {
671       myHolder.add(HighlightUtil.checkSingleImportClassConflict(statement, mySingleImportedClasses,myFile));
672     }
673   }
674
675   @Override
676   public void visitImportStaticReferenceElement(@NotNull PsiImportStaticReferenceElement ref) {
677     final String refName = ref.getReferenceName();
678     final JavaResolveResult[] results = ref.multiResolve(false);
679
680     final PsiElement referenceNameElement = ref.getReferenceNameElement();
681     if (results.length == 0) {
682       final String description = JavaErrorMessages.message("cannot.resolve.symbol", refName);
683       assert referenceNameElement != null : ref;
684       final HighlightInfo info =
685         HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(referenceNameElement).descriptionAndTooltip(description).create();
686       QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createSetupJDKFix());
687       myHolder.add(info);
688     }
689     else {
690       final PsiManager manager = ref.getManager();
691       for (JavaResolveResult result : results) {
692         final PsiElement element = result.getElement();
693
694         String description = null;
695         if (element instanceof PsiClass) {
696           final Pair<PsiImportStaticReferenceElement, PsiClass> imported = mySingleImportedClasses.get(refName);
697           final PsiClass aClass = imported == null ? null : imported.getSecond();
698           if (aClass != null && !manager.areElementsEquivalent(aClass, element)) {
699             description = imported.first == null
700                           ? JavaErrorMessages.message("single.import.class.conflict", refName)
701                           : imported.first.equals(ref)
702                             ? JavaErrorMessages.message("class.is.ambiguous.in.single.static.import", refName)
703                             : JavaErrorMessages.message("class.is.already.defined.in.single.static.import", refName);
704           }
705           mySingleImportedClasses.put(refName, Pair.create(ref, (PsiClass)element));
706         }
707         else if (element instanceof PsiField) {
708           final Pair<PsiImportStaticReferenceElement, PsiField> imported = mySingleImportedFields.get(refName);
709           final PsiField field = imported == null ? null : imported.getSecond();
710           if (field != null && !manager.areElementsEquivalent(field, element)) {
711             description = imported.first.equals(ref)
712                           ? JavaErrorMessages.message("field.is.ambiguous.in.single.static.import", refName)
713                           : JavaErrorMessages.message("field.is.already.defined.in.single.static.import", refName);
714           }
715           mySingleImportedFields.put(refName, Pair.create(ref, (PsiField)element));
716         }
717
718         if (description != null) {
719           myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(ref).descriptionAndTooltip(description).create());
720         }
721       }
722     }
723     if (!myHolder.hasErrorResults()) {
724       final PsiElement resolved = results.length == 1 ? results[0].getElement() : null;
725       final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
726       if (resolved instanceof PsiClass) {
727         myHolder.add(HighlightNamesUtil.highlightClassName((PsiClass)resolved, ref, colorsScheme));
728       }
729       else{
730         myHolder.add(HighlightNamesUtil.highlightClassNameInQualifier(ref, colorsScheme));
731         if (resolved instanceof PsiVariable) {
732           myHolder.add(HighlightNamesUtil.highlightVariableName((PsiVariable)resolved, referenceNameElement, colorsScheme));
733         }
734         else if (resolved instanceof PsiMethod) {
735           myHolder.add(HighlightNamesUtil.highlightMethodName((PsiMethod)resolved, referenceNameElement, false, colorsScheme));
736         }
737       }
738     }
739   }
740
741   @Override
742   public void visitInstanceOfExpression(PsiInstanceOfExpression expression) {
743     super.visitInstanceOfExpression(expression);
744     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInstanceOfApplicable(expression));
745     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkInstanceOfGenericType(expression));
746   }
747
748   @Override
749   public void visitKeyword(PsiKeyword keyword) {
750     super.visitKeyword(keyword);
751     PsiElement parent = keyword.getParent();
752     String text = keyword.getText();
753     if (parent instanceof PsiModifierList) {
754       PsiModifierList psiModifierList = (PsiModifierList)parent;
755       if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkNotAllowedModifier(keyword, psiModifierList));
756       if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalModifierCombination(keyword, psiModifierList));
757       if (PsiModifier.ABSTRACT.equals(text) && psiModifierList.getParent() instanceof PsiMethod) {
758         if (!myHolder.hasErrorResults()) {
759           myHolder.add(HighlightMethodUtil.checkAbstractMethodInConcreteClass((PsiMethod)psiModifierList.getParent(), keyword));
760         }
761       }
762     }
763     else if (PsiKeyword.INTERFACE.equals(text) && parent instanceof PsiClass) {
764       if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkInterfaceCannotBeLocal((PsiClass)parent));
765     }
766     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkStaticDeclarationInInnerClass(keyword));
767     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalVoidType(keyword));
768   }
769
770   @Override
771   public void visitLabeledStatement(PsiLabeledStatement statement) {
772     super.visitLabeledStatement(statement);
773     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkLabelWithoutStatement(statement));
774     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkLabelAlreadyInUse(statement));
775   }
776
777   @Override
778   public void visitLiteralExpression(PsiLiteralExpression expression) {
779     super.visitLiteralExpression(expression);
780     if (myHolder.hasErrorResults()) return;
781     myHolder.add(HighlightUtil.checkLiteralExpressionParsingError(expression, myLanguageLevel,myFile));
782     if (myRefCountHolder != null && !myHolder.hasErrorResults()) registerReferencesFromInjectedFragments(expression);
783   }
784
785   @Override
786   public void visitMethod(PsiMethod method) {
787     super.visitMethod(method);
788     if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement(method.getBody()));
789     if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorHandleSuperClassExceptions(method));
790     if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkRecursiveConstructorInvocation(method));
791     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkSafeVarargsAnnotation(method, myLanguageLevel));
792
793     PsiClass aClass = method.getContainingClass();
794     if (!myHolder.hasErrorResults() && method.isConstructor()) {
795       myHolder.add(HighlightClassUtil.checkThingNotAllowedInInterface(method, aClass));
796     }
797     if (!myHolder.hasErrorResults() && method.hasModifierProperty(PsiModifier.DEFAULT)) {
798       myHolder.add(checkFeature(method, Feature.EXTENSION_METHODS));
799     }
800     if (!myHolder.hasErrorResults() && aClass != null && aClass.isInterface() && method.hasModifierProperty(PsiModifier.STATIC)) {
801       myHolder.add(checkFeature(method, Feature.EXTENSION_METHODS));
802     }
803     if (!myHolder.hasErrorResults() && aClass != null) {
804       myHolder.add(HighlightMethodUtil.checkDuplicateMethod(aClass, method, getDuplicateMethods(aClass)));
805     }
806
807     // method params are highlighted in visitMethod since we should make sure the method body was visited before
808     PsiParameter[] parameters = method.getParameterList().getParameters();
809     final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
810
811     for (PsiParameter parameter : parameters) {
812       int info = myReassignedParameters.get(parameter);
813       if (info == 0) continue; // out of this file
814       if (info == 2) {// reassigned
815         myHolder.add(HighlightNamesUtil.highlightReassignedVariable(parameter, parameter.getNameIdentifier()));
816       }
817       else {
818         myHolder.add(HighlightNamesUtil.highlightVariableName(parameter, parameter.getNameIdentifier(), colorsScheme));
819       }
820     }
821   }
822
823   private void highlightReferencedMethodOrClassName(@NotNull PsiJavaCodeReferenceElement element, PsiElement resolved) {
824     PsiElement parent = element.getParent();
825     final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
826     if (parent instanceof PsiMethodCallExpression) {
827       PsiMethod method = ((PsiMethodCallExpression)parent).resolveMethod();
828       PsiElement methodNameElement = element.getReferenceNameElement();
829       if (method != null && methodNameElement != null&& !(methodNameElement instanceof PsiKeyword)) {
830         myHolder.add(HighlightNamesUtil.highlightMethodName(method, methodNameElement, false, colorsScheme));
831         myHolder.add(HighlightNamesUtil.highlightClassNameInQualifier(element, colorsScheme));
832       }
833     }
834     else if (parent instanceof PsiConstructorCall) {
835       try {
836         PsiMethod method = ((PsiConstructorCall)parent).resolveConstructor();
837         PsiMember methodOrClass = method != null ? method : resolved instanceof PsiClass ? (PsiClass)resolved : null;
838         if (methodOrClass != null) {
839           final PsiElement referenceNameElement = element.getReferenceNameElement();
840           if(referenceNameElement != null) {
841             // exclude type parameters from the highlighted text range
842             TextRange range = referenceNameElement.getTextRange();
843             myHolder.add(HighlightNamesUtil.highlightMethodName(methodOrClass, referenceNameElement, range, colorsScheme, false));
844           }
845         }
846       }
847       catch (IndexNotReadyException ignored) { }
848     }
849     else if (resolved instanceof PsiPackage) {
850       // highlight package (and following dot) as a class
851       myHolder.add(HighlightNamesUtil.highlightPackage(resolved, element, colorsScheme));
852     }
853     else if (resolved instanceof PsiClass) {
854       myHolder.add(HighlightNamesUtil.highlightClassName((PsiClass)resolved, element, colorsScheme));
855     }
856   }
857
858   @Override
859   public void visitMethodCallExpression(PsiMethodCallExpression expression) {
860     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumSuperConstructorCall(expression));
861     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkSuperQualifierType(myFile.getProject(), expression));
862     // in case of JSP synthetic method call, do not check
863     if (myFile.isPhysical() && !myHolder.hasErrorResults()) {
864       try {
865         myHolder.add(HighlightMethodUtil.checkMethodCall(expression, myResolveHelper, myLanguageLevel,myJavaSdkVersion));
866       }
867       catch (IndexNotReadyException ignored) { }
868     }
869
870     if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallMustBeFirstStatement(expression));
871     if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkSuperAbstractMethodDirectCall(expression));
872
873     if (!myHolder.hasErrorResults()) visitExpression(expression);
874   }
875
876   @Override
877   public void visitModifierList(PsiModifierList list) {
878     super.visitModifierList(list);
879     PsiElement parent = list.getParent();
880     if (parent instanceof PsiMethod) {
881       PsiMethod method = (PsiMethod)parent;
882       if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodCanHaveBody(method, myLanguageLevel));
883       MethodSignatureBackedByPsiMethod methodSignature = MethodSignatureBackedByPsiMethod.create(method, PsiSubstitutor.EMPTY);
884       if (!method.isConstructor()) {
885         try {
886           List<HierarchicalMethodSignature> superMethodSignatures = method.getHierarchicalMethodSignature().getSuperSignatures();
887           if (!superMethodSignatures.isEmpty()) {
888             if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodIncompatibleReturnType(methodSignature, superMethodSignatures, true));
889             if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodIncompatibleThrows(methodSignature, superMethodSignatures, true, method.getContainingClass()));
890             if (!method.hasModifierProperty(PsiModifier.STATIC)) {
891               if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodWeakerPrivileges(methodSignature, superMethodSignatures, true, myFile));
892               if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodOverridesFinal(methodSignature, superMethodSignatures));
893             }
894           }
895         }
896         catch (IndexNotReadyException ignored) { }
897       }
898       PsiClass aClass = method.getContainingClass();
899       if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodMustHaveBody(method, aClass));
900       if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallsBaseClassConstructor(method, myRefCountHolder, myResolveHelper));
901       if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkStaticMethodOverride(method,myFile));
902       if (!myHolder.hasErrorResults() && aClass != null &&
903           myOverrideEquivalentMethodsVisitedClasses.add(aClass)) {
904         myHolder.addAll(GenericsHighlightUtil.checkOverrideEquivalentMethods(aClass));
905       }
906     }
907     else if (parent instanceof PsiClass) {
908       PsiClass aClass = (PsiClass)parent;
909       try {
910         if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkDuplicateNestedClass(aClass));
911         if (!myHolder.hasErrorResults()) {
912           TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass);
913           myHolder.add(HighlightClassUtil.checkClassMustBeAbstract(aClass, textRange));
914         }
915         if (!myHolder.hasErrorResults()) {
916           myHolder.add(HighlightClassUtil.checkClassDoesNotCallSuperConstructorOrHandleExceptions(aClass, myRefCountHolder, myResolveHelper));
917         }
918         if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkOverrideEquivalentInheritedMethods(aClass, myFile, myLanguageLevel));
919         if (!myHolder.hasErrorResults() && myOverrideEquivalentMethodsVisitedClasses.add(aClass)) {
920           myHolder.addAll(GenericsHighlightUtil.checkOverrideEquivalentMethods(aClass));
921         }
922         if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCyclicInheritance(aClass));
923       }
924       catch (IndexNotReadyException ignored) {
925       }
926     }
927     else if (parent instanceof PsiEnumConstant) {
928       if (!myHolder.hasErrorResults()) myHolder.addAll(GenericsHighlightUtil.checkEnumConstantModifierList(list));
929     }
930   }
931
932   @Override
933   public void visitNameValuePair(PsiNameValuePair pair) {
934     myHolder.add(AnnotationsHighlightUtil.checkNameValuePair(pair));
935     if (!myHolder.hasErrorResults()) {
936       PsiIdentifier nameId = pair.getNameIdentifier();
937       if (nameId != null) {
938         HighlightInfo result = HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.ANNOTATION_ATTRIBUTE_NAME).range(nameId).create();
939         myHolder.add(result);
940       }
941     }
942   }
943
944   @Override
945   public void visitNewExpression(PsiNewExpression expression) {
946     final PsiType type = expression.getType();
947     final PsiClass aClass = PsiUtil.resolveClassInType(type);
948     myHolder.add(HighlightUtil.checkUnhandledExceptions(expression, null));
949     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkAnonymousInheritFinal(expression));
950     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkQualifiedNew(expression, type, aClass));
951     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCreateInnerClassFromStaticContext(expression, type, aClass));
952     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkTypeParameterInstantiation(expression));
953     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkInstantiationOfAbstractClass(aClass, expression));
954     try {
955       if (!myHolder.hasErrorResults()) HighlightMethodUtil.checkNewExpression(expression, type, myHolder, myJavaSdkVersion);
956     }
957     catch (IndexNotReadyException ignored) { }
958     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumInstantiation(expression, aClass));
959     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkGenericArrayCreation(expression, type));
960     if (!myHolder.hasErrorResults()) registerConstructorCall(expression);
961
962     if (!myHolder.hasErrorResults()) visitExpression(expression);
963   }
964
965   @Override
966   public void visitPackageStatement(PsiPackageStatement statement) {
967     super.visitPackageStatement(statement);
968     myHolder.add(AnnotationsHighlightUtil.checkPackageAnnotationContainingFile(statement));
969   }
970
971   @Override
972   public void visitParameter(PsiParameter parameter) {
973     super.visitParameter(parameter);
974
975     final PsiElement parent = parameter.getParent();
976     if (parent instanceof PsiParameterList && parameter.isVarArgs()) {
977       if (!myHolder.hasErrorResults()) myHolder.add(checkFeature(parameter, Feature.VARARGS));
978       if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkVarArgParameterIsLast(parameter));
979     }
980     else if (parent instanceof PsiCatchSection) {
981       if (!myHolder.hasErrorResults() && parameter.getType() instanceof PsiDisjunctionType) {
982         myHolder.add(checkFeature(parameter, Feature.MULTI_CATCH));
983       }
984       if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkCatchParameterIsThrowable(parameter));
985       if (!myHolder.hasErrorResults()) myHolder.addAll(GenericsHighlightUtil.checkCatchParameterIsClass(parameter));
986       if (!myHolder.hasErrorResults()) myHolder.addAll(HighlightUtil.checkCatchTypeIsDisjoint(parameter));
987     }
988     else if (parent instanceof PsiForeachStatement) {
989       if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkForEachParameterType((PsiForeachStatement)parent, parameter));
990     }
991   }
992
993   @Override
994   public void visitParameterList(PsiParameterList list) {
995     super.visitParameterList(list);
996     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAnnotationMethodParameters(list));
997   }
998
999   @Override
1000   public void visitPostfixExpression(PsiPostfixExpression expression) {
1001     super.visitPostfixExpression(expression);
1002     if (!myHolder.hasErrorResults()) {
1003       myHolder.add(HighlightUtil.checkUnaryOperatorApplicable(expression.getOperationSign(), expression.getOperand()));
1004     }
1005   }
1006
1007   @Override
1008   public void visitPrefixExpression(PsiPrefixExpression expression) {
1009     super.visitPrefixExpression(expression);
1010     if (!myHolder.hasErrorResults()) {
1011       myHolder.add(HighlightUtil.checkUnaryOperatorApplicable(expression.getOperationSign(), expression.getOperand()));
1012     }
1013   }
1014
1015   private void registerConstructorCall(@NotNull PsiConstructorCall constructorCall) {
1016     if (myRefCountHolder != null) {
1017       JavaResolveResult resolveResult = constructorCall.resolveMethodGenerics();
1018       final PsiElement resolved = resolveResult.getElement();
1019       if (resolved instanceof PsiNamedElement) {
1020         myRefCountHolder.registerLocallyReferenced((PsiNamedElement)resolved);
1021       }
1022     }
1023   }
1024
1025   @Override
1026   public void visitReferenceElement(PsiJavaCodeReferenceElement ref) {
1027     JavaResolveResult resolveResult = doVisitReferenceElement(ref);
1028     if (resolveResult != null && !myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkRawOnParameterizedType(ref, resolveResult.getElement()));
1029   }
1030
1031   private JavaResolveResult doVisitReferenceElement(@NotNull PsiJavaCodeReferenceElement ref) {
1032     JavaResolveResult result;
1033     try {
1034       result = resolveOptimised(ref);
1035     }
1036     catch (IndexNotReadyException e) {
1037       return null;
1038     }
1039     PsiElement resolved = result.getElement();
1040     PsiElement parent = ref.getParent();
1041
1042     if (myRefCountHolder != null) {
1043       myRefCountHolder.registerReference(ref, result);
1044     }
1045     myHolder.add(HighlightUtil.checkReference(ref, result, myFile, myLanguageLevel));
1046     if (parent instanceof PsiJavaCodeReferenceElement || ref.isQualified()) {
1047       if (!myHolder.hasErrorResults() && resolved instanceof PsiTypeParameter) {
1048         boolean cannotSelectFromTypeParameter = !myJavaSdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7);
1049         if (!cannotSelectFromTypeParameter) {
1050           final PsiClass containingClass = PsiTreeUtil.getParentOfType(ref, PsiClass.class);
1051           if (containingClass != null) {
1052             if (PsiTreeUtil.isAncestor(containingClass.getExtendsList(), ref, false) ||
1053                 PsiTreeUtil.isAncestor(containingClass.getImplementsList(), ref, false)) {
1054               cannotSelectFromTypeParameter = true;
1055             }
1056           }
1057         }
1058         if (cannotSelectFromTypeParameter) {
1059           myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip("Cannot select from a type parameter").range(ref).create());
1060         }
1061       }
1062     }
1063     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkAbstractInstantiation(ref));
1064     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkExtendsDuplicate(ref, resolved,myFile));
1065     if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassExtendsForeignInnerClass(ref, resolved));
1066     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkSelectStaticClassFromParameterizedType(resolved, ref));
1067     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, ref,
1068                                                                                                                  result.getSubstitutor(),
1069                                                                                                                  myJavaSdkVersion));
1070     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkCannotPassInner(ref));
1071
1072     if (resolved != null && parent instanceof PsiReferenceList) {
1073       if (!myHolder.hasErrorResults()) {
1074         PsiReferenceList referenceList = (PsiReferenceList)parent;
1075         myHolder.add(HighlightUtil.checkElementInReferenceList(ref, referenceList, result));
1076       }
1077     }
1078
1079     if (parent instanceof PsiAnonymousClass && ref.equals(((PsiAnonymousClass)parent).getBaseClassReference()) &&
1080         myOverrideEquivalentMethodsVisitedClasses.add((PsiClass)parent)) {
1081       PsiClass aClass = (PsiClass)parent;
1082       myHolder.addAll(GenericsHighlightUtil.checkOverrideEquivalentMethods(aClass));
1083     }
1084
1085     if (resolved instanceof PsiVariable) {
1086       PsiVariable variable = (PsiVariable)resolved;
1087
1088       final PsiElement containingClass = PsiTreeUtil.getNonStrictParentOfType(ref, PsiClass.class, PsiLambdaExpression.class);
1089       if ((containingClass instanceof PsiAnonymousClass || containingClass instanceof PsiLambdaExpression) &&
1090           !PsiTreeUtil.isAncestor(containingClass, variable, false) &&
1091           !(variable instanceof PsiField)) {
1092         if (containingClass instanceof PsiLambdaExpression || !PsiTreeUtil.isAncestor(((PsiAnonymousClass) containingClass).getArgumentList(), ref, false)) {
1093           myHolder.add(HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.IMPLICIT_ANONYMOUS_CLASS_PARAMETER).range(ref).create());
1094         }
1095       }
1096
1097       if (variable instanceof PsiParameter && ref instanceof PsiExpression && PsiUtil.isAccessedForWriting((PsiExpression)ref)) {
1098         myReassignedParameters.put((PsiParameter)variable, 2);
1099       }
1100
1101       final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
1102       if (!variable.hasModifierProperty(PsiModifier.FINAL) && isReassigned(variable)) {
1103         myHolder.add(HighlightNamesUtil.highlightReassignedVariable(variable, ref));
1104       }
1105       else {
1106         myHolder.add(HighlightNamesUtil.highlightVariableName(variable, ref.getReferenceNameElement(), colorsScheme));
1107       }
1108       myHolder.add(HighlightNamesUtil.highlightClassNameInQualifier(ref, colorsScheme));
1109     }
1110     else {
1111       highlightReferencedMethodOrClassName(ref, resolved);
1112     }
1113
1114     if (parent instanceof PsiNewExpression && !(resolved instanceof PsiClass) && resolved instanceof PsiNamedElement && ((PsiNewExpression)parent).getClassOrAnonymousClassReference() == ref) {
1115        myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(ref)
1116                       .descriptionAndTooltip("Cannot find symbol " + ((PsiNamedElement)resolved).getName()).create());
1117     }
1118     if (!myHolder.hasErrorResults() && resolved instanceof PsiClass) {
1119       final PsiClass aClass = ((PsiClass)resolved).getContainingClass();
1120       if (aClass != null) {
1121         final PsiElement qualifier = ref.getQualifier();
1122         final PsiElement place;
1123         if (qualifier instanceof PsiJavaCodeReferenceElement) {
1124           place = ((PsiJavaCodeReferenceElement)qualifier).resolve();
1125         }
1126         else {
1127           if (parent instanceof PsiNewExpression) {
1128             final PsiExpression newQualifier = ((PsiNewExpression)parent).getQualifier();
1129             place = newQualifier == null ? ref : PsiUtil.resolveClassInType(newQualifier.getType());
1130           }
1131           else {
1132             place = ref;
1133           }
1134         }
1135         if (place != null && PsiTreeUtil.isAncestor(aClass, place, false) && aClass.hasTypeParameters()) {
1136           myHolder.add(HighlightClassUtil.checkCreateInnerClassFromStaticContext(ref, place, (PsiClass)resolved));
1137         }
1138       }
1139       else if (resolved instanceof PsiTypeParameter) {
1140         final PsiTypeParameterListOwner owner = ((PsiTypeParameter)resolved).getOwner();
1141         if (owner instanceof PsiClass) {
1142           final PsiClass outerClass = (PsiClass)owner;
1143           if (!InheritanceUtil.hasEnclosingInstanceInScope(outerClass, ref, false, false)) {
1144             myHolder.add(HighlightClassUtil.reportIllegalEnclosingUsage(ref, null, (PsiClass)owner, ref));
1145           }
1146         }
1147       }
1148     }
1149
1150     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkPackageAndClassConflict(ref, myFile));
1151
1152     return result;
1153   }
1154
1155   @NotNull
1156   private JavaResolveResult resolveOptimised(@NotNull PsiJavaCodeReferenceElement ref) {
1157     JavaResolveResult result;
1158     if (ref instanceof PsiReferenceExpressionImpl) {
1159       JavaResolveResult[] results = JavaResolveUtil.resolveWithContainingFile(ref,
1160                                                                               PsiReferenceExpressionImpl.OurGenericsResolver.INSTANCE,
1161                                                                               true, true,
1162                                                                               myFile);
1163       result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
1164     }
1165     else {
1166       result = ref.advancedResolve(true);
1167     }
1168     return result;
1169   }
1170
1171   @NotNull
1172   private JavaResolveResult[] resolveOptimised(@NotNull PsiReferenceExpression expression) {
1173     JavaResolveResult[] results;
1174     if (expression instanceof PsiReferenceExpressionImpl) {
1175       results = JavaResolveUtil.resolveWithContainingFile(expression,
1176                                                           PsiReferenceExpressionImpl.OurGenericsResolver.INSTANCE, true, true,
1177                                                           myFile);
1178     }
1179     else {
1180       results = expression.multiResolve(true);
1181     }
1182     return results;
1183   }
1184
1185   @Override
1186   public void visitReferenceExpression(PsiReferenceExpression expression) {
1187     JavaResolveResult resultForIncompleteCode = doVisitReferenceElement(expression);
1188     if (!myHolder.hasErrorResults()) {
1189       visitExpression(expression);
1190       if (myHolder.hasErrorResults()) return;
1191     }
1192     JavaResolveResult result;
1193     JavaResolveResult[] results;
1194     try {
1195       results = resolveOptimised(expression);
1196       result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
1197     }
1198     catch (IndexNotReadyException e) {
1199       return;
1200     }
1201     PsiElement resolved = result.getElement();
1202     if (resolved instanceof PsiVariable && resolved.getContainingFile() == expression.getContainingFile()) {
1203       if (!myHolder.hasErrorResults()) {
1204         try {
1205           myHolder.add(HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, (PsiVariable)resolved, myUninitializedVarProblems,myFile));
1206         }
1207         catch (IndexNotReadyException ignored) { }
1208       }
1209       PsiVariable variable = (PsiVariable)resolved;
1210       boolean isFinal = variable.hasModifierProperty(PsiModifier.FINAL);
1211       if (isFinal && !variable.hasInitializer()) {
1212         if (!myHolder.hasErrorResults()) {
1213           myHolder.add(HighlightControlFlowUtil.checkFinalVariableMightAlreadyHaveBeenAssignedTo(variable, expression, myFinalVarProblems));
1214         }
1215         if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkFinalVariableInitializedInLoop(expression, resolved));
1216       }
1217     }
1218
1219     PsiElement parent = expression.getParent();
1220     if (parent instanceof PsiMethodCallExpression && ((PsiMethodCallExpression)parent).getMethodExpression() == expression && (!result.isAccessible() || !result.isStaticsScopeCorrect())) {
1221       PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)parent;
1222       PsiExpressionList list = methodCallExpression.getArgumentList();
1223       if (!HighlightMethodUtil.isDummyConstructorCall(methodCallExpression, myResolveHelper, list, expression)) {
1224         try {
1225           myHolder.add(HighlightMethodUtil.checkAmbiguousMethodCallIdentifier(expression, results, list, resolved, result, methodCallExpression, myResolveHelper));
1226
1227           if (!PsiTreeUtil.findChildrenOfType(methodCallExpression.getArgumentList(), PsiLambdaExpression.class).isEmpty()) {
1228             myHolder.add(HighlightMethodUtil
1229               .checkAmbiguousMethodCallArguments(expression, results, list, resolved, result, methodCallExpression, myResolveHelper, expression.getReferenceNameElement()));
1230           }
1231         }
1232         catch (IndexNotReadyException ignored) { }
1233       }
1234     }
1235
1236     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkExpressionRequired(expression, resultForIncompleteCode));
1237     if (!myHolder.hasErrorResults() && resolved instanceof PsiField) {
1238       try {
1239         myHolder.add(HighlightUtil.checkIllegalForwardReferenceToField(expression, (PsiField)resolved));
1240       }
1241       catch (IndexNotReadyException ignored) { }
1242     }
1243     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkAccessStaticFieldFromEnumConstructor(expression, result));
1244     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkClassReferenceAfterQualifier(expression, resolved));
1245     final PsiExpression qualifierExpression = expression.getQualifierExpression();
1246     myHolder.add(HighlightUtil.checkUnqualifiedSuperInDefaultMethod(myLanguageLevel, expression, qualifierExpression));
1247     if (!myHolder.hasErrorResults() && qualifierExpression != null) {
1248       PsiType type = qualifierExpression.getType();
1249       if (type instanceof PsiCapturedWildcardType) {
1250         type = ((PsiCapturedWildcardType)type).getUpperBound();
1251       }
1252       final PsiClass psiClass = PsiUtil.resolveClassInType(type);
1253       if (psiClass != null) {
1254         myHolder.add(GenericsHighlightUtil.areSupersAccessible(psiClass, expression));
1255       }
1256     }
1257   }
1258
1259   @Override
1260   public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
1261     myHolder.add(checkFeature(expression, Feature.METHOD_REFERENCES));
1262
1263     final JavaResolveResult result;
1264     final JavaResolveResult[] results;
1265     try {
1266       results = expression.multiResolve(true);
1267       result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
1268     }
1269     catch (IndexNotReadyException e) {
1270       return;
1271     }
1272     if (myRefCountHolder != null) {
1273       myRefCountHolder.registerReference(expression, result);
1274     }
1275     final PsiElement method = result.getElement();
1276     if (method != null && !result.isAccessible()) {
1277       final String accessProblem = HighlightUtil.buildProblemWithAccessDescription(expression, result);
1278       HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(accessProblem).create();
1279       myHolder.add(info);
1280     } else {
1281       final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
1282       if (method instanceof PsiMethod && !expression.isConstructor()) {
1283         final PsiElement methodNameElement = expression.getReferenceNameElement();
1284         myHolder.add(HighlightNamesUtil.highlightMethodName((PsiMethod)method, methodNameElement, false, colorsScheme));
1285       }
1286       myHolder.add(HighlightNamesUtil.highlightClassNameInQualifier(expression, colorsScheme));
1287     }
1288
1289     if (!LambdaUtil.isValidLambdaContext(expression.getParent())) {
1290       myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression)
1291         .descriptionAndTooltip("Method reference expression is not expected here").create());
1292     }
1293
1294     if (!myHolder.hasErrorResults()) {
1295       final PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
1296       if (functionalInterfaceType != null) {
1297         final boolean notFunctional = !LambdaUtil.isFunctionalType(functionalInterfaceType);
1298         if (notFunctional) {
1299           myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression)
1300                          .descriptionAndTooltip(functionalInterfaceType.getPresentableText() + " is not a functional interface").create());
1301         }
1302       }
1303       if (!myHolder.hasErrorResults()) {
1304         final PsiElement referenceNameElement = expression.getReferenceNameElement();
1305         if (referenceNameElement instanceof PsiKeyword) {
1306           if (!PsiMethodReferenceUtil.isValidQualifier(expression)) {
1307             final PsiElement qualifier = expression.getQualifier();
1308             String description = "Cannot find class " + qualifier.getText();
1309             HighlightInfo result1 =
1310               HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(qualifier).descriptionAndTooltip(description).create();
1311             myHolder.add(result1);
1312           }
1313         }
1314       }
1315       if (!myHolder.hasErrorResults()) {
1316         final PsiClassType.ClassResolveResult resolveResult = checkFunctionalInterfaceTypeAccessible(expression, functionalInterfaceType);
1317
1318         final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
1319         if (interfaceMethod != null) {
1320           if (!myHolder.hasErrorResults()) {
1321             final String errorMessage = PsiMethodReferenceUtil.checkMethodReferenceContext(expression);
1322             if (errorMessage != null) {
1323               myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(errorMessage).create());
1324             }
1325           }
1326
1327           if (!myHolder.hasErrorResults()) {
1328             final String badReturnTypeMessage = PsiMethodReferenceUtil.checkReturnType(expression, result, functionalInterfaceType);
1329             if (badReturnTypeMessage != null) {
1330               myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(badReturnTypeMessage).create());
1331             }
1332           }
1333         }
1334       }
1335     }
1336
1337     if (!myHolder.hasErrorResults()) {
1338       PsiElement qualifier = expression.getQualifier();
1339       if (qualifier instanceof PsiTypeElement) {
1340         final PsiType psiType = ((PsiTypeElement)qualifier).getType();
1341         final HighlightInfo genericArrayCreationInfo = GenericsHighlightUtil.checkGenericArrayCreation(qualifier, psiType);
1342         if (genericArrayCreationInfo != null) {
1343           myHolder.add(genericArrayCreationInfo);
1344         } else {
1345           final String wildcardMessage = PsiMethodReferenceUtil.checkTypeArguments((PsiTypeElement)qualifier, psiType);
1346           if (wildcardMessage != null) {
1347             myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(qualifier).descriptionAndTooltip(wildcardMessage).create());
1348           }
1349         }
1350       }
1351     }
1352
1353     if (!myHolder.hasErrorResults()) {
1354       myHolder.add(PsiMethodReferenceHighlightingUtil.checkRawConstructorReference(expression));
1355     }
1356
1357     if (!myHolder.hasErrorResults()) {
1358       myHolder.add(HighlightUtil.checkUnhandledExceptions(expression, expression.getTextRange()));
1359     }
1360
1361     if (!myHolder.hasErrorResults()) {
1362       if (results.length == 0 || results[0] instanceof MethodCandidateInfo &&
1363                                  !((MethodCandidateInfo)results[0]).isApplicable() &&
1364                                  expression.getFunctionalInterfaceType() != null) {
1365         String description = null;
1366         if (results.length == 1) {
1367           description = ((MethodCandidateInfo)results[0]).getInferenceErrorMessage();
1368         }
1369         if (expression.isConstructor()) {
1370           final PsiClass containingClass = PsiMethodReferenceUtil.getQualifierResolveResult(expression).getContainingClass();
1371
1372           if (containingClass != null) {
1373             if (!myHolder.add(HighlightClassUtil.checkInstantiationOfAbstractClass(containingClass, expression)) &&
1374                 !myHolder.add(GenericsHighlightUtil.checkEnumInstantiation(expression, containingClass)) &&
1375                 containingClass.isPhysical() &&
1376                 description == null) {
1377               description = JavaErrorMessages.message("cannot.resolve.constructor", containingClass.getName());
1378             }
1379           }
1380         }
1381         else if (description == null){
1382           description = JavaErrorMessages.message("cannot.resolve.method", expression.getReferenceName());
1383         }
1384
1385         if (description != null) {
1386           final PsiElement referenceNameElement = expression.getReferenceNameElement();
1387           final HighlightInfo highlightInfo =
1388             HighlightInfo.newHighlightInfo(results.length == 0 ? HighlightInfoType.WRONG_REF : HighlightInfoType.ERROR)
1389               .descriptionAndTooltip(description).range(referenceNameElement).create();
1390           myHolder.add(highlightInfo);
1391           final TextRange fixRange = HighlightMethodUtil.getFixRange(referenceNameElement);
1392           QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, QuickFixFactory.getInstance().createCreateMethodFromUsageFix(expression));
1393         }
1394       }
1395     }
1396   }
1397
1398   // 15.13 | 15.27
1399   // It is a compile-time error if any class or interface mentioned by either U or the function type of U
1400   // is not accessible from the class or interface in which the method reference expression appears.
1401   @NotNull
1402   private PsiClassType.ClassResolveResult checkFunctionalInterfaceTypeAccessible(@NotNull PsiFunctionalExpression expression,
1403                                                                                  PsiType functionalInterfaceType) {
1404     PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
1405     final PsiClass psiClass = resolveResult.getElement();
1406     if (psiClass != null) {
1407       if (!PsiUtil.isAccessible(myFile.getProject(), psiClass, expression, null)) {
1408         myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression)
1409                        .descriptionAndTooltip(HighlightUtil.buildProblemWithAccessDescription(expression, resolveResult)).create());
1410       }
1411       else {
1412         for (PsiType type : resolveResult.getSubstitutor().getSubstitutionMap().values()) {
1413           checkFunctionalInterfaceTypeAccessible(expression, type);
1414         }
1415       }
1416     }
1417     return resolveResult;
1418   }
1419
1420   @Override
1421   public void visitReferenceList(PsiReferenceList list) {
1422     if (list.getFirstChild() == null) return;
1423     PsiElement parent = list.getParent();
1424     if (!(parent instanceof PsiTypeParameter)) {
1425       myHolder.add(AnnotationsHighlightUtil.checkAnnotationDeclaration(parent, list));
1426       if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkExtendsAllowed(list));
1427       if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkImplementsAllowed(list));
1428       if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassExtendsOnlyOneClass(list));
1429       if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkGenericCannotExtendException(list));
1430     }
1431   }
1432
1433   @Override
1434   public void visitReferenceParameterList(PsiReferenceParameterList list) {
1435     if (list.getTextLength() == 0) return;
1436
1437     myHolder.add(checkFeature(list, Feature.GENERICS));
1438     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkParametersAllowed(list));
1439     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkParametersOnRaw(list));
1440     if (!myHolder.hasErrorResults()) {
1441       for (PsiTypeElement typeElement : list.getTypeParameterElements()) {
1442         if (typeElement.getType() instanceof PsiDiamondType) {
1443           myHolder.add(checkFeature(list, Feature.DIAMOND_TYPES));
1444         }
1445       }
1446     }
1447   }
1448
1449   @Override
1450   public void visitReturnStatement(PsiReturnStatement statement) {
1451     try {
1452       myHolder.add(HighlightUtil.checkReturnStatementType(statement));
1453     }
1454     catch (IndexNotReadyException ignore) { }
1455   }
1456
1457   @Override
1458   public void visitStatement(PsiStatement statement) {
1459     super.visitStatement(statement);
1460     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkNotAStatement(statement));
1461   }
1462
1463   @Override
1464   public void visitSuperExpression(PsiSuperExpression expr) {
1465     myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier(), myLanguageLevel));
1466     if (!myHolder.hasErrorResults()) visitExpression(expr);
1467   }
1468
1469   @Override
1470   public void visitSwitchLabelStatement(PsiSwitchLabelStatement statement) {
1471     super.visitSwitchLabelStatement(statement);
1472     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkCaseStatement(statement));
1473   }
1474
1475   @Override
1476   public void visitSwitchStatement(PsiSwitchStatement statement) {
1477     super.visitSwitchStatement(statement);
1478     myHolder.add(HighlightUtil.checkStatementPrependedWithCaseInsideSwitch(statement));
1479     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSwitchSelectorType(statement, myLanguageLevel));
1480   }
1481
1482   @Override
1483   public void visitThisExpression(PsiThisExpression expr) {
1484     if (!(expr.getParent() instanceof PsiReceiverParameter)) {
1485       myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier(), myLanguageLevel));
1486       if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkMemberReferencedBeforeConstructorCalled(expr, null, myFile));
1487       if (!myHolder.hasErrorResults()) visitExpression(expr);
1488     }
1489   }
1490
1491   @Override
1492   public void visitThrowStatement(PsiThrowStatement statement) {
1493     myHolder.add(HighlightUtil.checkUnhandledExceptions(statement, null));
1494     if (!myHolder.hasErrorResults()) visitStatement(statement);
1495   }
1496
1497   @Override
1498   public void visitTryStatement(PsiTryStatement statement) {
1499     super.visitTryStatement(statement);
1500     if (!myHolder.hasErrorResults()) {
1501       final Set<PsiClassType> thrownTypes = HighlightUtil.collectUnhandledExceptions(statement);
1502       for (PsiParameter parameter : statement.getCatchBlockParameters()) {
1503         boolean added = myHolder.addAll(HighlightUtil.checkExceptionAlreadyCaught(parameter));
1504         if (!added) {
1505           added = myHolder.addAll(HighlightUtil.checkExceptionThrownInTry(parameter, thrownTypes));
1506         }
1507         if (!added) {
1508           myHolder.addAll(HighlightUtil.checkWithImprovedCatchAnalysis(parameter, thrownTypes, myFile));
1509         }
1510       }
1511     }
1512   }
1513
1514   @Override
1515   public void visitResourceList(PsiResourceList resourceList) {
1516     super.visitResourceList(resourceList);
1517     if (!myHolder.hasErrorResults()) myHolder.add(checkFeature(resourceList, Feature.TRY_WITH_RESOURCES));
1518   }
1519
1520   @Override
1521   public void visitResourceVariable(PsiResourceVariable resource) {
1522     super.visitResourceVariable(resource);
1523     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resource));
1524     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(resource));
1525   }
1526
1527   @Override
1528   public void visitResourceExpression(PsiResourceExpression resource) {
1529     super.visitResourceExpression(resource);
1530     if (!myHolder.hasErrorResults()) myHolder.add(checkFeature(resource, Feature.REFS_AS_RESOURCE));
1531     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkResourceVariableIsFinal(resource));
1532     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resource));
1533     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(resource));
1534   }
1535
1536   @Override
1537   public void visitTypeElement(PsiTypeElement type) {
1538     if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalType(type));
1539     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkReferenceTypeUsedAsTypeArgument(type, myLanguageLevel));
1540     if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkWildcardUsage(type));
1541   }
1542
1543   @Override
1544   public void visitTypeCastExpression(PsiTypeCastExpression typeCast) {
1545     super.visitTypeCastExpression(typeCast);
1546     try {
1547       if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIntersectionInTypeCast(typeCast, myLanguageLevel));
1548       if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInconvertibleTypeCast(typeCast));
1549     }
1550     catch (IndexNotReadyException ignored) { }
1551   }
1552
1553   @Override
1554   public void visitTypeParameterList(PsiTypeParameterList list) {
1555     PsiTypeParameter[] typeParameters = list.getTypeParameters();
1556     if (typeParameters.length > 0) {
1557       myHolder.add(checkFeature(list, Feature.GENERICS));
1558       if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkTypeParametersList(list, typeParameters, myLanguageLevel));
1559     }
1560   }
1561
1562   @Override
1563   public void visitVariable(PsiVariable variable) {
1564     super.visitVariable(variable);
1565     try {
1566       if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkVariableInitializerType(variable));
1567     }
1568     catch (IndexNotReadyException ignored) { }
1569   }
1570
1571   private boolean isReassigned(@NotNull PsiVariable variable) {
1572     try {
1573       boolean reassigned;
1574       if (variable instanceof PsiParameter) {
1575         reassigned = myReassignedParameters.get((PsiParameter)variable) == 2;
1576       }
1577       else  {
1578         reassigned = HighlightControlFlowUtil.isReassigned(variable, myFinalVarProblems);
1579       }
1580
1581       return reassigned;
1582     }
1583     catch (IndexNotReadyException e) {
1584       return false;
1585     }
1586   }
1587
1588   @Override
1589   public void visitConditionalExpression(PsiConditionalExpression expression) {
1590     super.visitConditionalExpression(expression);
1591     if (myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8) && PsiPolyExpressionUtil.isPolyExpression(expression)) {
1592       final PsiExpression thenExpression = expression.getThenExpression();
1593       final PsiExpression elseExpression = expression.getElseExpression();
1594       if (thenExpression != null && elseExpression != null) {
1595         final PsiType conditionalType = expression.getType();
1596         if (conditionalType != null) {
1597           final PsiExpression[] sides = {thenExpression, elseExpression};
1598           for (PsiExpression side : sides) {
1599             final PsiType sideType = side.getType();
1600             if (sideType != null && !TypeConversionUtil.isAssignable(conditionalType, sideType)) {
1601               myHolder.add(HighlightUtil.checkAssignability(conditionalType, sideType, side, side));
1602             }
1603           }
1604         }
1605       }
1606     }
1607   }
1608
1609   @Override
1610   public void visitReceiverParameter(PsiReceiverParameter parameter) {
1611     super.visitReceiverParameter(parameter);
1612     if (!myHolder.hasErrorResults()) myHolder.add(checkFeature(parameter, Feature.RECEIVERS));
1613     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkReceiverPlacement(parameter));
1614     if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkReceiverType(parameter));
1615   }
1616
1617   @Override
1618   public void visitModule(PsiJavaModule module) {
1619     super.visitModule(module);
1620     if (!myHolder.hasErrorResults()) myHolder.add(checkFeature(module, Feature.MODULES));
1621     if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkFileName(module, myFile));
1622     if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkFileDuplicates(module, myFile));
1623     if (!myHolder.hasErrorResults()) myHolder.addAll(ModuleHighlightUtil.checkDuplicateRequires(module));
1624     if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkFileLocation(module, myFile));
1625   }
1626
1627   @Override
1628   public void visitRequiresStatement(PsiRequiresStatement statement) {
1629     super.visitRequiresStatement(statement);
1630     if (PsiUtil.isLanguageLevel9OrHigher(myFile)) {
1631       PsiJavaModuleReferenceElement ref = statement.getReferenceElement();
1632       if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkModuleReference(ref));
1633     }
1634   }
1635
1636   @Nullable
1637   private HighlightInfo checkFeature(@NotNull PsiElement element, @NotNull Feature feature) {
1638     return HighlightUtil.checkFeature(element, feature, myLanguageLevel, myFile);
1639   }
1640
1641   protected void prepareToRunAsInspection(@NotNull HighlightInfoHolder holder) {
1642     PsiFile file = holder.getContextFile();
1643     JavaSdkVersion sdkVersion = JavaVersionService.getInstance().getJavaSdkVersion(file);
1644
1645     myHolder = holder;
1646     myFile = file;
1647     myLanguageLevel = PsiUtil.getLanguageLevel(file);
1648     myJavaSdkVersion = sdkVersion != null ? sdkVersion : JavaSdkVersion.fromLanguageLevel(myLanguageLevel);
1649   }
1650 }