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)); } }
private boolean checkTagInfo(InspectionManager inspectionManager, JavadocTagInfo tagInfo, PsiDocTag tag, boolean isOnTheFly, ArrayList<ProblemDescriptor> problems) { final String tagName = tag.getName(); final StringTokenizer tokenizer = new StringTokenizer(myAdditionalJavadocTags, ", "); while (tokenizer.hasMoreTokens()) { if (Comparing.strEqual(tagName, tokenizer.nextToken())) return true; } final PsiElement nameElement = tag.getNameElement(); if (nameElement != null) { if (tagInfo == null) { problems.add( createDescriptor(nameElement, InspectionsBundle.message("inspection.javadoc.problem.wrong.tag", "<code>" + tagName + "</code>"), new AddUnknownTagToCustoms(tag.getName()), inspectionManager, isOnTheFly)); } else { problems.add(createDescriptor(nameElement, InspectionsBundle.message("inspection.javadoc.problem.disallowed.tag", "<code>" + tagName + "</code>"), new AddUnknownTagToCustoms(tag.getName()), inspectionManager, isOnTheFly)); } } return false; }
@Override @NotNull public JavadocTagInfo[] getTagInfos(PsiElement context) { List<JavadocTagInfo> result = new ArrayList<>(); for(JavadocTagInfo info : myInfos) { if(info.isValidInContext(context)) { result.add(info); } } return result.toArray(new JavadocTagInfo[result.size()]); }
@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); }
public JavadocManagerImpl(Project project) { myInfos = new ArrayList<JavadocTagInfo>(); myInfos.add(new SimpleDocTagInfo("author", PsiClass.class, PsiPackage.class, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("deprecated", PsiElement.class, false, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("serialData", PsiMethod.class, false, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("serialField", PsiField.class, false, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("since", PsiElement.class, PsiPackage.class, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("version", PsiClass.class, PsiPackage.class, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("apiNote", PsiElement.class, false, LanguageLevel.JDK_1_8)); myInfos.add(new SimpleDocTagInfo("implNote", PsiElement.class, false, LanguageLevel.JDK_1_8)); myInfos.add(new SimpleDocTagInfo("implSpec", PsiElement.class, false, LanguageLevel.JDK_1_8)); myInfos.add(new SimpleDocTagInfo("docRoot", PsiElement.class, true, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("inheritDoc", PsiElement.class, true, LanguageLevel.JDK_1_4)); myInfos.add(new SimpleDocTagInfo("literal", PsiElement.class, true, LanguageLevel.JDK_1_5)); myInfos.add(new SimpleDocTagInfo("code", PsiElement.class, true, LanguageLevel.JDK_1_5)); //Not a standard tag, but added by IDEA for inspection suppression myInfos.add(new SimpleDocTagInfo(SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME, PsiElement.class, false, LanguageLevel.JDK_1_3)); myInfos.add(new ParamDocTagInfo()); myInfos.add(new ReturnDocTagInfo()); myInfos.add(new SerialDocTagInfo()); myInfos.add(new SeeDocTagInfo("see", false)); myInfos.add(new SeeDocTagInfo("link", true)); myInfos.add(new SeeDocTagInfo("linkplain", true)); myInfos.add(new ExceptionTagInfo("exception")); myInfos.add(new ExceptionTagInfo("throws")); myInfos.add(new ValueDocTagInfo()); Collections.addAll(myInfos, Extensions.getExtensions(JavadocTagInfo.EP_NAME, project)); for (CustomJavadocTagProvider extension : Extensions.getExtensions(CustomJavadocTagProvider.EP_NAME)) { myInfos.addAll(extension.getSupportedTags()); } }
@Override @NotNull public JavadocTagInfo[] getTagInfos(PsiElement context) { List<JavadocTagInfo> result = new ArrayList<JavadocTagInfo>(); for (JavadocTagInfo info : myInfos) { if (info.isValidInContext(context)) { result.add(info); } } return result.toArray(new JavadocTagInfo[result.size()]); }
@Override @Nullable public JavadocTagInfo getTagInfo(String name) { for (JavadocTagInfo info : myInfos) { if (info.getName().equals(name)) return info; } return null; }
@Override public List<JavadocTagInfo> getSupportedTags() { return ContainerUtil.map(ANNOTATION_NAMES, new Function<String, JavadocTagInfo>() { @Override public JavadocTagInfo fun(String name) { return new MojoAnnotationInfo(name); } }); }
public JavadocManagerImpl(Project project) { myInfos = new ArrayList<JavadocTagInfo>(); myInfos.add(new SimpleDocTagInfo("author", PsiClass.class, false, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("deprecated", PsiElement.class, false, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("serialData", PsiMethod.class, false, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("serialField", PsiField.class, false, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("since", PsiElement.class, false, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("version", PsiClass.class, false, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("docRoot", PsiElement.class, true, LanguageLevel.JDK_1_3)); myInfos.add(new SimpleDocTagInfo("inheritDoc", PsiElement.class, true, LanguageLevel.JDK_1_4)); myInfos.add(new SimpleDocTagInfo("literal", PsiElement.class, true, LanguageLevel.JDK_1_5)); myInfos.add(new SimpleDocTagInfo("code", PsiElement.class, true, LanguageLevel.JDK_1_5)); //Not a standard tag, but added by IDEA for inspection suppression myInfos.add(new SimpleDocTagInfo(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME, PsiElement.class, false, LanguageLevel.JDK_1_3)); myInfos.add(new ParamDocTagInfo()); myInfos.add(new ReturnDocTagInfo()); myInfos.add(new SerialDocTagInfo()); myInfos.add(new SeeDocTagInfo("see", false)); myInfos.add(new SeeDocTagInfo("link", true)); myInfos.add(new SeeDocTagInfo("linkplain", true)); myInfos.add(new ExceptionTagInfo("exception")); myInfos.add(new ExceptionTagInfo("throws")); myInfos.add(new ValueDocTagInfo()); Collections.addAll(myInfos, Extensions.getExtensions(JavadocTagInfo.EP_NAME, project)); }
public JavadocManagerImpl(Project project) { myInfos = new ArrayList<>(); myInfos.add(new AuthorDocTagInfo()); myInfos.add(new SimpleDocTagInfo("deprecated", LanguageLevel.JDK_1_3, false, PsiElement.class)); myInfos.add(new SimpleDocTagInfo("serialData", LanguageLevel.JDK_1_3, false, PsiMethod.class)); myInfos.add(new SimpleDocTagInfo("serialField", LanguageLevel.JDK_1_3, false, PsiField.class)); myInfos.add(new SimpleDocTagInfo("since", LanguageLevel.JDK_1_3, false, PsiElement.class, PsiPackage.class)); myInfos.add(new SimpleDocTagInfo("version", LanguageLevel.JDK_1_3, false, PsiClass.class, PsiPackage.class)); myInfos.add(new SimpleDocTagInfo("apiNote", LanguageLevel.JDK_1_8, false, PsiElement.class)); myInfos.add(new SimpleDocTagInfo("implNote", LanguageLevel.JDK_1_8, false, PsiElement.class)); myInfos.add(new SimpleDocTagInfo("implSpec", LanguageLevel.JDK_1_8, false, PsiElement.class)); myInfos.add(new SimpleDocTagInfo("moduleGraph", LanguageLevel.JDK_1_9, false, PsiJavaModule.class)); myInfos.add(new SimpleDocTagInfo("docRoot", LanguageLevel.JDK_1_3, true, PsiElement.class)); myInfos.add(new SimpleDocTagInfo("inheritDoc", LanguageLevel.JDK_1_4, true, PsiElement.class)); myInfos.add(new SimpleDocTagInfo("literal", LanguageLevel.JDK_1_5, true, PsiElement.class)); myInfos.add(new SimpleDocTagInfo("code", LanguageLevel.JDK_1_5, true, PsiElement.class)); //Not a standard tag, but added by IDEA for inspection suppression myInfos.add(new SimpleDocTagInfo(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME, LanguageLevel.JDK_1_3, false, PsiElement.class)); myInfos.add(new ParamDocTagInfo()); myInfos.add(new ReturnDocTagInfo()); myInfos.add(new SerialDocTagInfo()); myInfos.add(new SeeDocTagInfo("see", false)); myInfos.add(new SeeDocTagInfo("link", true)); myInfos.add(new SeeDocTagInfo("linkplain", true)); myInfos.add(new ExceptionTagInfo("exception")); myInfos.add(new ExceptionTagInfo("throws")); myInfos.add(new ValueDocTagInfo()); Collections.addAll(myInfos, Extensions.getExtensions(JavadocTagInfo.EP_NAME, project)); }
@Override @Nullable public JavadocTagInfo getTagInfo(String name) { for(JavadocTagInfo info : myInfos) { if(info.getName().equals(name)) { return info; } } return null; }
@Deprecated public void registerTagInfo(@NotNull JavadocTagInfo info) { myInfos.add(info); }
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; }