private void checkForPeriodInDoc(PsiDocComment docComment, ArrayList<ProblemDescriptor> problems, InspectionManager manager, boolean onTheFly) { if (IGNORE_JAVADOC_PERIOD) return; PsiDocTag[] tags = docComment.getTags(); int dotIndex = docComment.getText().indexOf('.'); int tagOffset = 0; if (dotIndex >= 0) { //need to find first valid tag final PsiDocCommentOwner owner = PsiTreeUtil.getParentOfType(docComment, PsiDocCommentOwner.class); for (PsiDocTag tag : tags) { final String tagName = tag.getName(); final JavadocTagInfo tagInfo = JavadocManager.SERVICE.getInstance(tag.getProject()).getTagInfo(tagName); if (tagInfo != null && tagInfo.isValidInContext(owner) && !tagInfo.isInline()) { tagOffset = tag.getTextOffset(); break; } } } if (dotIndex == -1 || tagOffset > 0 && dotIndex + docComment.getTextOffset() > tagOffset) { problems.add(manager.createProblemDescriptor(docComment.getFirstChild(), InspectionsBundle.message("inspection.javadoc.problem.descriptor1"), null, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, onTheFly, false)); } }
@Override public PsiReference getReference() { PsiDocTag docTag = PsiTreeUtil.getParentOfType(this, PsiDocTag.class); if (docTag == null) { return null; } final String name = docTag.getName(); final JavadocManager manager = JavadocManager.SERVICE.getInstance(getProject()); final JavadocTagInfo info = manager.getTagInfo(name); if (info == null) return null; return info.getReference(this); }
@Override @Nullable public ProblemDescriptor[] checkField(@NotNull PsiField psiField, @NotNull InspectionManager manager, boolean isOnTheFly) { if (IGNORE_DEPRECATED && (psiField.isDeprecated() || psiField.getContainingClass().isDeprecated())) { return null; } PsiDocComment docComment = psiField.getDocComment(); if (docComment == null) { return isJavaDocRequired(psiField) ? new ProblemDescriptor[]{createDescriptor(psiField.getNameIdentifier(), REQUIRED_JAVADOC_IS_ABSENT, manager, isOnTheFly)} : null; } final ArrayList<ProblemDescriptor> problems = new ArrayList<ProblemDescriptor>(2); ArrayList<ProblemDescriptor> tagProblems = getTagValuesProblems(psiField, docComment.getTags(), manager, isOnTheFly); if (tagProblems != null) { problems.addAll(tagProblems); } checkInlineTags(manager, problems, docComment.getDescriptionElements(), JavadocManager.SERVICE.getInstance(docComment.getProject()), isOnTheFly); checkForPeriodInDoc(docComment, problems, manager, isOnTheFly); checkDuplicateTags(docComment.getTags(), problems, manager, isOnTheFly); checkForBadCharacters(docComment, problems, manager, isOnTheFly); return problems.isEmpty() ? null : problems.toArray(new ProblemDescriptor[problems.size()]); }
private void checkInlineTags(final InspectionManager inspectionManager, final ArrayList<ProblemDescriptor> problems, final PsiElement[] dataElements, final JavadocManager manager, boolean isOnTheFly) { for (PsiElement dataElement : dataElements) { if (dataElement instanceof PsiInlineDocTag) { final PsiInlineDocTag inlineDocTag = (PsiInlineDocTag)dataElement; final PsiElement nameElement = inlineDocTag.getNameElement(); if (manager.getTagInfo(inlineDocTag.getName()) == null) { checkTagInfo(inspectionManager, null, inlineDocTag, isOnTheFly, problems); } if (!IGNORE_POINT_TO_ITSELF) { final PsiDocTagValue value = inlineDocTag.getValueElement(); if (value != null) { final PsiReference reference = value.getReference(); if (reference != null) { final PsiElement ref = reference.resolve(); if (ref != null){ if (PsiTreeUtil.getParentOfType(inlineDocTag, PsiDocCommentOwner.class) == PsiTreeUtil.getParentOfType(ref, PsiDocCommentOwner.class, false)) { if (nameElement != null) { problems.add(createDescriptor(nameElement, InspectionsBundle.message("inspection.javadoc.problem.pointing.to.itself"), inspectionManager, isOnTheFly)); } } } } } } } } }
public static void visitRefInDocTag(final PsiDocTag tag, final JavadocManager manager, final PsiElement context, final ArrayList<ProblemDescriptor> problems, final InspectionManager inspectionManager, final boolean onTheFly) { final String tagName = tag.getName(); final PsiDocTagValue value = tag.getValueElement(); if(value == null) { return; } final JavadocTagInfo info = manager.getTagInfo(tagName); if(info != null && !info.isValidInContext(context)) { return; } final String message = info == null || !info.isInline() ? null : info.checkTagValue(value); if(message != null) { problems.add(createDescriptor(value, message, inspectionManager, onTheFly)); } final PsiReference reference = value.getReference(); if(reference == null) { return; } final PsiElement element = reference.resolve(); if(element != null) { return; } final int textOffset = value.getTextOffset(); if(textOffset == value.getTextRange().getEndOffset()) { return; } final PsiDocTagValue valueElement = tag.getValueElement(); if(valueElement == null) { return; } final CharSequence paramName = value.getContainingFile().getViewProvider().getContents().subSequence(textOffset, value.getTextRange().getEndOffset()); final String params = "<code>" + paramName + "</code>"; final List<LocalQuickFix> fixes = new ArrayList<LocalQuickFix>(); if(onTheFly && "param".equals(tagName)) { final PsiDocCommentOwner commentOwner = PsiTreeUtil.getParentOfType(tag, PsiDocCommentOwner.class); if(commentOwner instanceof PsiMethod) { final PsiMethod method = (PsiMethod) commentOwner; final PsiParameter[] parameters = method.getParameterList().getParameters(); final PsiDocTag[] tags = tag.getContainingComment().getTags(); final Set<String> unboundParams = new HashSet<String>(); for(PsiParameter parameter : parameters) { if(!JavaDocLocalInspection.isFound(tags, parameter)) { unboundParams.add(parameter.getName()); } } if(!unboundParams.isEmpty()) { fixes.add(new RenameReferenceQuickFix(unboundParams)); } } } fixes.add(new RemoveTagFix(tagName, paramName)); problems.add(inspectionManager.createProblemDescriptor(valueElement, reference.getRangeInElement(), cannotResolveSymbolMessage(params), ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, onTheFly, fixes.toArray(new LocalQuickFix[fixes.size()]))); }
@Nullable private ArrayList<ProblemDescriptor> getTagValuesProblems(PsiDocCommentOwner context, PsiDocTag[] tags, InspectionManager inspectionManager, boolean isOnTheFly) { final ArrayList<ProblemDescriptor> problems = new ArrayList<ProblemDescriptor>(2); nextTag: for (PsiDocTag tag : tags) { final JavadocManager manager = JavadocManager.SERVICE.getInstance(tag.getProject()); String tagName = tag.getName(); JavadocTagInfo tagInfo = manager.getTagInfo(tagName); if (tagInfo == null || !tagInfo.isValidInContext(context)) { if (checkTagInfo(inspectionManager, tagInfo, tag, isOnTheFly, problems)) continue nextTag; } PsiDocTagValue value = tag.getValueElement(); final JavadocTagInfo info = manager.getTagInfo(tagName); if (info != null && !info.isValidInContext(context)) continue; String message = info == null ? null : info.checkTagValue(value); final PsiReference reference = value != null ? value.getReference() : null; if (message == null && reference != null) { PsiElement element = reference.resolve(); if (element == null) { final int textOffset = value.getTextOffset(); if (textOffset == value.getTextRange().getEndOffset()) { problems.add(inspectionManager.createProblemDescriptor(tag, InspectionsBundle.message("inspection.javadoc.problem.name.expected"), null, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly, true)); } } } if (message != null) { final PsiDocTagValue valueElement = tag.getValueElement(); if (valueElement == null){ problems.add(inspectionManager.createProblemDescriptor(tag, InspectionsBundle.message("inspection.javadoc.method.problem.missing.tag.description", "<code>" + tag.getName() + "</code>"), null, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly, true)); } else { problems.add(createDescriptor(valueElement, message, inspectionManager, isOnTheFly)); } } checkInlineTags(inspectionManager, problems, tag.getDataElements(), manager, isOnTheFly); } return problems.isEmpty() ? null : problems; }