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