205

我在我的项目中配置了一个Checkstyle验证规则,该规则禁止定义具有 3 个以上输入参数的类方法。该规则适用于我的课程,但有时我必须扩展不遵守此特定规则的第三方课程。

是否有可能指示 Checkstyle 应该默默地忽略某个方法?

顺便说一句,我最终得到了我自己的 Checkstyle 包装器:qulice.com(请参阅严格控制 Java 代码质量

4

9 回答 9

316

在http://checkstyle.sourceforge.net/config_filters.html#SuppressionCommentFilter查看 supressionCommentFilter 的使用。您需要将该模块添加到您的 checkstyle.xml

<module name="SuppressionCommentFilter"/>

它是可配置的。因此,您可以在代码中添加注释以关闭 checkstyle(在各个级别),然后通过在代码中使用注释再次打开。例如

//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 现在提供的另一种方法是通过@SuppressWarningsjava 注释抑制违规。为此,您需要在配置文件中添加两个新模块 (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:”前缀是可选的(但推荐)。根据文档,参数名称必须全部小写,但实践表明任何大小写都有效。

于 2010-10-26T11:52:40.553 回答
78

如果您更喜欢使用注解来选择性地使规则静音,现在可以使用@SuppressWarnings注解,从 Checkstyle 5.7 开始(并且受 Checkstyle Maven 插件 2.12+ 支持)。

首先,在您的 中checkstyle.xml,将SuppressWarningsHolder模块添加到TreeWalker

<module name="TreeWalker">
    <!-- Make the @SuppressWarnings annotations available to Checkstyle -->
    <module name="SuppressWarningsHolder" />
</module>

接下来,启用SuppressWarningsFilterthere (作为 的兄弟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
}

参数中的checkstyle:前缀@SuppressWarnings是可选的,但我喜欢用它来提醒这个警告的来源。规则名称必须为小写。

最后,如果您使用的是 Eclipse,它会抱怨它不知道该参数:

不支持 @SuppressWarnings("checkstyle:methodlength")

如果您愿意,可以在首选项中禁用此 Eclipse 警告:

Preferences:
  Java
  --> Compiler
  --> Errors/Warnings
  --> Annotations
  --> Unhandled token in '@SuppressWarnings': set to 'Ignore'
于 2014-03-21T10:36:23.070 回答
34

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

于 2012-02-17T21:51:03.837 回答
5

每个关于SuppressWarningsFilter的答案都缺少一个重要的细节。如果在您的 checkstyle-config.xml 中这样定义,您只能使用全小写的 id。如果不是,您必须使用原始模块名称。

例如,如果在我的 checkstyle-config.xml 我有:

<module name="NoWhitespaceBefore"/>

我不能使用:

@SuppressWarnings({"nowhitespacebefore"})

但是,我必须使用:

@SuppressWarnings({"NoWhitespaceBefore"})

为了让第一个语法起作用,checkstyle-config.xml 应该有:

<module name="NoWhitespaceBefore">
  <property name="id" value="nowhitespacebefore"/>
</module>

这对我有用,至少在 CheckStyle 6.17 版中。

于 2016-04-22T12:22:07.843 回答
2

我对上面的答案有困难,可能是因为我将 checkStyle 警告设置为错误。起作用的是 SuppressionFilter:http ://checkstyle.sourceforge.net/config_filters.html#SuppressionFilter

这样做的缺点是行范围存储在单独的 suppresssions.xml 文件中,因此不熟悉的开发人员可能不会立即建立连接。

于 2016-11-03T14:42:36.670 回答
1
<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

看更多

于 2017-08-18T14:38:05.840 回答
1

如果您使用qulicemvn 插件 ( https://github.com/teamed/qulice ) 中的 checkstyle ,您可以使用以下抑制:

// @checkstyle <Rulename> (N lines)
... code with violation(s)

或者


/**
 * ...
 * @checkstyle <Rulename> (N lines)
 * ...
 */
 ... code with violation(s)
于 2021-01-28T21:01:12.497 回答
0

您还可以使用以下特殊注释将要禁用特定警告的代码括起来:

// CHECKSTYLE:DISABLE:<CheckName>
<Your code goes here>
// CHECKSTYLE:ENABLE:<CheckName>

例如:// CHECKSTYLE:DISABLE:ParameterNumberCheck

您可以在此处找到支持的检查的完整列表(请参阅直接已知子类)。

于 2021-08-16T06:31:38.917 回答
0

试试 https://checkstyle.sourceforge.io/config_filters.html#SuppressionXpathFilter

您可以将其配置为:


<module name="SuppressionXpathFilter">
  <property name="file" value="suppressions-xpath.xml"/>
  <property name="optional" value="false"/>
</module>
        

使用带有 -g 选项的 CLI 生成 Xpath 抑制,并使用 -o 开关指定输出。

https://checkstyle.sourceforge.io/cmdline.html#Command_line_usage

这是一个 ant 片段,可以帮助您设置 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>

抑制-xpath.xml 在 Checkstyle 规则配置中被指定为 Xpath 抑制源。在上面的代码片段中,我将 Checkstyle 类路径从文件 cs.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

于 2019-11-27T13:15:14.717 回答