/**
* Copyright (c) 2009 - 2016 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package org.candlepin.checks;
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
/**
* Checkstyle custom check that looks for public methods in REST resource
* classes which do not have swagger annotation.
*/
public class ResourceSwaggerCheck extends AbstractCheck {
private final String resourceClassAnnotationName = "Path";
private final String resourceMethodAnnotationName = "ApiOperation";
private final String ignoreAnnotationName = "SuppressSwaggerCheck";
private final String restPutAnnotationName = "PUT";
private final String restGetAnnotationName = "GET";
private int insideClass = 0;
private boolean insideIgnoredClass = false;
private boolean insideResourceClass = false;
private boolean insideMethod = false;
private boolean insideResourceMethod = false;
private boolean foundSwaggerMethodAnnotation = false;
@Override
public int[] getDefaultTokens() {
return new int[] { TokenTypes.CLASS_DEF, TokenTypes.METHOD_DEF,
TokenTypes.IDENT };
}
@Override
public void visitToken(DetailAST ast) {
int type = ast.getType();
if (type == TokenTypes.CLASS_DEF) {
insideClass += 1;
}
else if (type == TokenTypes.METHOD_DEF && insideResourceClass &&
ast.branchContains(TokenTypes.LITERAL_PUBLIC)) {
insideMethod = true;
}
else if (type == TokenTypes.IDENT) {
if (insideMethod &&
ast.getText().equals(resourceMethodAnnotationName)) {
foundSwaggerMethodAnnotation = true;
}
else if (insideClass > 0) {
if (ast.getText().equals(resourceClassAnnotationName)) {
insideResourceClass = true;
}
else if (ast.getText().equals(ignoreAnnotationName)) {
insideIgnoredClass = true;
}
else if (insideResourceClass &&
(ast.getText().equals(restGetAnnotationName) ||
ast.getText().equals(restPutAnnotationName))) {
insideResourceMethod = true;
}
}
}
}
@Override
public void leaveToken(DetailAST ast) {
int type = ast.getType();
if (type == TokenTypes.CLASS_DEF) {
insideClass -= 1;
insideResourceClass = false;
// TODO Does not handle nested ignored classes.
insideIgnoredClass = false;
}
else if (type == TokenTypes.METHOD_DEF && insideResourceMethod) {
if (!foundSwaggerMethodAnnotation && !insideIgnoredClass &&
insideResourceMethod) {
log(ast, "Method is missing swagger annotation.");
}
insideMethod = false;
insideResourceMethod = false;
foundSwaggerMethodAnnotation = false;
}
}
}