/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.xwiki.tool.checkstyle; import org.apache.commons.lang3.StringUtils; import com.puppycrawl.tools.checkstyle.api.AbstractCheck; import com.puppycrawl.tools.checkstyle.api.DetailAST; import com.puppycrawl.tools.checkstyle.api.FileContents; import com.puppycrawl.tools.checkstyle.api.FullIdent; import com.puppycrawl.tools.checkstyle.api.TextBlock; import com.puppycrawl.tools.checkstyle.api.TokenTypes; /** * Verify that the format of the {@code @since} javadoc tag is correct, i.e. that it obeys * <a href="http://dev.xwiki.org/xwiki/bin/view/Community/JavaCodeStyle#HUseone40sinceperversion">this rule</a>. * * @version $Id: b0c5cd9ed858792e4826e8958ea2f3ebb0df787f $ * @since 8.3 */ public class SinceFormatCheck extends AbstractCheck { private String packageName; private String classOrInterfaceName; @Override public int[] getDefaultTokens() { return new int[]{ TokenTypes.PACKAGE_DEF, TokenTypes.INTERFACE_DEF, TokenTypes.CLASS_DEF, TokenTypes.METHOD_DEF, }; } @Override public void visitToken(DetailAST ast) { switch (ast.getType()) { case TokenTypes.PACKAGE_DEF: // Save the package FullIdent ident = FullIdent.createFullIdent(ast.getLastChild().getPreviousSibling()); this.packageName = ident.getText(); return; case TokenTypes.CLASS_DEF: case TokenTypes.INTERFACE_DEF: this.classOrInterfaceName = ast.findFirstToken(TokenTypes.IDENT).getText(); break; } String elementName = ast.findFirstToken(TokenTypes.IDENT).getText(); FileContents contents = getFileContents(); TextBlock javadoc = contents.getJavadocBefore(ast.getLineNo()); if (javadoc != null) { for (String javadocLine : javadoc.getText()) { int pos = javadocLine.indexOf("@since"); if (pos > -1) { String text = javadocLine.substring(pos + "@since".length() + 1); if (StringUtils.containsAny(text, ',', '/', '\\', ';', ':', '+')) { log(ast.getLineNo(), ast.getColumnNo(), String.format("There must be only a single version per @since tag for [%s]. Got [%s]", computeElementName(elementName), text)); return; } } } } } private String computeElementName(String annotatedElementName) { return String.format("%s.%s%s", this.packageName, this.classOrInterfaceName, annotatedElementName.equals(this.classOrInterfaceName) ? "" : "." + annotatedElementName + "()"); } }