/** * Checks a set of tags for matching throws. * * @param tags the tags to check * @param throwsList the throws to check * @param reportExpectedTags whether we should report if do not find expected tag */ private void checkThrowsTags( List<JavadocTag> tags, List<ExceptionInfo> throwsList, boolean reportExpectedTags) { // Loop over the tags, checking to see they exist in the throws. // The foundThrows used for performance only final Set<String> foundThrows = Sets.newHashSet(); final ListIterator<JavadocTag> tagIt = tags.listIterator(); while (tagIt.hasNext()) { final JavadocTag tag = tagIt.next(); if (!tag.isThrowsTag()) { continue; } tagIt.remove(); // Loop looking for matching throw final String documentedEx = tag.getFirstArg(); final Token token = new Token(tag.getFirstArg(), tag.getLineNo(), tag.getColumnNo()); final AbstractClassInfo documentedCI = createClassInfo(token, getCurrentClassName()); final boolean found = foundThrows.contains(documentedEx) || isInThrows(throwsList, documentedCI, foundThrows); // Handle extra JavadocTag. if (!found) { boolean reqd = true; if (allowUndeclaredRTE) { reqd = !isUnchecked(documentedCI.getClazz()); } if (reqd && validateThrows) { log( tag.getLineNo(), tag.getColumnNo(), MSG_UNUSED_TAG, JavadocTagInfo.THROWS.getText(), tag.getFirstArg()); } } } // Now dump out all throws without tags :- unless // the user has chosen to suppress these problems if (!allowMissingThrowsTags && reportExpectedTags) { for (ExceptionInfo ei : throwsList) { if (!ei.isFound()) { final Token fi = ei.getName(); log( fi.getLineNo(), fi.getColumnNo(), MSG_EXCPECTED_TAG, JavadocTagInfo.THROWS.getText(), fi.getText()); } } } }
/** * Checks a set of tags for matching parameters. * * @param tags the tags to check * @param parent the node which takes the parameters * @param reportExpectedTags whether we should report if do not find expected tag */ private void checkParamTags( final List<JavadocTag> tags, final DetailAST parent, boolean reportExpectedTags) { final List<DetailAST> params = getParameters(parent); final List<DetailAST> typeParams = CheckUtils.getTypeParameters(parent); // Loop over the tags, checking to see they exist in the params. final ListIterator<JavadocTag> tagIt = tags.listIterator(); while (tagIt.hasNext()) { final JavadocTag tag = tagIt.next(); if (!tag.isParamTag()) { continue; } tagIt.remove(); final String arg1 = tag.getFirstArg(); boolean found = removeMatchingParam(params, arg1); if (CommonUtils.startsWithChar(arg1, '<') && CommonUtils.endsWithChar(arg1, '>')) { // Loop looking for matching type param final Iterator<DetailAST> typeParamsIt = typeParams.iterator(); while (typeParamsIt.hasNext()) { final DetailAST typeParam = typeParamsIt.next(); if (typeParam .findFirstToken(TokenTypes.IDENT) .getText() .equals(arg1.substring(1, arg1.length() - 1))) { found = true; typeParamsIt.remove(); break; } } } // Handle extra JavadocTag if (!found) { log(tag.getLineNo(), tag.getColumnNo(), MSG_UNUSED_TAG, "@param", arg1); } } // Now dump out all type parameters/parameters without tags :- unless // the user has chosen to suppress these problems if (!allowMissingParamTags && reportExpectedTags) { for (DetailAST param : params) { log(param, MSG_EXCPECTED_TAG, JavadocTagInfo.PARAM.getText(), param.getText()); } for (DetailAST typeParam : typeParams) { log( typeParam, MSG_EXCPECTED_TAG, JavadocTagInfo.PARAM.getText(), "<" + typeParam.findFirstToken(TokenTypes.IDENT).getText() + ">"); } } }
@Test public void testTagPositions() { final String[] text = { "/** @see elsewhere", " also {@link Name value} */", }; final Comment comment = new Comment(text, 1, 2, text[1].length()); final List<JavadocTag> tags = JavadocUtils.getJavadocTags(comment, JavadocUtils.JavadocTagType.ALL).getValidTags(); assertEquals(2, tags.size()); for (final JavadocTag tag : tags) { if (JavadocTagInfo.SEE.getName().equals(tag.getTagName())) { assertEquals(1, tag.getLineNo()); assertEquals(5, tag.getColumnNo()); } else if (JavadocTagInfo.LINK.getName().equals(tag.getTagName())) { assertEquals(2, tag.getLineNo()); assertEquals(10, tag.getColumnNo()); } else { fail("Unexpected tag: " + tag); } } }
/** * Checks for only one return tag. All return tags will be removed from the supplied list. * * @param tags the tags to check * @param lineNo the line number of the expected tag * @param reportExpectedTags whether we should report if do not find expected tag */ private void checkReturnTag(List<JavadocTag> tags, int lineNo, boolean reportExpectedTags) { // Loop over tags finding return tags. After the first one, report an // error. boolean found = false; final ListIterator<JavadocTag> it = tags.listIterator(); while (it.hasNext()) { final JavadocTag jt = it.next(); if (jt.isReturnTag()) { if (found) { log(jt.getLineNo(), jt.getColumnNo(), MSG_DUPLICATE_TAG, JavadocTagInfo.RETURN.getText()); } found = true; it.remove(); } } // Handle there being no @return tags :- unless // the user has chosen to suppress these problems if (!found && !allowMissingReturnTag && reportExpectedTags) { log(lineNo, MSG_RETURN_EXPECTED); } }