good code is red (in presence of raw overriding)
[fedora-idea.git] / java / java-impl / src / com / intellij / codeInsight / daemon / impl / analysis / HighlightVisitorImpl.java
blob2f50f7adb3b5b5dfcee98fda8927c6d4de2b4ae3
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.codeInsight.daemon.impl.analysis;
18 import com.intellij.codeHighlighting.Pass;
19 import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
20 import com.intellij.codeInsight.daemon.JavaErrorMessages;
21 import com.intellij.codeInsight.daemon.impl.*;
22 import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
23 import com.intellij.codeInsight.daemon.impl.quickfix.SetupJDKFix;
24 import com.intellij.lang.injection.InjectedLanguageManager;
25 import com.intellij.openapi.diagnostic.Logger;
26 import com.intellij.openapi.editor.Document;
27 import com.intellij.openapi.progress.ProgressManager;
28 import com.intellij.openapi.project.DumbAware;
29 import com.intellij.openapi.project.IndexNotReadyException;
30 import com.intellij.openapi.project.Project;
31 import com.intellij.openapi.util.Pair;
32 import com.intellij.openapi.util.TextRange;
33 import com.intellij.pom.java.LanguageLevel;
34 import com.intellij.psi.*;
35 import com.intellij.psi.controlFlow.ControlFlowUtil;
36 import com.intellij.psi.impl.source.javadoc.PsiDocMethodOrFieldRef;
37 import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
38 import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
39 import com.intellij.psi.javadoc.PsiDocComment;
40 import com.intellij.psi.javadoc.PsiDocTagValue;
41 import com.intellij.psi.templateLanguages.OuterLanguageElement;
42 import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
43 import com.intellij.psi.util.PsiTreeUtil;
44 import com.intellij.psi.util.PsiUtil;
45 import com.intellij.psi.xml.XmlAttributeValue;
46 import gnu.trove.THashMap;
47 import org.jetbrains.annotations.NonNls;
48 import org.jetbrains.annotations.NotNull;
50 import java.util.Collection;
51 import java.util.List;
52 import java.util.Map;
54 public class HighlightVisitorImpl extends JavaElementVisitor implements HighlightVisitor, DumbAware {
55 private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl");
57 private final PsiResolveHelper myResolveHelper;
59 private HighlightInfoHolder myHolder;
61 private RefCountHolder myRefCountHolder;
63 // map codeBlock->List of PsiReferenceExpression of uninitialized final variables
64 private final Map<PsiElement, Collection<PsiReferenceExpression>> myUninitializedVarProblems = new THashMap<PsiElement, Collection<PsiReferenceExpression>>();
65 // map codeBlock->List of PsiReferenceExpression of extra initialization of final variable
66 private final Map<PsiElement, Collection<ControlFlowUtil.VariableInfo>> myFinalVarProblems = new THashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>();
67 private final Map<PsiParameter, Boolean> myParameterIsReassigned = new THashMap<PsiParameter, Boolean>();
69 private final Map<String, Pair<PsiImportStatementBase, PsiClass>> mySingleImportedClasses = new THashMap<String, Pair<PsiImportStatementBase, PsiClass>>();
70 private final Map<String, Pair<PsiImportStaticReferenceElement, PsiField>> mySingleImportedFields = new THashMap<String, Pair<PsiImportStaticReferenceElement, PsiField>>();
71 private PsiFile myFile;
72 private final PsiElementVisitor REGISTER_REFERENCES_VISITOR = new PsiRecursiveElementWalkingVisitor() {
73 @Override public void visitElement(PsiElement element) {
74 super.visitElement(element);
75 for (PsiReference reference : element.getReferences()) {
76 PsiElement resolved = reference.resolve();
77 if (resolved instanceof PsiNamedElement) {
78 myRefCountHolder.registerLocallyReferenced((PsiNamedElement)resolved);
84 @SuppressWarnings({"UnusedDeclaration"}) //in plugin.xml
85 public HighlightVisitorImpl(Project project) {
86 this(JavaPsiFacade.getInstance(project).getResolveHelper());
89 private HighlightVisitorImpl(@NotNull PsiResolveHelper resolveHelper) {
90 myResolveHelper = resolveHelper;
93 public HighlightVisitorImpl clone() {
94 return new HighlightVisitorImpl(myResolveHelper);
97 public int order() {
98 return 0;
101 public boolean suitableForFile(PsiFile file) {
102 return !InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file);
105 public void visit(PsiElement element, HighlightInfoHolder holder) {
106 myHolder = holder;
108 if (LOG.isDebugEnabled()) {
109 LOG.assertTrue(element.isValid());
111 element.accept(this);
113 if (myRefCountHolder != null) {
114 registerReferencesFromInjectedFragments(element);
118 private void registerReferencesFromInjectedFragments(final PsiElement element) {
119 InjectedLanguageUtil.enumerate(element, myFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
120 public void visit(@NotNull final PsiFile injectedPsi, @NotNull final List<PsiLanguageInjectionHost.Shred> places) {
121 injectedPsi.accept(REGISTER_REFERENCES_VISITOR);
123 }, false);
126 public boolean analyze(final Runnable action, final boolean updateWholeFile, final PsiFile file) {
127 myFile = file;
128 boolean success = true;
129 try {
130 if (updateWholeFile) {
131 Project project = file.getProject();
132 DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(project);
133 FileStatusMap fileStatusMap = ((DaemonCodeAnalyzerImpl)daemonCodeAnalyzer).getFileStatusMap();
134 RefCountHolder refCountHolder = RefCountHolder.getInstance(file);
135 myRefCountHolder = refCountHolder;
136 Document document = PsiDocumentManager.getInstance(project).getDocument(file);
137 TextRange dirtyScope = document == null ? file.getTextRange() : fileStatusMap.getFileDirtyScope(document, Pass.UPDATE_ALL);
138 success = refCountHolder.analyze(action, dirtyScope, file);
140 else {
141 myRefCountHolder = null;
142 action.run();
145 finally {
146 myUninitializedVarProblems.clear();
147 myFinalVarProblems.clear();
148 mySingleImportedClasses.clear();
149 mySingleImportedFields.clear();
150 myParameterIsReassigned.clear();
152 myRefCountHolder = null;
153 myFile = null;
154 myHolder = null;
157 return success;
160 public void visitElement(final PsiElement element) {
161 if (element instanceof XmlAttributeValue) {
162 try {
163 for (PsiReference reference : element.getReferences()) {
164 if(reference instanceof PsiJavaReference && myRefCountHolder != null){
165 final PsiJavaReference psiJavaReference = (PsiJavaReference)reference;
166 myRefCountHolder.registerReference(psiJavaReference, psiJavaReference.advancedResolve(false));
170 catch (IndexNotReadyException ignored) {
175 @Override public void visitAnnotation(PsiAnnotation annotation) {
176 super.visitAnnotation(annotation);
177 if (!PsiUtil.isLanguageLevel5OrHigher(annotation)) {
178 HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, annotation, JavaErrorMessages.message("annotations.prior.15"));
179 QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
180 myHolder.add(info);
181 return;
184 myHolder.add(AnnotationsHighlightUtil.checkApplicability(annotation));
185 if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkAnnotationType(annotation));
186 if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkMissingAttributes(annotation));
187 if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkTargetAnnotationDuplicates(annotation));
188 if (!myHolder.hasErrorResults()) myHolder.add(AnnotationsHighlightUtil.checkDuplicatedAnnotations(annotation));
191 @Override public void visitAnnotationArrayInitializer(PsiArrayInitializerMemberValue initializer) {
192 PsiMethod method = null;
193 PsiElement parent = initializer.getParent();
194 if (parent instanceof PsiNameValuePair) {
195 method = (PsiMethod)parent.getReference().resolve();
197 else if (parent instanceof PsiAnnotationMethod) {
198 method = (PsiMethod)parent;
200 if (method != null) {
201 PsiType type = method.getReturnType();
202 if (type instanceof PsiArrayType) {
203 type = ((PsiArrayType)type).getComponentType();
204 PsiAnnotationMemberValue[] initializers = initializer.getInitializers();
205 for (PsiAnnotationMemberValue initializer1 : initializers) {
206 myHolder.add(AnnotationsHighlightUtil.checkMemberValueType(initializer1, type));
212 @Override public void visitAnnotationMethod(PsiAnnotationMethod method) {
213 PsiType returnType = method.getReturnType();
214 PsiAnnotationMemberValue value = method.getDefaultValue();
215 if (returnType != null && value != null) {
216 myHolder.add(AnnotationsHighlightUtil.checkMemberValueType(value, returnType));
219 myHolder.add(AnnotationsHighlightUtil.checkValidAnnotationType(method.getReturnTypeElement()));
220 myHolder.add(AnnotationsHighlightUtil.checkCyclicMemberType(method.getReturnTypeElement(), method.getContainingClass()));
223 @Override public void visitArrayInitializerExpression(PsiArrayInitializerExpression expression) {
224 super.visitArrayInitializerExpression(expression);
225 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkArrayInitializerApplicable(expression));
226 if (!(expression.getParent() instanceof PsiNewExpression)) {
227 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkGenericArrayCreation(expression, expression.getType()));
231 @Override public void visitAssignmentExpression(PsiAssignmentExpression assignment) {
232 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentCompatibleTypes(assignment));
233 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentOperatorApplicable(assignment));
234 if (!myHolder.hasErrorResults()) visitExpression(assignment);
237 @Override public void visitBinaryExpression(PsiBinaryExpression expression) {
238 super.visitBinaryExpression(expression);
239 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkBinaryOperatorApplicable(expression));
242 @Override public void visitBreakStatement(PsiBreakStatement statement) {
243 super.visitBreakStatement(statement);
244 if (!myHolder.hasErrorResults()) {
245 myHolder.add(HighlightUtil.checkLabelDefined(statement.getLabelIdentifier(), statement.findExitedStatement()));
249 @Override public void visitClass(PsiClass aClass) {
250 super.visitClass(aClass);
251 if (aClass instanceof JspClass) return;
252 if (aClass.isAnnotationType()) {
253 if (!PsiUtil.isLanguageLevel5OrHigher(aClass)) {
254 HighlightInfo info = HighlightInfo
255 .createHighlightInfo(HighlightInfoType.ERROR, aClass.getNameIdentifier(), JavaErrorMessages.message("annotations.prior.15"));
256 QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
257 myHolder.add(info);
260 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkInterfaceMultipleInheritance(aClass));
261 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkDuplicateTopLevelClass(aClass));
262 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumMustNotBeLocal(aClass));
263 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkImplicitThisReferenceBeforeSuper(aClass));
266 @Override public void visitClassInitializer(PsiClassInitializer initializer) {
267 super.visitClassInitializer(initializer);
268 if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkInitializerCompleteNormally(initializer));
269 if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement(initializer.getBody()));
270 if (!myHolder.hasErrorResults()) {
271 myHolder.add(HighlightClassUtil.checkThingNotAllowedInInterface(initializer, initializer.getContainingClass()));
275 @Override public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
276 super.visitClassObjectAccessExpression(expression);
277 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkClassObjectAccessExpression(expression));
280 @Override public void visitComment(PsiComment comment) {
281 super.visitComment(comment);
282 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnclosedComment(comment));
285 @Override public void visitContinueStatement(PsiContinueStatement statement) {
286 super.visitContinueStatement(statement);
287 if (!myHolder.hasErrorResults()) {
288 myHolder.add(HighlightUtil.checkLabelDefined(statement.getLabelIdentifier(), statement.findContinuedStatement()));
292 @Override public void visitJavaToken(PsiJavaToken token) {
293 super.visitJavaToken(token);
294 if (!myHolder.hasErrorResults()
295 && token.getTokenType() == JavaTokenType.RBRACE
296 && token.getParent() instanceof PsiCodeBlock
297 && token.getParent().getParent() instanceof PsiMethod) {
298 PsiMethod method = (PsiMethod)token.getParent().getParent();
299 myHolder.add(HighlightControlFlowUtil.checkMissingReturnStatement(method));
304 @Override public void visitDocComment(PsiDocComment comment) {
305 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnclosedComment(comment));
308 @Override public void visitDocTagValue(PsiDocTagValue value) {
309 if (value.getReference() != null) {
310 PsiReference reference = value.getReference();
311 if (reference != null) {
312 PsiElement element = reference.resolve();
313 if (element instanceof PsiMethod) {
314 myHolder.add(HighlightNamesUtil.highlightMethodName((PsiMethod)element, ((PsiDocMethodOrFieldRef)value).getNameElement(), false));
316 else if (element instanceof PsiParameter) {
317 myHolder.add(HighlightNamesUtil.highlightVariable((PsiVariable)element, value.getNavigationElement()));
323 @Override public void visitEnumConstant(PsiEnumConstant enumConstant) {
324 super.visitEnumConstant(enumConstant);
325 if (!myHolder.hasErrorResults()) GenericsHighlightUtil.checkEnumConstantForConstructorProblems(enumConstant, myHolder);
326 if (!myHolder.hasErrorResults()) registerConstructorCall(enumConstant);
329 @Override public void visitEnumConstantInitializer(PsiEnumConstantInitializer enumConstantInitializer) {
330 super.visitEnumConstantInitializer(enumConstantInitializer);
331 if (!myHolder.hasErrorResults()) {
332 TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(enumConstantInitializer);
333 myHolder.add(HighlightClassUtil.checkClassMustBeAbstract(enumConstantInitializer, textRange));
337 @Override public void visitExpression(PsiExpression expression) {
338 ProgressManager.checkCanceled(); // visitLiteralExpression is invoked very often in array initializers
340 super.visitExpression(expression);
341 if (myHolder.add(HighlightUtil.checkMustBeBoolean(expression))) return;
342 if (expression instanceof PsiArrayAccessExpression
343 && ((PsiArrayAccessExpression)expression).getIndexExpression() != null) {
344 myHolder.add(HighlightUtil.checkValidArrayAccessExpression(((PsiArrayAccessExpression)expression).getArrayExpression(),
345 ((PsiArrayAccessExpression)expression).getIndexExpression()));
347 if (expression.getParent() instanceof PsiNewExpression
348 && ((PsiNewExpression)expression.getParent()).getQualifier() != expression
349 && ((PsiNewExpression)expression.getParent()).getArrayInitializer() != expression) {
350 // like in 'new String["s"]'
351 myHolder.add(HighlightUtil.checkValidArrayAccessExpression(null, expression));
353 if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkCannotWriteToFinal(expression));
354 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkVariableExpected(expression));
355 if (!myHolder.hasErrorResults()) HighlightUtil.checkArrayInitalizer(expression, myHolder);
356 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTernaryOperatorConditionIsBoolean(expression));
357 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssertOperatorTypes(expression));
358 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSynchronizedExpressionType(expression));
359 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkConditionalExpressionBranchTypesMatch(expression));
360 if (!myHolder.hasErrorResults()
361 && expression.getParent() instanceof PsiThrowStatement
362 && ((PsiThrowStatement)expression.getParent()).getException() == expression) {
363 PsiType type = expression.getType();
364 myHolder.add(HighlightUtil.checkMustBeThrowable(type, expression, true));
367 if (!myHolder.hasErrorResults()) {
368 myHolder.add(AnnotationsHighlightUtil.checkConstantExpression(expression));
372 @Override public void visitField(PsiField field) {
373 super.visitField(field);
374 if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkFinalFieldInitialized(field));
377 @Override public void visitForeachStatement(PsiForeachStatement statement) {
378 if (!PsiUtil.isLanguageLevel5OrHigher(statement)) {
379 HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, statement.getFirstChild(), JavaErrorMessages.message("foreach.prior.15"));
380 QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
381 myHolder.add(info);
385 @Override public void visitImportStaticStatement(PsiImportStaticStatement statement) {
386 if (!PsiUtil.isLanguageLevel5OrHigher(statement)) {
387 HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, statement.getFirstChild(), JavaErrorMessages.message("static.imports.prior.15"));
388 QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
389 myHolder.add(info);
393 @Override public void visitIdentifier(PsiIdentifier identifier) {
394 PsiElement parent = identifier.getParent();
395 if (parent instanceof PsiVariable) {
396 myHolder.add(HighlightUtil.checkVariableAlreadyDefined((PsiVariable)parent));
398 else if (parent instanceof PsiClass) {
399 myHolder.add(HighlightClassUtil.checkClassAlreadyImported((PsiClass)parent, identifier));
400 myHolder.add(HighlightClassUtil.checkExternalizableHasPublicNoArgsConstructor((PsiClass)parent, identifier));
401 if (!(parent instanceof PsiAnonymousClass)) {
402 myHolder.add(HighlightNamesUtil.highlightClassName((PsiClass)parent, ((PsiClass)parent).getNameIdentifier()));
405 else if (parent instanceof PsiMethod) {
406 PsiMethod method = (PsiMethod)parent;
407 if (method.isConstructor()) {
408 myHolder.add(HighlightMethodUtil.checkConstructorName(method));
411 super.visitIdentifier(identifier);
414 @Override public void visitImportStatement(PsiImportStatement statement) {
415 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSingleImportClassConflict(statement, mySingleImportedClasses));
418 @Override public void visitImportStaticReferenceElement(PsiImportStaticReferenceElement ref) {
419 String refName = ref.getReferenceName();
420 JavaResolveResult[] results = ref.multiResolve(false);
422 if (results.length == 0) {
423 String description = JavaErrorMessages.message("cannot.resolve.symbol", refName);
424 HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, ref.getReferenceNameElement(), description);
425 myHolder.add(info);
426 QuickFixAction.registerQuickFixAction(info, SetupJDKFix.getInstnace());
428 else {
429 PsiManager manager = ref.getManager();
430 for (JavaResolveResult result : results) {
431 PsiElement element = result.getElement();
432 if (!(element instanceof PsiModifierListOwner) || !((PsiModifierListOwner)element).hasModifierProperty(PsiModifier.STATIC)) {
433 continue;
435 @NonNls String messageKey = null;
436 if (element instanceof PsiClass) {
437 Pair<PsiImportStatementBase, PsiClass> imported = mySingleImportedClasses.get(refName);
438 PsiClass aClass = imported == null ? null : imported.getSecond();
439 PsiImportStaticStatement statement = (PsiImportStaticStatement)ref.getParent();
441 if (aClass != null && !manager.areElementsEquivalent(aClass, element) && !imported.getFirst().equals(statement)) {
442 messageKey = "class.is.already.defined.in.single.type.import";
444 mySingleImportedClasses.put(refName, Pair.<PsiImportStatementBase, PsiClass>create(statement, (PsiClass)element));
446 else if (element instanceof PsiField) {
447 Pair<PsiImportStaticReferenceElement, PsiField> imported = mySingleImportedFields.get(refName);
448 PsiField field = imported == null ? null : imported.getSecond();
450 if (field != null && !manager.areElementsEquivalent(field, element) && !imported.getFirst().equals(ref.getParent())) {
451 messageKey = "field.is.already.defined.in.single.type.import";
453 mySingleImportedFields.put(refName, Pair.create(ref, (PsiField)element));
456 if (messageKey != null) {
457 String description = JavaErrorMessages.message(messageKey, refName);
458 myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, ref, description));
464 @Override public void visitInstanceOfExpression(PsiInstanceOfExpression expression) {
465 super.visitInstanceOfExpression(expression);
466 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInstanceOfApplicable(expression));
467 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkInstanceOfGenericType(expression));
470 @Override public void visitKeyword(PsiKeyword keyword) {
471 super.visitKeyword(keyword);
472 PsiElement parent = keyword.getParent();
473 if (parent instanceof PsiModifierList) {
474 PsiModifierList psiModifierList = (PsiModifierList)parent;
475 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkNotAllowedModifier(keyword, psiModifierList));
476 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalModifierCombination(keyword, psiModifierList));
477 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkPublicClassInRightFile(keyword, psiModifierList));
478 if (PsiModifier.ABSTRACT.equals(keyword.getText()) && psiModifierList.getParent() instanceof PsiMethod) {
479 if (!myHolder.hasErrorResults()) {
480 myHolder.add(HighlightMethodUtil.checkAbstractMethodInConcreteClass((PsiMethod)psiModifierList.getParent(), keyword));
484 else if (keyword.getText().equals(PsiKeyword.CONTINUE) && parent instanceof PsiContinueStatement) {
485 PsiContinueStatement statement = (PsiContinueStatement)parent;
486 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkContinueOutsideLoop(statement));
488 else if (keyword.getText().equals(PsiKeyword.BREAK) && parent instanceof PsiBreakStatement) {
489 PsiBreakStatement statement = (PsiBreakStatement)parent;
490 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkBreakOutsideLoop(statement));
492 else if (PsiKeyword.INTERFACE.equals(keyword.getText()) && parent instanceof PsiClass) {
493 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkInterfaceCannotBeLocal((PsiClass)parent));
495 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkStaticDeclarationInInnerClass(keyword));
496 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalVoidType(keyword));
498 if (PsiTreeUtil.getParentOfType(keyword, PsiDocTagValue.class) != null) {
499 myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.JAVA_KEYWORD, keyword, null));
503 @Override public void visitLabeledStatement(PsiLabeledStatement statement) {
504 super.visitLabeledStatement(statement);
505 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkLabelWithoutStatement(statement));
506 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkLabelAlreadyInUse(statement));
509 @Override public void visitLiteralExpression(PsiLiteralExpression expression) {
510 super.visitLiteralExpression(expression);
511 if (myHolder.hasErrorResults()) return;
512 myHolder.add(HighlightUtil.checkLiteralExpressionParsingError(expression));
515 @Override public void visitMethod(PsiMethod method) {
516 super.visitMethod(method);
517 if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement(method.getBody()));
518 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorHandleSuperClassExceptions(method));
519 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkRecursiveConstructorInvocation(method));
520 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkOverrideAnnotation(method));
521 if (!myHolder.hasErrorResults() && method.isConstructor()) {
522 myHolder.add(HighlightClassUtil.checkThingNotAllowedInInterface(method, method.getContainingClass()));
524 myHolder.add(HighlightNamesUtil.highlightMethodName(method, method.getNameIdentifier(), true));
527 private void highlightMethodOrClassName(PsiJavaCodeReferenceElement element) {
528 PsiElement parent = element.getParent();
529 if (parent instanceof PsiReferenceExpression || parent instanceof PsiJavaCodeReferenceElement) {
530 return;
532 if (parent instanceof PsiMethodCallExpression) {
533 PsiMethod method = ((PsiMethodCallExpression)parent).resolveMethod();
534 PsiElement methodNameElement = element.getReferenceNameElement();
535 if (method != null && methodNameElement != null) {
536 myHolder.add(HighlightNamesUtil.highlightMethodName(method, methodNameElement, false));
537 myHolder.add(HighlightNamesUtil.highlightClassNameInQualifier(element));
540 else if (parent instanceof PsiConstructorCall) {
541 try {
542 PsiMethod method = ((PsiConstructorCall)parent).resolveConstructor();
543 if (method == null) {
544 PsiElement resolved = element.resolve();
545 if (resolved instanceof PsiClass) {
546 myHolder.add(HighlightNamesUtil.highlightClassName((PsiClass)resolved, element));
549 else {
550 myHolder.add(HighlightNamesUtil.highlightMethodName(method, element, false));
553 catch (IndexNotReadyException ignored) {
556 else if (parent instanceof PsiImportStatement && ((PsiImportStatement)parent).isOnDemand()) {
557 // highlight on demand import as class
558 myHolder.add(HighlightNamesUtil.highlightClassName(null, element));
560 else {
561 PsiElement resolved = element.resolve();
562 if (resolved instanceof PsiClass) {
563 myHolder.add(HighlightNamesUtil.highlightClassName((PsiClass)resolved, element));
568 @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) {
569 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumSuperConstructorCall(expression));
570 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkSuperQualifierType(expression));
572 if (!myHolder.hasErrorResults()) visitExpression(expression);
575 @Override public void visitModifierList(PsiModifierList list) {
576 super.visitModifierList(list);
577 PsiElement parent = list.getParent();
578 if (!myHolder.hasErrorResults() && parent instanceof PsiMethod) {
579 myHolder.add(HighlightMethodUtil.checkMethodCanHaveBody((PsiMethod)parent));
581 if (parent instanceof PsiMethod) {
582 PsiMethod method = (PsiMethod)parent;
583 MethodSignatureBackedByPsiMethod methodSignature = MethodSignatureBackedByPsiMethod.create(method, PsiSubstitutor.EMPTY);
584 if (!method.isConstructor()) {
585 List<HierarchicalMethodSignature> superMethodSignatures = method.getHierarchicalMethodSignature().getSuperSignatures();
586 if (!superMethodSignatures.isEmpty()) {
587 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodIncompatibleReturnType(methodSignature, superMethodSignatures, true));
588 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodIncompatibleThrows(methodSignature, superMethodSignatures, true, method.getContainingClass()));
589 if (!method.hasModifierProperty(PsiModifier.STATIC)) {
590 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodWeakerPrivileges(methodSignature, superMethodSignatures, true));
591 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkUncheckedOverriding(method, superMethodSignatures));
592 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodOverridesFinal(methodSignature, superMethodSignatures));
596 PsiClass aClass = method.getContainingClass();
597 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodMustHaveBody(method, aClass));
598 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkDuplicateMethod(aClass, method));
599 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallsBaseClassConstructor(method, myRefCountHolder, myResolveHelper));
600 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkStaticMethodOverride(method));
602 else if (parent instanceof PsiClass) {
603 PsiClass aClass = (PsiClass)parent;
604 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkDuplicateNestedClass(aClass));
605 if (!myHolder.hasErrorResults()) {
606 TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass);
607 myHolder.add(HighlightClassUtil.checkClassMustBeAbstract(aClass, textRange));
609 if (!myHolder.hasErrorResults()) {
610 myHolder.add(HighlightClassUtil.checkClassDoesNotCallSuperConstructorOrHandleExceptions(aClass, myRefCountHolder, myResolveHelper));
612 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkOverrideEquivalentInheritedMethods(aClass));
613 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkOverrideEquivalentMethods(aClass));
614 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCyclicInheritance(aClass));
616 else if (parent instanceof PsiEnumConstant) {
617 if (!myHolder.hasErrorResults()) myHolder.addAll(GenericsHighlightUtil.checkEnumConstantModifierList(list));
621 @Override public void visitNameValuePair(PsiNameValuePair pair) {
622 myHolder.add(AnnotationsHighlightUtil.checkNameValuePair(pair));
623 if (!myHolder.hasErrorResults()) {
624 PsiIdentifier nameId = pair.getNameIdentifier();
625 if (nameId != null) myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ANNOTATION_ATTRIBUTE_NAME, nameId, null));
629 @Override public void visitNewExpression(PsiNewExpression expression) {
630 myHolder.add(HighlightUtil.checkUnhandledExceptions(expression, null));
631 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkAnonymousInheritFinal(expression));
632 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkQualifiedNewOfStaticClass(expression));
633 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCreateInnerClassFromStaticContext(expression));
634 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkTypeParameterInstantiation(expression));
635 if (!myHolder.hasErrorResults()) HighlightMethodUtil.checkNewExpression(expression, myHolder);
636 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumInstantiation(expression));
637 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkGenericArrayCreation(expression, expression.getType()));
638 if (!myHolder.hasErrorResults()) registerConstructorCall(expression);
640 if (!myHolder.hasErrorResults()) visitExpression(expression);
643 @Override public void visitOuterLanguageElement(OuterLanguageElement element) {
644 XmlHighlightVisitor.visitJspElement(element);
645 super.visitOuterLanguageElement(element);
648 @Override public void visitPackageStatement(PsiPackageStatement statement) {
649 super.visitPackageStatement(statement);
650 myHolder.add(AnnotationsHighlightUtil.checkPackageAnnotationContainingFile(statement));
653 @Override public void visitParameter(PsiParameter parameter) {
654 super.visitParameter(parameter);
655 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkVarArgParameterIsLast(parameter));
656 if (!myHolder.hasErrorResults() && parameter.getParent() instanceof PsiForeachStatement) {
657 myHolder.add(GenericsHighlightUtil.checkForeachLoopParameterType((PsiForeachStatement)parameter.getParent()));
661 @Override public void visitParameterList(PsiParameterList list) {
662 PsiElement parent = list.getParent();
663 if (parent instanceof PsiAnnotationMethod && list.getParametersCount() > 0) {
664 myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR,
665 list,
666 JavaErrorMessages.message("annotation.interface.members.may.not.have.parameters")));
670 @Override public void visitPostfixExpression(PsiPostfixExpression expression) {
671 super.visitPostfixExpression(expression);
672 if (!myHolder.hasErrorResults()) {
673 myHolder.add(HighlightUtil.checkUnaryOperatorApplicable(expression.getOperationSign(), expression.getOperand()));
677 @Override public void visitPrefixExpression(PsiPrefixExpression expression) {
678 super.visitPrefixExpression(expression);
679 if (!myHolder.hasErrorResults()) {
680 myHolder.add(HighlightUtil.checkUnaryOperatorApplicable(expression.getOperationSign(), expression.getOperand()));
684 private void registerConstructorCall(PsiConstructorCall constructorCall) {
685 if (myRefCountHolder != null) {
686 JavaResolveResult resolveResult = constructorCall.resolveMethodGenerics();
687 final PsiElement resolved = resolveResult.getElement();
688 if (resolved instanceof PsiNamedElement) {
689 myRefCountHolder.registerLocallyReferenced((PsiNamedElement)resolved);
694 @Override public void visitReferenceElement(PsiJavaCodeReferenceElement ref) {
695 JavaResolveResult result;
696 try {
697 result = ref.advancedResolve(true);
699 catch (IndexNotReadyException e) {
700 return;
702 PsiElement resolved = result.getElement();
703 PsiElement parent = ref.getParent();
704 if (myRefCountHolder != null) {
705 myRefCountHolder.registerReference(ref, result);
708 myHolder.add(HighlightUtil.checkReference(ref, result, resolved));
709 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkAbstractInstantiation(ref));
710 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkExtendsDuplicate(ref, resolved));
711 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkExceptionAlreadyCaught(ref, resolved));
712 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassExtendsForeignInnerClass(ref, resolved));
713 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkSelectStaticClassFromParameterizedType(resolved, ref));
714 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkParameterizedReferenceTypeArguments(resolved, ref, result.getSubstitutor()));
716 if (resolved != null && parent instanceof PsiReferenceList) {
717 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkElementInReferenceList(ref, (PsiReferenceList)parent, result));
720 if (parent instanceof PsiAnonymousClass && ref.equals(((PsiAnonymousClass)parent).getBaseClassReference())) {
721 myHolder.add(GenericsHighlightUtil.checkOverrideEquivalentMethods((PsiClass)parent));
724 if (resolved instanceof PsiVariable) {
725 PsiVariable variable = (PsiVariable)resolved;
727 final PsiClass containingClass = PsiTreeUtil.getParentOfType(ref, PsiClass.class);
728 if (containingClass instanceof PsiAnonymousClass && !PsiTreeUtil.isAncestor(containingClass, variable, false) && !(variable instanceof PsiField)) {
729 if (!PsiTreeUtil.isAncestor(((PsiAnonymousClass) containingClass).getArgumentList(), ref, false)) {
730 myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.IMPLICIT_ANONYMOUS_CLASS_PARAMETER, ref, null));
734 if (!variable.hasModifierProperty(PsiModifier.FINAL) && isReassigned(variable)) {
735 myHolder.add(HighlightNamesUtil.highlightReassignedVariable(variable, ref));
737 else {
738 myHolder.add(HighlightNamesUtil.highlightVariable(variable, ref.getReferenceNameElement()));
740 myHolder.add(HighlightNamesUtil.highlightClassNameInQualifier(ref));
742 else {
743 highlightMethodOrClassName(ref);
747 @Override public void visitReferenceExpression(PsiReferenceExpression expression) {
748 visitReferenceElement(expression);
749 if (!myHolder.hasErrorResults()) {
750 visitExpression(expression);
751 if (myHolder.hasErrorResults()) return;
753 JavaResolveResult result;
754 try {
755 result = expression.advancedResolve(false);
757 catch (IndexNotReadyException e) {
758 return;
760 PsiElement resolved = result.getElement();
761 if (resolved instanceof PsiVariable && resolved.getContainingFile() == expression.getContainingFile()) {
762 if (!myHolder.hasErrorResults()) {
763 myHolder.add(HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, (PsiVariable)resolved, myUninitializedVarProblems));
765 PsiVariable variable = (PsiVariable)resolved;
766 boolean isFinal = variable.hasModifierProperty(PsiModifier.FINAL);
767 if (isFinal && !variable.hasInitializer()) {
768 if (!myHolder.hasErrorResults()) {
769 myHolder.add(HighlightControlFlowUtil.checkFinalVariableMightAlreadyHaveBeenAssignedTo(variable, expression, myFinalVarProblems));
771 if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkFinalVariableInitalizedInLoop(expression, resolved));
774 else {
775 PsiElement parent = expression.getParent();
776 PsiMethodCallExpression methodCall;
778 if (parent instanceof PsiMethodCallExpression && (methodCall = (PsiMethodCallExpression)parent).getMethodExpression() == expression) {
779 myHolder.addAll(HighlightMethodUtil.checkMethodCall(methodCall, myResolveHelper));
783 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkExpressionRequired(expression));
784 if (!myHolder.hasErrorResults() && resolved instanceof PsiField) {
785 myHolder.add(HighlightUtil.checkIllegalForwardReferenceToField(expression, (PsiField)resolved));
787 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallMustBeFirstStatement(expression));
788 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkAccessStaticFieldFromEnumConstructor(expression, result));
789 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkClassReferenceAfterQualifier(expression, resolved));
792 @Override public void visitReferenceList(PsiReferenceList list) {
793 if (list.getFirstChild() == null) return;
794 PsiElement parent = list.getParent();
795 if (!(parent instanceof PsiTypeParameter)) {
796 myHolder.add(AnnotationsHighlightUtil.checkAnnotationDeclaration(parent, list));
797 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkImplementsAllowed(list));
798 if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassExtendsOnlyOneClass(list));
799 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkGenericCannotExtendException(list));
803 @Override public void visitReferenceParameterList(PsiReferenceParameterList list) {
804 myHolder.add(GenericsHighlightUtil.checkParametersOnRaw(list));
807 @Override public void visitReturnStatement(PsiReturnStatement statement) {
808 myHolder.add(HighlightUtil.checkReturnStatementType(statement));
811 @Override public void visitStatement(PsiStatement statement) {
812 super.visitStatement(statement);
813 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkNotAStatement(statement));
814 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkStatementPrependedWithCaseInsideSwitch(statement));
817 @Override public void visitSuperExpression(PsiSuperExpression expr) {
818 myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier()));
819 if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkAbstractMethodDirectCall(expr));
820 if (!myHolder.hasErrorResults()) visitExpression(expr);
823 @Override public void visitSwitchLabelStatement(PsiSwitchLabelStatement statement) {
824 super.visitSwitchLabelStatement(statement);
825 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkCaseStatement(statement));
828 @Override public void visitSwitchStatement(PsiSwitchStatement statement) {
829 super.visitSwitchStatement(statement);
830 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSwitchSelectorType(statement));
833 @Override public void visitThisExpression(PsiThisExpression expr) {
834 myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier()));
835 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkMemberReferencedBeforeConstructorCalled(expr));
836 if (!myHolder.hasErrorResults()) {
837 visitExpression(expr);
841 @Override public void visitThrowStatement(PsiThrowStatement statement) {
842 myHolder.add(HighlightUtil.checkUnhandledExceptions(statement, null));
843 if (!myHolder.hasErrorResults()) visitStatement(statement);
846 @Override public void visitTryStatement(PsiTryStatement statement) {
847 super.visitTryStatement(statement);
848 if (!myHolder.hasErrorResults()) {
849 PsiParameter[] parameters = statement.getCatchBlockParameters();
850 for (PsiParameter parameter : parameters) {
851 myHolder.add(HighlightUtil.checkExceptionThrownInTry(parameter));
852 myHolder.add(HighlightUtil.checkCatchParameterIsThrowable(parameter));
853 myHolder.add(GenericsHighlightUtil.checkCatchParameterIsClass(parameter));
858 @Override public void visitTypeElement(PsiTypeElement type) {
859 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalType(type));
860 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkReferenceTypeUsedAsTypeArgument(type));
861 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkWildcardUsage(type));
864 @Override public void visitTypeCastExpression(PsiTypeCastExpression typeCast) {
865 super.visitTypeCastExpression(typeCast);
866 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInconvertibleTypeCast(typeCast));
867 if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkUncheckedTypeCast(typeCast));
870 @Override public void visitTypeParameterList(PsiTypeParameterList list) {
871 myHolder.add(GenericsHighlightUtil.checkTypeParametersList(list));
874 @Override public void visitVariable(PsiVariable variable) {
875 super.visitVariable(variable);
876 if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkVariableInitializerType(variable));
878 if (isReassigned(variable)) {
879 myHolder.add(HighlightNamesUtil.highlightReassignedVariable(variable, variable.getNameIdentifier()));
881 else {
882 if (variable.getInitializer() == null) {
883 final PsiElement child = variable.getLastChild();
884 if (child instanceof PsiErrorElement && child.getPrevSibling() == variable.getNameIdentifier()) return;
886 myHolder.add(HighlightNamesUtil.highlightVariable(variable, variable.getNameIdentifier()));
890 private boolean isReassigned(PsiVariable variable) {
891 try {
892 return HighlightControlFlowUtil.isReassigned(variable, myFinalVarProblems, myParameterIsReassigned);
894 catch (IndexNotReadyException e) {
895 return false;