英文:
Java checkstyle: Check whether or not return type is X if method name contains Y
问题
我正在尝试编写一个Checkstyle规则,如果方法名称通过特定的正则表达式,它会验证方法的返回类型。
例如:如果方法名称包含Foo
,我想确保返回类型不是Bar
。
通过示例:
public Fizz testFoo() {}
public Optional<Fizz> testFoo2() {}
不通过示例:
public Bar testFoo() {}
public Optional<Bar> fooTest() {}
英文:
I'm trying to write a checkstyle rule that verifies the return type of a method if the name passes a certain regex.
e.g: If the method name contains Foo
, I want to make sure that the return type isn't Bar
.
Passes:
public Fizz testFoo() {}
public Optional<Fizz> testFoo2() {}
Fails:
public Bar testFoo() {}
public Optional<Bar> fooTest() {}
答案1
得分: 1
你可以构建自己的检查并使用它。
例如,这是一个可以解决你问题的自定义检查。
XML配置:
<module name="Checker">
<module name="TreeWalker">
<module name="ReturnTypeNameCheck">
<property name="methodNameFormat" value=".*Foo"/>
<property name="returnNameFormat" value="String"/>
</module>
</module>
</module>
自定义检查代码:
public class ReturnTypeNameCheck extends AbstractCheck {
public static final String MSG_KEY = "return.type.name.check";
private String methodNameFormat = "";
private String returnNameFormat = "";
@Override
public int[] getDefaultTokens() {
return getRequiredTokens();
}
@Override
public int[] getAcceptableTokens() {
return getRequiredTokens();
}
@Override
public int[] getRequiredTokens() {
return new int[] {TokenTypes.METHOD_DEF};
}
public final void setMethodNameFormat(String format) {
methodNameFormat = format;
}
public final void setReturnNameFormat(String format) {
returnNameFormat = format;
}
@Override
public void visitToken(DetailAST ast) {
DetailAST methodName = ast.findFirstToken(TokenTypes.IDENT);
DetailAST methodType = ast.findFirstToken(TokenTypes.TYPE);
String methodNameStr = methodName.getText();
String returnTypeName = methodType.getFirstChild().getText();
if(methodNameStr.matches(methodNameFormat)) {
if(methodType.branchContains(TokenTypes.TYPE_ARGUMENTS)){
DetailAST typeArgs = methodType.getLastChild();
while (typeArgs != null && typeArgs.getChildCount(TokenTypes.TYPE_ARGUMENT) != 0) {
typeArgs = typeArgs.findFirstToken(TokenTypes.TYPE_ARGUMENT);
String genericTypeName = typeArgs.findFirstToken(TokenTypes.IDENT).getText();
if(genericTypeName.contains(returnNameFormat)){
log(ast, MSG_KEY);
return;
}
typeArgs = typeArgs.getLastChild();
}
} else{
if(returnTypeName.contains(returnNameFormat)){
log(ast, MSG_KEY);
}
}
}
}
}
此检查的使用示例:
class Test {
public void testFoo() {} //OK
public String testFoo() {} //违规
public ClassOne<String> testFoo() {} //违规
public ClassOne<ClassTwo<String>> testFoo() {} //违规
public ClassOne<ClassTwo<ClassThree<String>>> testFoo() {} //违规
}
此链接将帮助您构建自己的自定义检查:https://checkstyle.sourceforge.io/writingchecks.html
英文:
You can build your own check and use it
for example this is custom check that can solve your problem
The XML Config
<module name="Checker">
<module name="TreeWalker">
<module name="ReturnTypeNameCheck">
<property name="methodNameFormat" value=".*Foo"/>
<property name="returnNameFormat" value="String"/>
</module>
</module>
</module>
The Custom check code
public class ReturnTypeNameCheck extends AbstractCheck {
public static final String MSG_KEY = "return.type.name.check";
private String methodNameFormat = "";
private String returnNameFormat = "";
@Override
public int[] getDefaultTokens() {
return getRequiredTokens();
}
@Override
public int[] getAcceptableTokens() {
return getRequiredTokens();
}
@Override
public int[] getRequiredTokens() {
return new int[] {TokenTypes.METHOD_DEF};
}
public final void setMethodNameFormat(String format) {
methodNameFormat = format;
}
public final void setReturnNameFormat(String format) {
returnNameFormat = format;
}
@Override
public void visitToken(DetailAST ast) {
DetailAST methodName = ast.findFirstToken(TokenTypes.IDENT);
DetailAST methodType = ast.findFirstToken(TokenTypes.TYPE);
String methodNameStr = methodName.getText();
String returnTypeName = methodType.getFirstChild().getText();
if(methodNameStr.matches(methodNameFormat)) {
if(methodType.branchContains(TokenTypes.TYPE_ARGUMENTS)){
DetailAST typeArgs = methodType.getLastChild();
while (typeArgs != null && typeArgs.getChildCount(TokenTypes.TYPE_ARGUMENT) != 0) {
typeArgs = typeArgs.findFirstToken(TokenTypes.TYPE_ARGUMENT);
String genericTypeName = typeArgs.findFirstToken(TokenTypes.IDENT).getText();
if(genericTypeName.contains(returnNameFormat)){
log(ast, MSG_KEY);
return;
}
typeArgs = typeArgs.getLastChild();
}
} else{
if(returnTypeName.contains(returnNameFormat)){
log(ast, MSG_KEY);
}
}
}
}
Examples of vol for this Check
class Test {
public void testFoo() {} //OK
public String testFoo() {} //violation
public ClassOne<String> testFoo() {} //violation
public ClassOne<ClassTwo<String>> testFoo() {} //violation
public ClassOne<ClassTwo<ClassThree<String>>> testFoo() {} //violation
}
and this link will help you to build your own custom Check
https://checkstyle.sourceforge.io/writingchecks.html
答案2
得分: 0
我不太了解这些问题,但也许这段代码可能是这样的:
Method[] methods = this.getClass().getMethods();
for (Method method : methods) {
if(method.getName().contains("Foo")){
if(!method.getReturnType().getClass().getName().contains("Foo")){
throw new Exception("返回类型错误!");
}
}
}
英文:
I dont understand mụch about the questions but may be this code co
Method[] methods = this.getClass().getMethods();
for (Method method : methods) {
if(method.getName().contains("Foo")){
if(!method.getReturnType().getClass().getName().contains("Foo")){
throw new Exception("Wrong return type!");
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论