@Override public boolean checkApplicability( @NotNull AnnotationHolder holder, @NotNull GrAnnotation annotation) { final String qname = annotation.getQualifiedName(); if (!GroovyCommonClassNames.GROOVY_TRANSFORM_FIELD.equals(qname)) return false; checkScriptField(holder, annotation); PsiElement annoParent = annotation.getParent(); PsiElement ownerToUse = annoParent instanceof PsiModifierList ? annoParent.getParent() : annoParent; if (!(ownerToUse instanceof GrVariableDeclaration) || !PsiUtil.isLocalVariable(((GrVariableDeclaration) ownerToUse).getVariables()[0])) { return false; } if (!GrAnnotationImpl.isAnnotationApplicableTo( annotation, PsiAnnotation.TargetType.LOCAL_VARIABLE)) { GrCodeReferenceElement ref = annotation.getClassReference(); String target = JavaErrorMessages.message("annotation.target.LOCAL_VARIABLE"); String description = JavaErrorMessages.message("annotation.not.applicable", ref.getText(), target); holder.createErrorAnnotation(ref, description); } return true; }
@Nullable public PsiBuilder.Marker parseConditional(final PsiBuilder builder) { final PsiBuilder.Marker condition = parseExpression(builder, ExprType.CONDITIONAL_OR); if (condition == null) return null; if (builder.getTokenType() != JavaTokenType.QUEST) return condition; final PsiBuilder.Marker ternary = condition.precede(); builder.advanceLexer(); final PsiBuilder.Marker truePart = parse(builder); if (truePart == null) { error(builder, JavaErrorMessages.message("expected.expression")); ternary.done(JavaElementType.CONDITIONAL_EXPRESSION); return ternary; } if (builder.getTokenType() != JavaTokenType.COLON) { error(builder, JavaErrorMessages.message("expected.colon")); ternary.done(JavaElementType.CONDITIONAL_EXPRESSION); return ternary; } builder.advanceLexer(); final PsiBuilder.Marker falsePart = parseConditional(builder); if (falsePart == null) { error(builder, JavaErrorMessages.message("expected.expression")); ternary.done(JavaElementType.CONDITIONAL_EXPRESSION); return ternary; } ternary.done(JavaElementType.CONDITIONAL_EXPRESSION); return ternary; }
@SuppressWarnings({"UnresolvedPropertyKey"}) public String getUnresolvedMessagePattern(int index) { if (canReferencePackage(index)) { return JavaErrorMessages.message("error.cannot.resolve.class.or.package"); } return JavaErrorMessages.message("error.cannot.resolve.class"); }
@Nullable static HighlightInfo checkFileDuplicates(@NotNull PsiJavaModule element, @NotNull PsiFile file) { Module module = ModuleUtilCore.findModuleForPsiElement(element); if (module != null) { Project project = file.getProject(); Collection<VirtualFile> others = FilenameIndex.getVirtualFilesByName(project, MODULE_INFO_FILE, new ModulesScope(module)); if (others.size() > 1) { String message = JavaErrorMessages.message("module.file.duplicate"); HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(range(element)) .description(message) .create(); others .stream() .map(f -> PsiManager.getInstance(project).findFile(f)) .filter(f -> f != file) .findFirst() .ifPresent( duplicate -> QuickFixAction.registerQuickFixAction( info, new GoToSymbolFix( duplicate, JavaErrorMessages.message("module.open.duplicate.text")))); return info; } } return null; }
@Nullable private PsiBuilder.Marker parseUnary(final PsiBuilder builder) { final IElementType tokenType = builder.getTokenType(); if (PREFIX_OPS.contains(tokenType)) { final PsiBuilder.Marker unary = builder.mark(); builder.advanceLexer(); final PsiBuilder.Marker operand = parseUnary(builder); if (operand == null) { error(builder, JavaErrorMessages.message("expected.expression")); } unary.done(JavaElementType.PREFIX_EXPRESSION); return unary; } else if (tokenType == JavaTokenType.LPARENTH) { final PsiBuilder.Marker typeCast = builder.mark(); builder.advanceLexer(); ReferenceParser.TypeInfo typeInfo = myParser .getReferenceParser() .parseTypeInfo( builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD | ReferenceParser.CONJUNCTIONS | ReferenceParser.INCOMPLETE_ANNO); if (typeInfo == null || !expect(builder, JavaTokenType.RPARENTH)) { typeCast.rollbackTo(); return parsePostfix(builder); } if (PREF_ARITHMETIC_OPS.contains(builder.getTokenType()) && !typeInfo.isPrimitive) { typeCast.rollbackTo(); return parsePostfix(builder); } final PsiBuilder.Marker expr = parseUnary(builder); if (expr == null) { if (!typeInfo .isParameterized) { // cannot parse correct parenthesized expression after correct // parameterized type typeCast.rollbackTo(); return parsePostfix(builder); } else { error(builder, JavaErrorMessages.message("expected.expression")); } } typeCast.done(JavaElementType.TYPE_CAST_EXPRESSION); return typeCast; } else { return parsePostfix(builder); } }
@Nullable private PsiBuilder.Marker parseArrayInitializer(final PsiBuilder builder) { if (builder.getTokenType() != JavaTokenType.LBRACE) return null; final PsiBuilder.Marker arrayInit = builder.mark(); builder.advanceLexer(); boolean expressionMissed = false; PsiBuilder.Marker lastComma = null; while (true) { if (builder.getTokenType() == JavaTokenType.RBRACE) { builder.advanceLexer(); break; } if (builder.getTokenType() == null) { error(builder, JavaErrorMessages.message("expected.rbrace")); break; } if (expressionMissed && lastComma != null) { // before comma must be an expression lastComma .precede() .errorBefore(JavaErrorMessages.message("expected.expression"), lastComma); lastComma.drop(); lastComma = null; } final PsiBuilder.Marker arg = parse(builder); if (arg == null) { if (builder.getTokenType() == JavaTokenType.COMMA) { expressionMissed = true; lastComma = builder.mark(); } else { error(builder, JavaErrorMessages.message("expected.rbrace")); break; } } final IElementType tokenType = builder.getTokenType(); if (tokenType == JavaTokenType.COMMA) { builder.advanceLexer(); } else if (tokenType != JavaTokenType.RBRACE) { error(builder, JavaErrorMessages.message("expected.comma")); } } if (lastComma != null) { lastComma.drop(); } arrayInit.done(JavaElementType.ARRAY_INITIALIZER_EXPRESSION); return arrayInit; }
@Nullable static HighlightInfo checkFinalFieldInitialized(@NotNull PsiField field) { if (!field.hasModifierProperty(PsiModifier.FINAL)) return null; if (isFieldInitializedAfterObjectConstruction(field)) return null; String description = JavaErrorMessages.message("variable.not.initialized", field.getName()); TextRange range = HighlightNamesUtil.getFieldDeclarationTextRange(field); HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(range) .descriptionAndTooltip(description) .create(); QuickFixAction.registerQuickFixAction( highlightInfo, HighlightMethodUtil.getFixRange(field), QUICK_FIX_FACTORY.createCreateConstructorParameterFromFieldFix(field)); QuickFixAction.registerQuickFixAction( highlightInfo, HighlightMethodUtil.getFixRange(field), QUICK_FIX_FACTORY.createInitializeFinalFieldInConstructorFix(field)); final PsiClass containingClass = field.getContainingClass(); if (containingClass != null && !containingClass.isInterface()) { QuickFixAction.registerQuickFixAction( highlightInfo, QUICK_FIX_FACTORY.createModifierListFix(field, PsiModifier.FINAL, false, false)); } QuickFixAction.registerQuickFixAction( highlightInfo, QUICK_FIX_FACTORY.createAddVariableInitializerFix(field)); return highlightInfo; }
@NotNull static List<HighlightInfo> checkDuplicateRequires(@NotNull PsiJavaModule module) { List<HighlightInfo> results = ContainerUtil.newSmartList(); Map<String, PsiElement> map = ContainerUtil.newHashMap(); for (PsiElement child = module.getFirstChild(); child != null; child = child.getNextSibling()) { if (child instanceof PsiRequiresStatement) { PsiJavaModuleReferenceElement ref = ((PsiRequiresStatement) child).getReferenceElement(); if (ref != null) { String text = ref.getReferenceText(); if (!map.containsKey(text)) { map.put(text, child); } else { String message = JavaErrorMessages.message("module.duplicate.requires", text); HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(child) .description(message) .create(); QuickFixAction.registerQuickFixAction(info, new DeleteElementFix(child)); results.add(info); } } } } return results; }
@Nullable private PsiBuilder.Marker parseLambdaExpression( final PsiBuilder builder, final boolean typed, @Nullable final PsiBuilder.Marker typeList) { final PsiBuilder.Marker start = typeList != null ? typeList.precede() : builder.mark(); myParser.getDeclarationParser().parseLambdaParameterList(builder, typed); if (!expect(builder, JavaTokenType.ARROW)) { start.rollbackTo(); return null; } final PsiBuilder.Marker body; if (builder.getTokenType() == JavaTokenType.LBRACE) { body = myParser.getStatementParser().parseCodeBlock(builder); } else { body = parse(builder); } if (body == null) { builder.error(JavaErrorMessages.message("expected.lbrace")); } start.done(JavaElementType.LAMBDA_EXPRESSION); return start; }
@Nullable private static PsiBuilder.Marker parseBinary( final PsiBuilder builder, final ExprType type, final TokenSet ops) { PsiBuilder.Marker left = parseExpression(builder, type); if (left == null) return null; while (true) { final IElementType tokenType = getGtTokenType(builder); if (tokenType == null || !ops.contains(tokenType)) break; final PsiBuilder.Marker binary = left.precede(); advanceGtToken(builder, tokenType); final PsiBuilder.Marker right = parseExpression(builder, type); if (right == null) { error(builder, JavaErrorMessages.message("expected.expression")); binary.done(JavaElementType.BINARY_EXPRESSION); return binary; } binary.done(JavaElementType.BINARY_EXPRESSION); left = binary; } return left; }
@Nullable public static HighlightInfo checkMissingReturnStatement(PsiCodeBlock body, PsiType returnType) { if (body == null || returnType == null || PsiType.VOID.equals(returnType.getDeepComponentType())) { return null; } // do not compute constant expressions for if() statement condition // see JLS 14.20 Unreachable Statements try { ControlFlow controlFlow = getControlFlowNoConstantEvaluate(body); if (!ControlFlowUtil.returnPresent(controlFlow)) { PsiJavaToken rBrace = body.getRBrace(); PsiElement context = rBrace == null ? body.getLastChild() : rBrace; String message = JavaErrorMessages.message("missing.return.statement"); HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(context) .descriptionAndTooltip(message) .create(); PsiElement parent = body.getParent(); if (parent instanceof PsiMethod) { PsiMethod method = (PsiMethod) parent; QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createAddReturnFix(method)); QuickFixAction.registerQuickFixAction( info, QUICK_FIX_FACTORY.createMethodReturnFix(method, PsiType.VOID, true)); } return info; } } catch (AnalysisCanceledException ignored) { } return null; }
@Nullable private static String doCheckRepeatableAnnotation(@NotNull PsiAnnotation annotation) { PsiAnnotationOwner owner = annotation.getOwner(); if (!(owner instanceof PsiModifierList)) return null; PsiElement target = ((PsiModifierList) owner).getParent(); if (!(target instanceof PsiClass) || !((PsiClass) target).isAnnotationType()) return null; PsiClass container = getRepeatableContainer(annotation); if (container == null) return null; PsiMethod[] methods = container.findMethodsByName("value", false); if (methods.length == 0) { return JavaErrorMessages.message( "annotation.container.no.value", container.getQualifiedName()); } if (methods.length == 1) { PsiType expected = new PsiImmediateClassType((PsiClass) target, PsiSubstitutor.EMPTY).createArrayType(); if (!expected.equals(methods[0].getReturnType())) { return JavaErrorMessages.message( "annotation.container.bad.type", container.getQualifiedName(), JavaHighlightUtil.formatType(expected)); } } RetentionPolicy targetPolicy = getRetentionPolicy((PsiClass) target); if (targetPolicy != null) { RetentionPolicy containerPolicy = getRetentionPolicy(container); if (containerPolicy != null && targetPolicy.compareTo(containerPolicy) > 0) { return JavaErrorMessages.message( "annotation.container.low.retention", container.getQualifiedName(), containerPolicy); } } Set<PsiAnnotation.TargetType> repeatableTargets = PsiImplUtil.getAnnotationTargets((PsiClass) target); if (repeatableTargets != null) { Set<PsiAnnotation.TargetType> containerTargets = PsiImplUtil.getAnnotationTargets(container); if (containerTargets != null && !repeatableTargets.containsAll(containerTargets)) { return JavaErrorMessages.message( "annotation.container.wide.target", container.getQualifiedName()); } } return null; }
@NotNull public static PsiBuilder.Marker parseArgumentList(final PsiBuilder builder) { final PsiBuilder.Marker list = builder.mark(); builder.advanceLexer(); boolean first = true; while (true) { final IElementType tokenType = builder.getTokenType(); if (first && (ARGS_LIST_END.contains(tokenType) || builder.eof())) break; if (!first && !ARGS_LIST_CONTINUE.contains(tokenType)) break; boolean hasError = false; if (!first) { if (builder.getTokenType() == JavaTokenType.COMMA) { builder.advanceLexer(); } else { hasError = true; error(builder, JavaErrorMessages.message("expected.comma.or.rparen")); emptyExpression(builder); } } first = false; final PsiBuilder.Marker arg = parse(builder); if (arg == null) { if (!hasError) { error(builder, JavaErrorMessages.message("expected.expression")); emptyExpression(builder); } if (!ARGS_LIST_CONTINUE.contains(builder.getTokenType())) break; if (builder.getTokenType() != JavaTokenType.COMMA && !builder.eof()) { builder.advanceLexer(); } } } final boolean closed = JavaParserUtil.expectOrError( builder, JavaTokenType.RPARENTH, JavaErrorMessages.message("expected.rparen")); list.done(JavaElementType.EXPRESSION_LIST); if (!closed) { list.setCustomEdgeTokenBinders(null, GREEDY_RIGHT_EDGE_PROCESSOR); } return list; }
@Nullable public static String isAnnotationApplicable( @NotNull GrAnnotation annotation, final PsiElement parent) { PsiElement owner = parent.getParent(); final PsiElement ownerToUse = parent instanceof PsiModifierList ? owner : parent; String[] elementTypeFields = GrAnnotationImpl.getApplicableElementTypeFields(ownerToUse); if (elementTypeFields != null && !GrAnnotationImpl.isAnnotationApplicableTo(annotation, false, elementTypeFields)) { final String annotationTargetText = JavaErrorMessages.message("annotation.target." + elementTypeFields[0]); GrCodeReferenceElement ref = annotation.getClassReference(); return JavaErrorMessages.message( "annotation.not.applicable", ref.getText(), annotationTargetText); } return null; }
@Nullable public static HighlightInfo checkValidAnnotationType(final PsiTypeElement typeElement) { PsiType type = typeElement.getType(); if (type.accept(AnnotationReturnTypeVisitor.INSTANCE).booleanValue()) { return null; } String description = JavaErrorMessages.message("annotation.invalid.annotation.member.type"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(typeElement) .descriptionAndTooltip(description) .create(); }
@Nullable private PsiBuilder.Marker parseRelational(final PsiBuilder builder) { PsiBuilder.Marker left = parseExpression(builder, ExprType.SHIFT); if (left == null) return null; IElementType tokenType; while ((tokenType = getGtTokenType(builder)) != null) { final IElementType toCreate; final ExprType toParse; if (RELATIONAL_OPS.contains(tokenType)) { toCreate = JavaElementType.BINARY_EXPRESSION; toParse = ExprType.SHIFT; } else if (tokenType == JavaTokenType.INSTANCEOF_KEYWORD) { toCreate = JavaElementType.INSTANCE_OF_EXPRESSION; toParse = ExprType.TYPE; } else { break; } final PsiBuilder.Marker expression = left.precede(); advanceGtToken(builder, tokenType); final PsiBuilder.Marker right = parseExpression(builder, toParse); if (right == null) { error( builder, toParse == ExprType.TYPE ? JavaErrorMessages.message("expected.type") : JavaErrorMessages.message("expected.expression")); expression.done(toCreate); return expression; } expression.done(toCreate); left = expression; } return left; }
@Nullable public static HighlightInfo checkNameValuePair(PsiNameValuePair pair) { PsiReference ref = pair.getReference(); if (ref == null) return null; PsiMethod method = (PsiMethod) ref.resolve(); if (method == null) { if (pair.getName() != null) { final String description = JavaErrorMessages.message("annotation.unknown.method", ref.getCanonicalText()); PsiElement element = ref.getElement(); final HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF) .range(element) .descriptionAndTooltip(description) .create(); QuickFixAction.registerQuickFixAction( highlightInfo, QuickFixFactory.getInstance().createCreateAnnotationMethodFromUsageFix(pair)); return highlightInfo; } else { String description = JavaErrorMessages.message("annotation.missing.method", ref.getCanonicalText()); PsiElement element = ref.getElement(); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(element) .descriptionAndTooltip(description) .create(); } } else { PsiType returnType = method.getReturnType(); assert returnType != null : method; PsiAnnotationMemberValue value = pair.getValue(); HighlightInfo info = checkMemberValueType(value, returnType); if (info != null) return info; return checkDuplicateAttribute(pair); } }
@Nullable public static HighlightInfo checkCyclicMemberType(PsiTypeElement typeElement, PsiClass aClass) { LOG.assertTrue(aClass.isAnnotationType()); PsiType type = typeElement.getType(); final Set<PsiClass> checked = new HashSet<PsiClass>(); if (cyclicDependencies(aClass, type, checked, aClass.getManager())) { String description = JavaErrorMessages.message("annotation.cyclic.element.type"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(typeElement) .descriptionAndTooltip(description) .create(); } return null; }
@Nullable private static HighlightInfo checkReferenceTarget( PsiAnnotation annotation, @Nullable PsiJavaCodeReferenceElement ref) { if (ref == null) return null; PsiElement refTarget = ref.resolve(); if (refTarget == null) return null; String message = null; if (!(refTarget instanceof PsiClass)) { message = JavaErrorMessages.message("annotation.not.allowed.ref"); } else { PsiElement parent = ref.getParent(); if (parent instanceof PsiJavaCodeReferenceElement) { PsiElement qualified = ((PsiJavaCodeReferenceElement) parent).resolve(); if (qualified instanceof PsiMember && ((PsiMember) qualified).hasModifierProperty(PsiModifier.STATIC)) { message = JavaErrorMessages.message("annotation.not.allowed.static"); } } } return message != null ? annotationError(annotation, message) : null; }
@NotNull private PsiBuilder.Marker parseMethodReference( final PsiBuilder builder, final PsiBuilder.Marker start) { builder.advanceLexer(); myParser.getReferenceParser().parseReferenceParameterList(builder, false, false); if (!expect(builder, JavaTokenType.IDENTIFIER) && !expect(builder, JavaTokenType.NEW_KEYWORD)) { error(builder, JavaErrorMessages.message("expected.identifier")); } start.done(JavaElementType.METHOD_REF_EXPRESSION); return start; }
@Nullable static HighlightInfo checkVariableMustBeFinal( PsiVariable variable, PsiJavaCodeReferenceElement context, @NotNull LanguageLevel languageLevel) { if (variable.hasModifierProperty(PsiModifier.FINAL)) return null; final PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, context); if (innerClass != null) { if (variable instanceof PsiParameter) { final PsiElement parent = variable.getParent(); if (parent instanceof PsiParameterList && parent.getParent() instanceof PsiLambdaExpression && notAccessedForWriting( variable, new LocalSearchScope(((PsiParameter) variable).getDeclarationScope()))) { return null; } } if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && isEffectivelyFinal(variable, innerClass, context)) { return null; } final String description = JavaErrorMessages.message("variable.must.be.final", context.getText()); final HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(context) .descriptionAndTooltip(description) .create(); QuickFixAction.registerQuickFixAction( highlightInfo, QUICK_FIX_FACTORY.createVariableAccessFromInnerClassFix(variable, innerClass)); return highlightInfo; } final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(context, PsiLambdaExpression.class); if (lambdaExpression != null && !PsiTreeUtil.isAncestor(lambdaExpression, variable, true)) { final PsiElement parent = variable.getParent(); if (parent instanceof PsiParameterList && parent.getParent() == lambdaExpression) { return null; } if (!isEffectivelyFinal(variable, lambdaExpression, context)) { return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(context) .descriptionAndTooltip("Variable used in lambda expression should be effectively final") .create(); } } return null; }
@Nullable public static HighlightInfo checkAnnotationDeclaration( final PsiElement parent, final PsiReferenceList list) { if (PsiUtil.isAnnotationMethod(parent)) { PsiAnnotationMethod method = (PsiAnnotationMethod) parent; if (list == method.getThrowsList()) { String description = JavaErrorMessages.message("annotation.members.may.not.have.throws.list"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(list) .descriptionAndTooltip(description) .create(); } } else if (parent instanceof PsiClass && ((PsiClass) parent).isAnnotationType()) { if (PsiKeyword.EXTENDS.equals(list.getFirstChild().getText())) { String description = JavaErrorMessages.message("annotation.may.not.have.extends.list"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(list) .descriptionAndTooltip(description) .create(); } } return null; }
@Nullable public static HighlightInfo checkAnnotationType(PsiAnnotation annotation) { PsiJavaCodeReferenceElement nameReferenceElement = annotation.getNameReferenceElement(); if (nameReferenceElement != null) { PsiElement resolved = nameReferenceElement.resolve(); if (!(resolved instanceof PsiClass) || !((PsiClass) resolved).isAnnotationType()) { String description = JavaErrorMessages.message("annotation.annotation.type.expected"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(nameReferenceElement) .descriptionAndTooltip(description) .create(); } } return null; }
@Nullable static HighlightInfo checkFileName(@NotNull PsiJavaModule element, @NotNull PsiFile file) { if (!MODULE_INFO_FILE.equals(file.getName())) { String message = JavaErrorMessages.message("module.file.wrong.name"); HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(range(element)) .description(message) .create(); QuickFixAction.registerQuickFixAction(info, factory().createRenameFileFix(MODULE_INFO_FILE)); return info; } return null; }
@Nullable public static HighlightInfo checkPackageAnnotationContainingFile( final PsiPackageStatement statement) { if (statement.getAnnotationList() == null) { return null; } PsiFile file = statement.getContainingFile(); if (file != null && !PsiPackage.PACKAGE_INFO_FILE.equals(file.getName())) { String description = JavaErrorMessages.message("invalid.package.annotation.containing.file"); HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR); builder.range(statement.getAnnotationList().getTextRange()); builder.descriptionAndTooltip(description); return builder.create(); } return null; }
@Nullable public static HighlightInfo checkMissingAttributes(PsiAnnotation annotation) { PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement(); if (nameRef == null) return null; PsiClass aClass = (PsiClass) nameRef.resolve(); if (aClass != null && aClass.isAnnotationType()) { Set<String> names = new HashSet<String>(); PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes(); for (PsiNameValuePair attribute : attributes) { final String name = attribute.getName(); if (name != null) { names.add(name); } else { names.add(PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME); } } PsiMethod[] annotationMethods = aClass.getMethods(); List<String> missed = new ArrayList<String>(); for (PsiMethod method : annotationMethods) { if (PsiUtil.isAnnotationMethod(method)) { PsiAnnotationMethod annotationMethod = (PsiAnnotationMethod) method; if (annotationMethod.getDefaultValue() == null) { if (!names.contains(annotationMethod.getName())) { missed.add(annotationMethod.getName()); } } } } if (!missed.isEmpty()) { StringBuffer buff = new StringBuffer("'" + missed.get(0) + "'"); for (int i = 1; i < missed.size(); i++) { buff.append(", "); buff.append("'").append(missed.get(i)).append("'"); } String description = JavaErrorMessages.message("annotation.missing.attribute", buff); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(nameRef) .descriptionAndTooltip(description) .create(); } } return null; }
@Nullable public static HighlightInfo checkConstantExpression(PsiExpression expression) { final PsiElement parent = expression.getParent(); if (PsiUtil.isAnnotationMethod(parent) || parent instanceof PsiNameValuePair || parent instanceof PsiArrayInitializerMemberValue) { if (!PsiUtil.isConstantExpression(expression)) { String description = JavaErrorMessages.message("annotation.non.constant.attribute.value"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(expression) .descriptionAndTooltip(description) .create(); } } return null; }
@Nullable static HighlightInfo checkModuleReference(@Nullable PsiJavaModuleReferenceElement refElement) { if (refElement != null) { PsiPolyVariantReference ref = refElement.getReference(); assert ref != null : refElement.getParent(); if (ref.multiResolve(false).length == 0) { String message = JavaErrorMessages.message("module.ref.unknown", refElement.getReferenceText()); return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF) .range(refElement) .description(message) .create(); } } return null; }
public static HighlightInfo checkUnreachableStatement(PsiCodeBlock codeBlock) { if (codeBlock == null) return null; // do not compute constant expressions for if() statement condition // see JLS 14.20 Unreachable Statements try { final ControlFlow controlFlow = getControlFlowNoConstantEvaluate(codeBlock); final PsiElement unreachableStatement = ControlFlowUtil.getUnreachableStatement(controlFlow); if (unreachableStatement != null) { String description = JavaErrorMessages.message("unreachable.statement"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(unreachableStatement) .descriptionAndTooltip(description) .create(); } } catch (AnalysisCanceledException e) { // incomplete code } catch (IndexNotReadyException ignored) { } return null; }
@Nullable static HighlightInfo checkFinalVariableInitializedInLoop( @NotNull PsiReferenceExpression expression, @NotNull PsiElement resolved) { if (ControlFlowUtil.isVariableAssignedInLoop(expression, resolved)) { String description = JavaErrorMessages.message( "variable.assigned.in.loop", ((PsiVariable) resolved).getName()); final HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR) .range(expression) .descriptionAndTooltip(description) .create(); QuickFixAction.registerQuickFixAction( highlightInfo, QUICK_FIX_FACTORY.createModifierListFix( (PsiVariable) resolved, PsiModifier.FINAL, false, false)); return highlightInfo; } return null; }