我在我的项目中配置了一个Checkstyle验证规则,禁止定义具有超过3个输入参数的类方法。该规则适用于我的类,但有时我必须扩展第三方类,这些类不遵守这一特定规则。
是否有可能指示Checkstyle,某个方法应该被无声地忽略?
顺便说一句,我最终得到了我自己的Checkstyle包装器:qulice.com(参见Java代码质量的严格控制)
我在我的项目中配置了一个Checkstyle验证规则,禁止定义具有超过3个输入参数的类方法。该规则适用于我的类,但有时我必须扩展第三方类,这些类不遵守这一特定规则。
是否有可能指示Checkstyle,某个方法应该被无声地忽略?
顺便说一句,我最终得到了我自己的Checkstyle包装器:qulice.com(参见Java代码质量的严格控制)
当前回答
我在回答上面的问题时遇到了困难,可能是因为我将checkStyle警告设置为错误。什么工作是SuppressionFilter: http://checkstyle.sourceforge.net/config_filters.html#SuppressionFilter
这样做的缺点是行范围存储在单独的suppression .xml文件中,因此不熟悉的开发人员可能不会立即建立连接。
其他回答
如果你更喜欢使用注释来选择性地屏蔽规则,现在可以使用@SuppressWarnings注释,从Checkstyle 5.7开始(Checkstyle Maven Plugin 2.12+支持)。
首先,在checkstyle.xml中,将SuppressWarningsHolder模块添加到TreeWalker中:
<module name="TreeWalker">
<!-- Make the @SuppressWarnings annotations available to Checkstyle -->
<module name="SuppressWarningsHolder" />
</module>
接下来,在那里启用SuppressWarningsFilter(作为TreeWalker的兄弟):
<!-- Filter out Checkstyle warnings that have been suppressed with the @SuppressWarnings annotation -->
<module name="SuppressWarningsFilter" />
<module name="TreeWalker">
...
现在你可以注释你想要排除在Checkstyle规则之外的方法:
@SuppressWarnings("checkstyle:methodlength")
@Override
public boolean equals(Object obj) {
// very long auto-generated equals() method
}
@SuppressWarnings参数中的checkstyle:前缀是可选的,但我喜欢用它来提醒这个警告来自哪里。规则名称必须为小写。
最后,如果你正在使用Eclipse,它会抱怨参数对它是未知的:
不支持@SuppressWarnings(“checkstyle: methodlength”)
如果你愿意,你可以在首选项中禁用这个Eclipse警告:
Preferences:
Java
--> Compiler
--> Errors/Warnings
--> Annotations
--> Unhandled token in '@SuppressWarnings': set to 'Ignore'
同样工作良好的还有SuppressWithNearbyCommentFilter,它使用单个注释来抑制审计事件。
例如
// CHECKSTYLE IGNORE check FOR NEXT 1 LINES
public void onClick(View view) { ... }
配置一个过滤器,使CHECKSTYLE IGNORE check FOR NEXT var LINES避免触发对当前行和下一个var行(总共var+1行)的给定检查的任何审计:
<module name="SuppressWithNearbyCommentFilter">
<property name="commentFormat" value="CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINES"/>
<property name="checkFormat" value="$1"/>
<property name="influenceFormat" value="$2"/>
</module>
http://checkstyle.sourceforge.net/config.html
试一试 https://checkstyle.sourceforge.io/config_filters.html#SuppressionXpathFilter
你可以这样配置:
<module name="SuppressionXpathFilter">
<property name="file" value="suppressions-xpath.xml"/>
<property name="optional" value="false"/>
</module>
使用CLI和-g选项生成Xpath抑制,并使用-o开关指定输出。
https://checkstyle.sourceforge.io/cmdline.html#Command_line_usage
下面是一个蚂蚁代码片段,它将帮助您设置Checkstyle抑制自动生成;你可以使用Antrun插件将它集成到Maven中。
<target name="checkstyleg">
<move file="suppressions-xpath.xml"
tofile="suppressions-xpath.xml.bak"
preservelastmodified="true"
force="true"
failonerror="false"
verbose="true"/>
<fileset dir="${basedir}"
id="javasrcs">
<include name="**/*.java" />
</fileset>
<pathconvert property="sources"
refid="javasrcs"
pathsep=" " />
<loadfile property="cs.cp"
srcFile="../${cs.classpath.file}" />
<java classname="${cs.main.class}"
logError="true">
<arg line="-c ../${cs.config} -p ${cs.properties} -o ${ant.project.name}-xpath.xml -g ${sources}" />
<classpath>
<pathelement path="${cs.cp}" />
<pathelement path="${java.class.path}" />
</classpath>
</java>
<condition property="file.is.empty" else="false">
<length file="${ant.project.name}-xpath.xml" when="equal" length="0" />
</condition>
<if>
<equals arg1="${file.is.empty}" arg2="false"/>
<then>
<move file="${ant.project.name}-xpath.xml"
tofile="suppressions-xpath.xml"
preservelastmodified="true"
force="true"
failonerror="true"
verbose="true"/>
</then>
</if>
</target>
在Checkstyle规则配置中,suppress - Xpath .xml被指定为Xpath抑制源。 在上面的代码片段中,我从文件cs中加载Checkstyle类路径。Cp变成了一个属性。您可以选择直接指定类路径。
或者你可以在Maven(或Ant)中使用groovy来做同样的事情:
import java.nio.file.Files
import java.nio.file.StandardCopyOption
import java.nio.file.Paths
def backupSuppressions() {
def supprFileName =
project.properties["checkstyle.suppressionsFile"]
def suppr = Paths.get(supprFileName)
def target = null
if (Files.exists(suppr)) {
def supprBak = Paths.get(supprFileName + ".bak")
target = Files.move(suppr, supprBak,
StandardCopyOption.REPLACE_EXISTING)
println "Backed up " + supprFileName
}
return target
}
def renameSuppressions() {
def supprFileName =
project.properties["checkstyle.suppressionsFile"]
def suppr = Paths.get(project.name + "-xpath.xml")
def target = null
if (Files.exists(suppr)) {
def supprNew = Paths.get(supprFileName)
target = Files.move(suppr, supprNew)
println "Renamed " + suppr + " to " + supprFileName
}
return target
}
def getClassPath(classLoader, sb) {
classLoader.getURLs().each {url->
sb.append("${url.getFile().toString()}:")
}
if (classLoader.parent) {
getClassPath(classLoader.parent, sb)
}
return sb.toString()
}
backupSuppressions()
def cp = getClassPath(this.class.classLoader,
new StringBuilder())
def csMainClass =
project.properties["cs.main.class"]
def csRules =
project.properties["checkstyle.rules"]
def csProps =
project.properties["checkstyle.properties"]
String[] args = ["java", "-cp", cp,
csMainClass,
"-c", csRules,
"-p", csProps,
"-o", project.name + "-xpath.xml",
"-g", "src"]
ProcessBuilder pb = new ProcessBuilder(args)
pb = pb.inheritIO()
Process proc = pb.start()
proc.waitFor()
renameSuppressions()
使用Xpath抑制的唯一缺点——除了它不支持的检查——是如果你有如下代码:
package cstests;
public interface TestMagicNumber {
static byte[] getAsciiRotator() {
byte[] rotation = new byte[95 * 2];
for (byte i = ' '; i <= '~'; i++) {
rotation[i - ' '] = i;
rotation[i + 95 - ' '] = i;
}
return rotation;
}
}
在这种情况下生成的Xpath抑制没有被Checkstyle摄取,检查器在生成的抑制上出现异常而失败:
<suppress-xpath
files="TestMagicNumber.java"
checks="MagicNumberCheck"
query="/INTERFACE_DEF[./IDENT[@text='TestMagicNumber']]/OBJBLOCK/METHOD_DEF[./IDENT[@text='getAsciiRotator']]/SLIST/LITERAL_FOR/SLIST/EXPR/ASSIGN[./IDENT[@text='i']]/INDEX_OP[./IDENT[@text='rotation']]/EXPR/MINUS[./CHAR_LITERAL[@text='' '']]/PLUS[./IDENT[@text='i']]/NUM_INT[@text='95']"/>
当您已经修复了所有其他违规并希望抑制其余违规时,建议生成Xpath抑制。它不允许您在代码中选择要抑制的特定实例。但是,您可以从生成的文件中选择抑制来实现这一点。
SuppressionXpathSingleFilter更适合于识别和抑制特定的规则、文件或错误消息。您可以配置多个过滤器,通过id属性标识每个过滤器。
https://checkstyle.sourceforge.io/config_filters.html#SuppressionXpathSingleFilter
在http://checkstyle.sourceforge.net/config_filters.html#SuppressionCommentFilter上查看supressionCommentFilter的使用。您需要将模块添加到checkstyle.xml中
<module name="SuppressionCommentFilter"/>
它是可配置的。因此,您可以在代码中添加注释来关闭检查样式(在不同级别上),然后通过在代码中使用注释来再次打开检查样式。如。
//CHECKSTYLE:OFF
public void someMethod(String arg1, String arg2, String arg3, String arg4) {
//CHECKSTYLE:ON
或者更好的是,使用下面的版本:
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)"/>
<property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>
<property name="checkFormat" value="$1"/>
</module>
它允许你关闭特定代码行的特定检查:
//CHECKSTYLE.OFF: IllegalCatch - Much more readable than catching 7 exceptions
catch (Exception e)
//CHECKSTYLE.ON: IllegalCatch
*注意:你还需要添加FileContentsHolder:
<module name="FileContentsHolder"/>
另请参阅
<module name="SuppressionFilter">
<property name="file" value="docs/suppressions.xml"/>
</module>
在同一页面的SuppressionFilter部分下,它允许您关闭模式匹配资源的单独检查。
如果你在checkstyle。xml中有:
<module name="ParameterNumber">
<property name="id" value="maxParameterNumber"/>
<property name="max" value="3"/>
<property name="tokens" value="METHOD_DEF"/>
</module>
你可以在你的抑制xml文件中关闭它:
<suppress id="maxParameterNumber" files="YourCode.java"/>
Checkstyle 5.7中现在可用的另一种方法是通过@SuppressWarnings java注释来抑制违规。要做到这一点,你需要在配置文件中添加两个新模块(SuppressWarningsFilter和SuppressWarningsHolder):
<module name="Checker">
...
<module name="SuppressWarningsFilter" />
<module name="TreeWalker">
...
<module name="SuppressWarningsHolder" />
</module>
</module>
然后,在你的代码中,你可以做以下事情:
@SuppressWarnings("checkstyle:methodlength")
public void someLongMethod() throws Exception {
或者,对于多重抑制:
@SuppressWarnings({"checkstyle:executablestatementcount", "checkstyle:methodlength"})
public void someLongMethod() throws Exception {
注意:“checkstyle:”前缀是可选的(但推荐使用)。根据文档,参数名必须全小写,但实践表明,任何情况下工作。
<module name="Checker">
<module name="SuppressionCommentFilter"/>
<module name="TreeWalker">
<module name="FileContentsHolder"/>
</module>
</module>
使用实例配置一个过滤器,在包含BEGIN GENERATED CODE的注释和包含END GENERATED CODE的注释之间屏蔽审计事件:
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="BEGIN GENERATED CODE"/>
<property name="onCommentFormat" value="END GENERATED CODE"/>
</module>
//BEGIN GENERATED CODE
@Override
public boolean equals(Object obj) { ... } // No violation events will be reported
@Override
public int hashCode() { ... } // No violation events will be reported
//END GENERATED CODE
查看更多