catch PCE during dumb resolve
[fedora-idea.git] / java / java-impl / src / com / intellij / codeInsight / daemon / impl / analysis / HighlightVisitorImpl.java
blob12ffff1d738f8fbcbc35be368998453d16bcf7b4
1 package com.intellij.codeInsight.daemon.impl.analysis;
3 import com.intellij.codeHighlighting.Pass;
4 import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
5 import com.intellij.codeInsight.daemon.JavaErrorMessages;
6 import com.intellij.codeInsight.daemon.impl.*;
7 import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
8 import com.intellij.codeInsight.daemon.impl.quickfix.SetupJDKFix;
9 import com.intellij.openapi.diagnostic.Logger;
10 import com.intellij.openapi.editor.Document;
11 import com.intellij.openapi.progress.ProgressManager;
12 import com.intellij.openapi.project.DumbAware;
13 import com.intellij.openapi.project.Project;
14 import com.intellij.openapi.project.IndexNotReadyException;
15 import com.intellij.openapi.util.Pair;
16 import com.intellij.openapi.util.TextRange;
17 import com.intellij.pom.java.LanguageLevel;
18 import com.intellij.psi.*;
19 import com.intellij.psi.controlFlow.ControlFlowUtil;
20 import com.intellij.psi.impl.source.javadoc.PsiDocMethodOrFieldRef;
21 import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
22 import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
23 import com.intellij.psi.javadoc.PsiDocComment;
24 import com.intellij.psi.javadoc.PsiDocTagValue;
25 import com.intellij.psi.templateLanguages.OuterLanguageElement;
26 import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
27 import com.intellij.psi.util.PsiTreeUtil;
28 import com.intellij.psi.util.PsiUtil;
29 import com.intellij.psi.xml.XmlAttributeValue;
30 import gnu.trove.THashMap;
31 import org.jetbrains.annotations.NonNls;
32 import org.jetbrains.annotations.NotNull;
34 import java.util.Collection;
35 import java.util.List;
36 import java.util.Map;
38 public class HighlightVisitorImpl extends JavaElementVisitor implements HighlightVisitor, DumbAware {
39 private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl");
41 private final PsiResolveHelper myResolveHelper;
43 private HighlightInfoHolder myHolder;
45 private RefCountHolder myRefCountHolder;
47 // map codeBlock->List of PsiReferenceExpression of uninitialized final variables
48 private final Map<PsiElement, Collection<PsiReferenceExpression>> myUninitializedVarProblems = new THashMap<PsiElement, Collection<PsiReferenceExpression>>();
49 // map codeBlock->List of PsiReferenceExpression of extra initialization of final variable
50 private final Map<PsiElement, Collection<ControlFlowUtil.VariableInfo>> myFinalVarProblems = new THashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>();
51 private final Map<PsiParameter, Boolean> myParameterIsReassigned = new THashMap<PsiParameter, Boolean>();
53 private final Map<String, Pair<PsiImportStatementBase, PsiClass>> mySingleImportedClasses = new THashMap<String, Pair<PsiImportStatementBase, PsiClass>>();
54 private final Map<String, Pair<PsiImportStaticReferenceElement, PsiField>> mySingleImportedFields = new THashMap<String, Pair<PsiImportStaticReferenceElement, PsiField>>();
55 private PsiFile myFile;
56 private final PsiElementVisitor REGISTER_REFERENCES_VISITOR = new PsiRecursiveElementWalkingVisitor() {
57 @Override public void visitElement(PsiElement element) {
58 super.visitElement(element);
59 for (PsiReference reference : element.getReferences()) {
60 PsiElement resolved = reference.resolve();
61 if (resolved instanceof PsiNamedElement) {
62 myRefCountHolder.registerLocallyReferenced((PsiNamedElement)resolved);
68 @SuppressWarnings({"UnusedDeclaration"}) //in plugin.xml
69 public HighlightVisitorImpl(Project project) {
70 this(JavaPsiFacade.getInstance(project).getResolveHelper());
73 private HighlightVisitorImpl(@NotNull PsiResolveHelper resolveHelper) {
74 myResolveHelper = resolveHelper;
77 public HighlightVisitorImpl clone() {
78 return new HighlightVisitorImpl(myResolveHelper);
81 public int order() {
82 return 0;
85 public boolean suitableForFile(PsiFile file) {
86 return true;
89 public void visit(PsiElement element, HighlightInfoHolder holder) {
90 if (!holder.isWritable()) {
91 throw new UnsupportedOperationException();
93 myHolder = holder;
95 if (LOG.isDebugEnabled()) {
96 LOG.assertTrue(element.isValid());
98 element.accept(this);
100 if (myRefCountHolder != null) {
101 registerReferencesFromInjectedFragments(element);
105 private void registerReferencesFromInjectedFragments(final PsiElement element) {
106 InjectedLanguageUtil.enumerate(element, myFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
107 public void visit(@NotNull final PsiFile injectedPsi, @NotNull final List<PsiLanguageInjectionHost.Shred> places) {
108 injectedPsi.accept(REGISTER_REFERENCES_VISITOR);
110 }, false);
113 public boolean analyze(final Runnable action, final boolean updateWholeFile, final PsiFile file) {
114 myFile = file;
115 boolean success = true;
116 try {
117 if (updateWholeFile) {
118 Project project = file.getProject();
119 DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(project);
120 FileStatusMap fileStatusMap = ((DaemonCodeAnalyzerImpl)daemonCodeAnalyzer).getFileStatusMap();
121 RefCountHolder refCountHolder = RefCountHolder.getInstance(file);
122 myRefCountHolder = refCountHolder;
123 Document document = PsiDocumentManager.getInstance(project).getDocument(file);
124 TextRange dirtyScope = document == null ? file.getTextRange() : fileStatusMap.getFileDirtyScope(document, Pass.UPDATE_ALL);
125 success = refCountHolder.analyze(action, dirtyScope, file);
127 else {
128 myRefCountHolder = null;
129 action.run();
132 finally {
133 myUninitializedVarProblems.clear();
134 myFinalVarProblems.clear();
135 mySingleImportedClasses.clear();
136 mySingleImportedFields.clear();
137 myParameterIsReassigned.clear();
139 myRefCountHolder = null;
140 myFile = null;
141 myHolder = null;
144 return success;
147 public void visitElement(final PsiElement element) {
148 if (element instanceof XmlAttributeValue) {
149 try {
150 for (PsiReference reference : element.getReferences()) {
151 if(reference instanceof PsiJavaReference && myRefCountHolder != null){
152 final PsiJavaReference psiJavaReference = (PsiJavaReference)reference;
153 myRefCountHolder.registerReference(psiJavaReference, psiJavaReference.advancedResolve(false));
157 catch (IndexNotReadyException ignored) {
162 @Override public void visitAnnotation(PsiAnnotation annotation) {
163 super.visitAnnotation(annotation);
164 if (!PsiUtil.isLanguageLevel5OrHigher(annotation)) {
165 HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, annotation, JavaErrorMessages.message("annotations.prior.15"));
166 QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
167 myHolder.add(info);
168 return;
171 myHolder.add(AnnotationsHighlightUtil.checkApplicability(annotation));
172 if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkAnnotationType(annotation));
173 if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkMissingAttributes(annotation));
174 if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkTargetAnnotationDuplicates(annotation));
175 if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkDuplicatedAnnotations(annotation));
178 @Override public void visitAnnotationArrayInitializer(PsiArrayInitializerMemberValue initializer) {
179 PsiMethod method = null;
180 PsiElement parent = initializer.getParent();
181 if (parent instanceof PsiNameValuePair) {
182 method = (PsiMethod)parent.getReference().resolve();
184 else if (parent instanceof PsiAnnotationMethod) {
185 method = (PsiMethod)parent;
187 if (method != null) {
188 PsiType type = method.getReturnType();
189 if (type instanceof PsiArrayType) {
190 type = ((PsiArrayType)type).getComponentType();
191 PsiAnnotationMemberValue[] initializers = initializer.getInitializers();
192 for (PsiAnnotationMemberValue initializer1 : initializers) {
193 myHolder.add(AnnotationsHighlightUtil.checkMemberValueType(initializer1, type));
199 @Override public void visitAnnotationMethod(PsiAnnotationMethod method) {
200 PsiType returnType = method.getReturnType();
201 PsiAnnotationMemberValue value = method.getDefaultValue();
202 if (returnType != null && value != null) {
203 myHolder.add(AnnotationsHighlightUtil.checkMemberValueType(value, returnType));
206 myHolder.add(AnnotationsHighlightUtil.checkValidAnnotationType(method.getReturnTypeElement()));
207 myHolder.add(AnnotationsHighlightUtil.checkCyclicMemberType(method.getReturnTypeElement(), method.getContainingClass()));
210 @Override public void visitArrayInitializerExpression(PsiArrayInitializerExpression expression) {
211 super.visitArrayInitializerExpression(expression);
212 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkArrayInitializerApplicable(expression));
213 if (!(expression.getParent() instanceof PsiNewExpression)) {
214 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkGenericArrayCreation(expression, expression.getType()));
218 @Override public void visitAssignmentExpression(PsiAssignmentExpression assignment) {
219 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentCompatibleTypes(assignment));
220 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentOperatorApplicable(assignment));
221 if (!myHolder.hasErrorResults()) visitExpression(assignment);
224 @Override public void visitBinaryExpression(PsiBinaryExpression expression) {
225 super.visitBinaryExpression(expression);
226 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkBinaryOperatorApplicable(expression));
229 @Override public void visitBreakStatement(PsiBreakStatement statement) {
230 super.visitBreakStatement(statement);
231 if (!myHolder.hasErrorResults()) {
232 myHolder.add(HighlightUtil.checkLabelDefined(statement.getLabelIdentifier(), statement.findExitedStatement()));
236 @Override public void visitClass(PsiClass aClass) {
237 super.visitClass(aClass);
238 if (aClass instanceof JspClass) return;
239 if (aClass.isAnnotationType()) {
240 if (!PsiUtil.isLanguageLevel5OrHigher(aClass)) {
241 HighlightInfo info = HighlightInfo
242 .createHighlightInfo(HighlightInfoType.ERROR, aClass.getNameIdentifier(), JavaErrorMessages.message("annotations.prior.15"));
243 QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
244 myHolder.add(info);
247 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkInterfaceMultipleInheritance(aClass));
248 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkDuplicateTopLevelClass(aClass));
249 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumMustNotBeLocal(aClass));
250 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkImplicitThisReferenceBeforeSuper(aClass));
253 @Override public void visitClassInitializer(PsiClassInitializer initializer) {
254 super.visitClassInitializer(initializer);
255 if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkInitializerCompleteNormally(initializer));
256 if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement(initializer.getBody()));
257 if (!myHolder.hasErrorResults()) {
258 myHolder.add(HighlightClassUtil.checkThingNotAllowedInInterface(initializer, initializer.getContainingClass()));
262 @Override public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
263 super.visitClassObjectAccessExpression(expression);
264 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkClassObjectAccessExpression(expression));
267 @Override public void visitComment(PsiComment comment) {
268 super.visitComment(comment);
269 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnclosedComment(comment));
272 @Override public void visitContinueStatement(PsiContinueStatement statement) {
273 super.visitContinueStatement(statement);
274 if (!myHolder.hasErrorResults()) {
275 myHolder.add(HighlightUtil.checkLabelDefined(statement.getLabelIdentifier(), statement.findContinuedStatement()));
279 @Override public void visitJavaToken(PsiJavaToken token) {
280 super.visitJavaToken(token);
281 if (!myHolder.hasErrorResults()
282 && token.getTokenType() == JavaTokenType.RBRACE
283 && token.getParent() instanceof PsiCodeBlock
284 && token.getParent().getParent() instanceof PsiMethod) {
285 PsiMethod method = (PsiMethod)token.getParent().getParent();
286 myHolder.add(HighlightControlFlowUtil.checkMissingReturnStatement(method));
291 @Override public void visitDocComment(PsiDocComment comment) {
292 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnclosedComment(comment));
295 @Override public void visitDocTagValue(PsiDocTagValue value) {
296 if (value.getReference() != null) {
297 PsiReference reference = value.getReference();
298 if (reference != null) {
299 PsiElement element = reference.resolve();
300 if (element instanceof PsiMethod) {
301 myHolder.add(HighlightNamesUtil.highlightMethodName((PsiMethod)element, ((PsiDocMethodOrFieldRef)value).getNameElement(), false));
303 else if (element instanceof PsiParameter) {
304 myHolder.add(HighlightNamesUtil.highlightVariable((PsiVariable)element, value.getNavigationElement()));
310 @Override public void visitEnumConstant(PsiEnumConstant enumConstant) {
311 super.visitEnumConstant(enumConstant);
312 if (!myHolder.hasErrorResults()) GenericsHighlightUtil.checkEnumConstantForConstructorProblems(enumConstant, myHolder);
313 if (!myHolder.hasErrorResults()) registerConstructorCall(enumConstant);
316 @Override public void visitEnumConstantInitializer(PsiEnumConstantInitializer enumConstantInitializer) {
317 super.visitEnumConstantInitializer(enumConstantInitializer);
318 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassMustBeAbstract(enumConstantInitializer));
321 @Override public void visitExpression(PsiExpression expression) {
322 ProgressManager.getInstance().checkCanceled(); // visitLiteralExpression is invoked very often in array initializers
324 super.visitExpression(expression);
325 if (myHolder.add(HighlightUtil.checkMustBeBoolean(expression))) return;
326 if (expression instanceof PsiArrayAccessExpression
327 && ((PsiArrayAccessExpression)expression).getIndexExpression() != null) {
328 myHolder.add(HighlightUtil.checkValidArrayAccessExpression(((PsiArrayAccessExpression)expression).getArrayExpression(),
329 ((PsiArrayAccessExpression)expression).getIndexExpression()));
331 if (expression.getParent() instanceof PsiNewExpression
332 && ((PsiNewExpression)expression.getParent()).getQualifier() != expression
333 && ((PsiNewExpression)expression.getParent()).getArrayInitializer() != expression) {
334 // like in 'new String["s"]'
335 myHolder.add(HighlightUtil.checkValidArrayAccessExpression(null, expression));
337 if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkCannotWriteToFinal(expression));
338 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkVariableExpected(expression));
339 if (!myHolder.hasErrorResults()) HighlightUtil.checkArrayInitalizer(expression, myHolder);
340 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTernaryOperatorConditionIsBoolean(expression));
341 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssertOperatorTypes(expression));
342 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSynchronizedExpressionType(expression));
343 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkConditionalExpressionBranchTypesMatch(expression));
344 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkConstantExpressionOverflow(expression));
345 if (!myHolder.hasErrorResults()
346 && expression.getParent() instanceof PsiThrowStatement
347 && ((PsiThrowStatement)expression.getParent()).getException() == expression) {
348 PsiType type = expression.getType();
349 myHolder.add(HighlightUtil.checkMustBeThrowable(type, expression, true));
352 if (!myHolder.hasErrorResults()) {
353 myHolder.add(AnnotationsHighlightUtil.checkConstantExpression(expression));
357 @Override public void visitField(PsiField field) {
358 super.visitField(field);
359 if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkFinalFieldInitialized(field));
362 @Override public void visitForeachStatement(PsiForeachStatement statement) {
363 if (!PsiUtil.isLanguageLevel5OrHigher(statement)) {
364 HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, statement.getFirstChild(), JavaErrorMessages.message("foreach.prior.15"));
365 QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
366 myHolder.add(info);
370 @Override public void visitImportStaticStatement(PsiImportStaticStatement statement) {
371 if (!PsiUtil.isLanguageLevel5OrHigher(statement)) {
372 HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, statement.getFirstChild(), JavaErrorMessages.message("static.imports.prior.15"));
373 QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
374 myHolder.add(info);
378 @Override public void visitIdentifier(PsiIdentifier identifier) {
379 PsiElement parent = identifier.getParent();
380 if (parent instanceof PsiVariable) {
381 myHolder.add(HighlightUtil.checkVariableAlreadyDefined((PsiVariable)parent));
383 else if (parent instanceof PsiClass) {
384 myHolder.add(HighlightClassUtil.checkClassAlreadyImported((PsiClass)parent, identifier));
385 myHolder.add(HighlightClassUtil.checkExternalizableHasPublicNoArgsConstructor((PsiClass)parent, identifier));
386 if (!(parent instanceof PsiAnonymousClass)) {
387 myHolder.add(HighlightNamesUtil.highlightClassName((PsiClass)parent, ((PsiClass)parent).getNameIdentifier()));
390 else if (parent instanceof PsiMethod) {
391 PsiMethod method = (PsiMethod)parent;
392 if (method.isConstructor()) {
393 myHolder.add(HighlightMethodUtil.checkConstructorName(method));
396 super.visitIdentifier(identifier);
399 @Override public void visitImportStatement(PsiImportStatement statement) {
400 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSingleImportClassConflict(statement, mySingleImportedClasses));
403 @Override public void visitImportStaticReferenceElement(PsiImportStaticReferenceElement ref) {
404 String refName = ref.getReferenceName();
405 JavaResolveResult[] results = ref.multiResolve(false);
407 if (results.length == 0) {
408 String description = JavaErrorMessages.message("cannot.resolve.symbol", refName);
409 HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, ref.getReferenceNameElement(), description);
410 myHolder.add(info);
411 QuickFixAction.registerQuickFixAction(info, SetupJDKFix.getInstnace());
413 else {
414 PsiManager manager = ref.getManager();
415 for (JavaResolveResult result : results) {
416 PsiElement element = result.getElement();
417 if (!(element instanceof PsiModifierListOwner) || !((PsiModifierListOwner)element).hasModifierProperty(PsiModifier.STATIC)) {
418 continue;
420 @NonNls String messageKey = null;
421 if (element instanceof PsiClass) {
422 Pair<PsiImportStatementBase, PsiClass> imported = mySingleImportedClasses.get(refName);
423 PsiClass aClass = imported == null ? null : imported.getSecond();
424 PsiImportStaticStatement statement = (PsiImportStaticStatement)ref.getParent();
426 if (aClass != null && !manager.areElementsEquivalent(aClass, element) && !imported.getFirst().equals(statement)) {
427 messageKey = "class.is.already.defined.in.single.type.import";
429 mySingleImportedClasses.put(refName, Pair.<PsiImportStatementBase, PsiClass>create(statement, (PsiClass)element));
431 else if (element instanceof PsiField) {
432 Pair<PsiImportStaticReferenceElement, PsiField> imported = mySingleImportedFields.get(refName);
433 PsiField field = imported == null ? null : imported.getSecond();
435 if (field != null && !manager.areElementsEquivalent(field, element) && !imported.getFirst().equals(ref.getParent())) {
436 messageKey = "field.is.already.defined.in.single.type.import";
438 mySingleImportedFields.put(refName, Pair.create(ref, (PsiField)element));
441 if (messageKey != null) {
442 String description = JavaErrorMessages.message(messageKey, refName);
443 myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, ref, description));
449 @Override public void visitInstanceOfExpression(PsiInstanceOfExpression expression) {
450 super.visitInstanceOfExpression(expression);
451 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInstanceOfApplicable(expression));
452 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkInstanceOfGenericType(expression));
455 @Override public void visitKeyword(PsiKeyword keyword) {
456 super.visitKeyword(keyword);
457 PsiElement parent = keyword.getParent();
458 if (parent instanceof PsiModifierList) {
459 PsiModifierList psiModifierList = (PsiModifierList)parent;
460 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkNotAllowedModifier(keyword, psiModifierList));
461 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalModifierCombination(keyword, psiModifierList));
462 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkPublicClassInRightFile(keyword, psiModifierList));
463 if (PsiModifier.ABSTRACT.equals(keyword.getText()) && psiModifierList.getParent() instanceof PsiMethod) {
464 if (!myHolder.hasErrorResults()) {
465 myHolder.add(HighlightMethodUtil.checkAbstractMethodInConcreteClass((PsiMethod)psiModifierList.getParent(), keyword));
469 else if (keyword.getText().equals(PsiKeyword.CONTINUE) && parent instanceof PsiContinueStatement) {
470 PsiContinueStatement statement = (PsiContinueStatement)parent;
471 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkContinueOutsideLoop(statement));
473 else if (keyword.getText().equals(PsiKeyword.BREAK) && parent instanceof PsiBreakStatement) {
474 PsiBreakStatement statement = (PsiBreakStatement)parent;
475 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkBreakOutsideLoop(statement));
477 else if (PsiKeyword.INTERFACE.equals(keyword.getText()) && parent instanceof PsiClass) {
478 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkInterfaceCannotBeLocal((PsiClass)parent));
480 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkStaticDeclarationInInnerClass(keyword));
481 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalVoidType(keyword));
483 if (PsiTreeUtil.getParentOfType(keyword, PsiDocTagValue.class) != null) {
484 myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.JAVA_KEYWORD, keyword, null));
488 @Override public void visitLabeledStatement(PsiLabeledStatement statement) {
489 super.visitLabeledStatement(statement);
490 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkLabelWithoutStatement(statement));
491 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkLabelAlreadyInUse(statement));
494 @Override public void visitLiteralExpression(PsiLiteralExpression expression) {
495 super.visitLiteralExpression(expression);
496 if (myHolder.hasErrorResults()) return;
497 myHolder.add(HighlightUtil.checkLiteralExpressionParsingError(expression));
500 @Override public void visitMethod(PsiMethod method) {
501 super.visitMethod(method);
502 if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement(method.getBody()));
503 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorHandleSuperClassExceptions(method));
504 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkRecursiveConstructorInvocation(method));
505 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkOverrideAnnotation(method));
506 if (!myHolder.hasErrorResults() && method.isConstructor()) {
507 myHolder.add(HighlightClassUtil.checkThingNotAllowedInInterface(method, method.getContainingClass()));
509 myHolder.add(HighlightNamesUtil.highlightMethodName(method, method.getNameIdentifier(), true));
512 private void highlightMethodOrClassName(PsiJavaCodeReferenceElement element) {
513 PsiElement parent = element.getParent();
514 if (parent instanceof PsiReferenceExpression || parent instanceof PsiJavaCodeReferenceElement) {
515 return;
517 if (parent instanceof PsiMethodCallExpression) {
518 PsiMethod method = ((PsiMethodCallExpression)parent).resolveMethod();
519 PsiElement methodNameElement = element.getReferenceNameElement();
520 if (method != null && methodNameElement != null) {
521 myHolder.add(HighlightNamesUtil.highlightMethodName(method, methodNameElement, false));
522 myHolder.add(HighlightNamesUtil.highlightClassNameInQualifier(element));
525 else if (parent instanceof PsiConstructorCall) {
526 try {
527 PsiMethod method = ((PsiConstructorCall)parent).resolveConstructor();
528 if (method == null) {
529 PsiElement resolved = element.resolve();
530 if (resolved instanceof PsiClass) {
531 myHolder.add(HighlightNamesUtil.highlightClassName((PsiClass)resolved, element));
534 else {
535 myHolder.add(HighlightNamesUtil.highlightMethodName(method, element, false));
538 catch (IndexNotReadyException e) {
541 else if (parent instanceof PsiImportStatement && ((PsiImportStatement)parent).isOnDemand()) {
542 // highlight on demand import as class
543 myHolder.add(HighlightNamesUtil.highlightClassName(null, element));
545 else {
546 PsiElement resolved = element.resolve();
547 if (resolved instanceof PsiClass) {
548 myHolder.add(HighlightNamesUtil.highlightClassName((PsiClass)resolved, element));
553 @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) {
554 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumSuperConstructorCall(expression));
555 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkSuperQualifierType(expression));
557 if (!myHolder.hasErrorResults()) visitExpression(expression);
560 @Override public void visitModifierList(PsiModifierList list) {
561 super.visitModifierList(list);
562 PsiElement parent = list.getParent();
563 if (!myHolder.hasErrorResults() && parent instanceof PsiMethod) {
564 myHolder.add(HighlightMethodUtil.checkMethodCanHaveBody((PsiMethod)parent));
566 if (parent instanceof PsiMethod) {
567 PsiMethod method = (PsiMethod)parent;
568 MethodSignatureBackedByPsiMethod methodSignature = MethodSignatureBackedByPsiMethod.create(method, PsiSubstitutor.EMPTY);
569 if (!method.isConstructor()) {
570 List<HierarchicalMethodSignature> superMethodSignatures = method.getHierarchicalMethodSignature().getSuperSignatures();
571 if (!superMethodSignatures.isEmpty()) {
572 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodIncompatibleReturnType(methodSignature, superMethodSignatures, true));
573 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodIncompatibleThrows(methodSignature, superMethodSignatures, true, method.getContainingClass()));
574 if (!method.hasModifierProperty(PsiModifier.STATIC)) {
575 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodWeakerPrivileges(methodSignature, superMethodSignatures, true));
576 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkUncheckedOverriding(method, superMethodSignatures));
577 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodOverridesFinal(methodSignature, superMethodSignatures));
581 PsiClass aClass = method.getContainingClass();
582 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodMustHaveBody(method, aClass));
583 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkDuplicateMethod(aClass, method));
584 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallsBaseClassConstructor(method, myRefCountHolder, myResolveHelper));
585 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkStaticMethodOverride(method));
587 else if (parent instanceof PsiClass) {
588 PsiClass aClass = (PsiClass)parent;
589 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkDuplicateNestedClass(aClass));
590 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassMustBeAbstract(aClass));
591 if (!myHolder.hasErrorResults()) {
592 myHolder.add(HighlightClassUtil.checkClassDoesNotCallSuperConstructorOrHandleExceptions(aClass, myRefCountHolder, myResolveHelper));
594 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkOverrideEquivalentInheritedMethods(aClass));
595 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkOverrideEquivalentMethods(aClass));
596 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCyclicInheritance(aClass));
598 else if (parent instanceof PsiEnumConstant) {
599 if (!myHolder.hasErrorResults()) myHolder.addAll(GenericsHighlightUtil.checkEnumConstantModifierList(list));
603 @Override public void visitNameValuePair(PsiNameValuePair pair) {
604 myHolder.add(AnnotationsHighlightUtil.checkNameValuePair(pair));
605 if (!myHolder.hasErrorResults()) {
606 PsiIdentifier nameId = pair.getNameIdentifier();
607 if (nameId != null) myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ANNOTATION_ATTRIBUTE_NAME, nameId, null));
611 @Override public void visitNewExpression(PsiNewExpression expression) {
612 myHolder.add(HighlightUtil.checkUnhandledExceptions(expression, null));
613 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkAnonymousInheritFinal(expression));
614 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkQualifiedNewOfStaticClass(expression));
615 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCreateInnerClassFromStaticContext(expression));
616 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkTypeParameterInstantiation(expression));
617 if (!myHolder.hasErrorResults()) HighlightMethodUtil.checkNewExpression(expression, myHolder);
618 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumInstantiation(expression));
619 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkGenericArrayCreation(expression, expression.getType()));
620 if (!myHolder.hasErrorResults()) registerConstructorCall(expression);
622 if (!myHolder.hasErrorResults()) visitExpression(expression);
625 @Override public void visitOuterLanguageElement(OuterLanguageElement element) {
626 XmlHighlightVisitor.visitJspElement(element);
627 super.visitOuterLanguageElement(element);
630 @Override public void visitPackageStatement(PsiPackageStatement statement) {
631 super.visitPackageStatement(statement);
632 myHolder.add(AnnotationsHighlightUtil.checkPackageAnnotationContainingFile(statement));
635 @Override public void visitParameter(PsiParameter parameter) {
636 super.visitParameter(parameter);
637 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkVarArgParameterIsLast(parameter));
638 if (!myHolder.hasErrorResults() && parameter.getParent() instanceof PsiForeachStatement) {
639 myHolder.add(GenericsHighlightUtil.checkForeachLoopParameterType((PsiForeachStatement)parameter.getParent()));
643 @Override public void visitParameterList(PsiParameterList list) {
644 PsiElement parent = list.getParent();
645 if (parent instanceof PsiAnnotationMethod && list.getParametersCount() > 0) {
646 myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR,
647 list,
648 JavaErrorMessages.message("annotation.interface.members.may.not.have.parameters")));
652 @Override public void visitPostfixExpression(PsiPostfixExpression expression) {
653 super.visitPostfixExpression(expression);
654 if (!myHolder.hasErrorResults()) {
655 myHolder.add(HighlightUtil.checkUnaryOperatorApplicable(expression.getOperationSign(), expression.getOperand()));
659 @Override public void visitPrefixExpression(PsiPrefixExpression expression) {
660 super.visitPrefixExpression(expression);
661 if (!myHolder.hasErrorResults()) {
662 myHolder.add(HighlightUtil.checkUnaryOperatorApplicable(expression.getOperationSign(), expression.getOperand()));
666 private void registerConstructorCall(PsiConstructorCall constructorCall) {
667 if (myRefCountHolder != null) {
668 JavaResolveResult resolveResult = constructorCall.resolveMethodGenerics();
669 final PsiElement resolved = resolveResult.getElement();
670 if (resolved instanceof PsiNamedElement) {
671 myRefCountHolder.registerLocallyReferenced((PsiNamedElement)resolved);
676 @Override public void visitReferenceElement(PsiJavaCodeReferenceElement ref) {
677 JavaResolveResult result = ref.advancedResolve(true);
678 PsiElement resolved = result.getElement();
679 PsiElement parent = ref.getParent();
680 if (myRefCountHolder != null) {
681 myRefCountHolder.registerReference(ref, result);
684 myHolder.add(HighlightUtil.checkReference(ref, result, resolved));
685 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkAbstractInstantiation(ref));
686 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkExtendsDuplicate(ref, resolved));
687 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkExceptionAlreadyCaught(ref, resolved));
688 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassExtendsForeignInnerClass(ref, resolved));
689 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkSelectStaticClassFromParameterizedType(resolved, ref));
690 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, ref, result.getSubstitutor()));
692 if (resolved != null && parent instanceof PsiReferenceList) {
693 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkElementInReferenceList(ref, (PsiReferenceList)parent, result));
696 if (parent instanceof PsiAnonymousClass && ref.equals(((PsiAnonymousClass)parent).getBaseClassReference())) {
697 myHolder.add(GenericsHighlightUtil.checkOverrideEquivalentMethods((PsiClass)parent));
700 if (resolved instanceof PsiVariable) {
701 PsiVariable variable = (PsiVariable)resolved;
703 final PsiClass containingClass = PsiTreeUtil.getParentOfType(ref, PsiClass.class);
704 if (containingClass instanceof PsiAnonymousClass && !PsiTreeUtil.isAncestor(containingClass, variable, false) && !(variable instanceof PsiField)) {
705 if (!PsiTreeUtil.isAncestor(((PsiAnonymousClass) containingClass).getArgumentList(), ref, false)) {
706 myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.IMPLICIT_ANONYMOUS_CLASS_PARAMETER, ref, null));
710 if (!variable.hasModifierProperty(PsiModifier.FINAL) && isReassigned(variable)) {
711 myHolder.add(HighlightNamesUtil.highlightReassignedVariable(variable, ref));
713 else {
714 myHolder.add(HighlightNamesUtil.highlightVariable(variable, ref.getReferenceNameElement()));
716 myHolder.add(HighlightNamesUtil.highlightClassNameInQualifier(ref));
718 else {
719 highlightMethodOrClassName(ref);
723 @Override public void visitReferenceExpression(PsiReferenceExpression expression) {
724 visitReferenceElement(expression);
725 if (!myHolder.hasErrorResults()) {
726 visitExpression(expression);
727 if (myHolder.hasErrorResults()) return;
729 JavaResolveResult result = expression.advancedResolve(false);
730 PsiElement resolved = result.getElement();
731 if (resolved instanceof PsiVariable && resolved.getContainingFile() == expression.getContainingFile()) {
732 if (!myHolder.hasErrorResults()) {
733 myHolder.add(HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, (PsiVariable)resolved, myUninitializedVarProblems));
735 PsiVariable variable = (PsiVariable)resolved;
736 boolean isFinal = variable.hasModifierProperty(PsiModifier.FINAL);
737 if (isFinal && !variable.hasInitializer()) {
738 if (!myHolder.hasErrorResults()) {
739 myHolder.add(HighlightControlFlowUtil.checkFinalVariableMightAlreadyHaveBeenAssignedTo(variable, expression, myFinalVarProblems));
741 if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkFinalVariableInitalizedInLoop(expression, resolved));
744 else {
745 PsiElement parent = expression.getParent();
746 if (parent instanceof PsiMethodCallExpression && ((PsiMethodCallExpression)parent).getMethodExpression() == expression) {
747 myHolder.addAll(HighlightMethodUtil.checkMethodCall((PsiMethodCallExpression)parent, myResolveHelper));
751 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkExpressionRequired(expression));
752 if (!myHolder.hasErrorResults() && resolved instanceof PsiField) {
753 myHolder.add(HighlightUtil.checkIllegalForwardReferenceToField(expression, (PsiField)resolved));
755 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallMustBeFirstStatement(expression));
756 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkAccessStaticFieldFromEnumConstructor(expression, result));
757 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkClassReferenceAfterQualifier(expression, resolved));
760 @Override public void visitReferenceList(PsiReferenceList list) {
761 if (list.getFirstChild() == null) return;
762 PsiElement parent = list.getParent();
763 if (!(parent instanceof PsiTypeParameter)) {
764 myHolder.add(AnnotationsHighlightUtil.checkAnnotationDeclaration(parent, list));
765 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkImplementsAllowed(list));
766 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassExtendsOnlyOneClass(list));
767 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkGenericCannotExtendException(list));
771 @Override public void visitReferenceParameterList(PsiReferenceParameterList list) {
772 myHolder.add(GenericsHighlightUtil.checkParametersOnRaw(list));
775 @Override public void visitReturnStatement(PsiReturnStatement statement) {
776 myHolder.add(HighlightUtil.checkReturnStatementType(statement));
779 @Override public void visitStatement(PsiStatement statement) {
780 super.visitStatement(statement);
781 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkNotAStatement(statement));
782 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkStatementPrependedWithCaseInsideSwitch(statement));
785 @Override public void visitSuperExpression(PsiSuperExpression expr) {
786 myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier()));
787 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkAbstractMethodDirectCall(expr));
788 if (!myHolder.hasErrorResults()) visitExpression(expr);
791 @Override public void visitSwitchLabelStatement(PsiSwitchLabelStatement statement) {
792 super.visitSwitchLabelStatement(statement);
793 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkCaseStatement(statement));
796 @Override public void visitSwitchStatement(PsiSwitchStatement statement) {
797 super.visitSwitchStatement(statement);
798 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSwitchSelectorType(statement));
801 @Override public void visitThisExpression(PsiThisExpression expr) {
802 myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier()));
803 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkMemberReferencedBeforeConstructorCalled(expr));
804 if (!myHolder.hasErrorResults()) {
805 visitExpression(expr);
809 @Override public void visitThrowStatement(PsiThrowStatement statement) {
810 myHolder.add(HighlightUtil.checkUnhandledExceptions(statement, null));
811 if (!myHolder.hasErrorResults()) visitStatement(statement);
814 @Override public void visitTryStatement(PsiTryStatement statement) {
815 super.visitTryStatement(statement);
816 if (!myHolder.hasErrorResults()) {
817 PsiParameter[] parameters = statement.getCatchBlockParameters();
818 for (PsiParameter parameter : parameters) {
819 myHolder.add(HighlightUtil.checkExceptionThrownInTry(parameter));
820 myHolder.add(HighlightUtil.checkCatchParameterIsThrowable(parameter));
821 myHolder.add(GenericsHighlightUtil.checkCatchParameterIsClass(parameter));
826 @Override public void visitTypeElement(PsiTypeElement type) {
827 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalType(type));
828 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkReferenceTypeUsedAsTypeArgument(type));
829 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkWildcardUsage(type));
832 @Override public void visitTypeCastExpression(PsiTypeCastExpression typeCast) {
833 super.visitTypeCastExpression(typeCast);
834 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInconvertibleTypeCast(typeCast));
835 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkUncheckedTypeCast(typeCast));
838 @Override public void visitTypeParameterList(PsiTypeParameterList list) {
839 myHolder.add(GenericsHighlightUtil.checkTypeParametersList(list));
842 @Override public void visitVariable(PsiVariable variable) {
843 super.visitVariable(variable);
844 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkVariableInitializerType(variable));
846 if (isReassigned(variable)) {
847 myHolder.add(HighlightNamesUtil.highlightReassignedVariable(variable, variable.getNameIdentifier()));
849 else {
850 if (variable.getInitializer() == null) {
851 final PsiElement child = variable.getLastChild();
852 if (child instanceof PsiErrorElement && child.getPrevSibling() == variable.getNameIdentifier()) return;
854 myHolder.add(HighlightNamesUtil.highlightVariable(variable, variable.getNameIdentifier()));
858 private boolean isReassigned(PsiVariable variable) {
859 try {
860 return HighlightControlFlowUtil.isReassigned(variable, myFinalVarProblems, myParameterIsReassigned);
862 catch (IndexNotReadyException e) {
863 return false;