checkstyle

命令行工具

checkstyle/checkstyle

用于检查 Java 代码风格的静态分析工具。

项目简介

Checkstyle 帮助 Java 开发者编写符合编码标准的代码,默认支持 Google Java Style Guide 和 Sun Code Conventions。它高度可配置,可通过命令行或 ANT 任务运行,能检测 switch 分支穿透等问题。

README 预览

# Checkstyle - Java Code Quality Tool\n\n\n\n--------------------------\n\n*Checkstyle is a tool that ensures adherence to a code standard or a set of best practices.*\n\n[![][appveyor img]][appveyor]\n[![][circleci img]][circleci]\n[![][cirrusci img]][cirrusci]\n[![][coverage img]][coverage]\n[![][snyk img]][snyk]\n[![][semaphoreci img]][semaphoreci]\n[![][azure img]][azure]\n[![][error prone img]][error prone]\n[![][qodana img]][qodana]\n[![][pitest img]][pitest]\n[![][checker framework img]][checker framework]\n[![][dependabot img]][dependabot]\n[![][release notes/version img]][release notes/version]\n[![][closed issues img]][closed issues]\n[![][link check img]][link check]\n[![][milestone img]][milestone]\n[![][buildkite img]][buildkite]\n\n[![][mavenbadge img]][mavenbadge]\n\nThe latest release version can be found at\n[GitHub releases](https://github.com/checkstyle/checkstyle/releases/)\nor at [Maven repo](https://repo1.maven.org/maven2/com/puppycrawl/tools/checkstyle/).\n\nDocumentation is available in HTML format, see [Checkstyle checks][checks-docs].\n\nThe latest deployed website from `master` is available [here][site-latest].\n\n## Table of Contents\n\n- [Quick Start](#quick-start)\n- [Contributing](#contributing)\n- [Feedback and Support](#feedback-and-support)\n- [Javadoc](#javadoc)\n- [Sponsor Checkstyle](#sponsor-checkstyle)\n- [Licensing](#licensing)\n\n## Quick Start\n\n- Download our [Latest Release](https://github.com/checkstyle/checkstyle/releases/) from GitHub\n  or add Checkstyle to your build from [Maven Central][maven-central].\n- Read our Documentation for [usage](https://checkstyle.org/cmdline.html)\n  and [configuration](https://checkstyle.org/config.html).\n\n```bash\n$ cat config.xml\n\n\n\n  \n    \n  \n\n\n$ cat Test.java\nclass Test {\n  public void foo() {\n    int i = 0;\n    while (i >= 0) {\n      switch (i) {\n        case 1:\n        case 2:\n          i++;\n        case 3: // violation 'fall from previous branch of the switch'

常见问题 (5)

故障排除
为什么 Bash 脚本在函数或 Maven 命令失败后仍然继续执行,以及如何让它快速失败?

诸如 CS_version=$(getCheckstylePomVersion) 这样的命令替换本身并不会终止脚本。如果 Maven 执行失败,脚本可能会带着无效或空的输出继续运行,随后产生诸如 Unrecognized option 这样令人困惑的错误。应在调用之后添加显式的状态检查:

CS_version="$(getPomVersion)" || {
  echo "Failed to determine Checkstyle POM version" >&2
  exit 1
}

为了实现可靠的快速失败行为,还应在脚本顶部添加:

set -euo pipefail

当函数将 Maven 的输出通过管道传递给 grep、sed 或类似命令时,pipefail 非常重要;否则即使 Maven 失败,整个管道也可能被判定为成功。应将版本查询保留在辅助函数中,并在每个调用点都应用该防护检查,正如 Checkstyle 的 .ci/util.sh、validation.sh、no-exception-test.sh 以及发布脚本中所做的那样。

来源 Issue #9956
故障排除
为什么 Checkstyle 的 MissingJavadocMethod 在启用 allowMissingPropertyJavadoc 时,会误报包含块注释的 getter 或 setter 方法?

这是 Checkstyle 在 14.2.0 等版本中的一个 bug:访问器(accessor)检测会跳过 // 单行注释,但不会跳过 /* ... */ 块注释,因此块注释可能导致合法的 getter/setter 无法被识别。请升级到包含 issue #21755 修复的 Checkstyle 版本。作为临时解决方案,可以将访问器内的块注释替换为单行注释、将其删除,或对受影响的方法抑制 MissingJavadocMethod 检查。例如,在方法体内使用 // comment 而不是 /* block comment */。

来源 Issue #21755
故障排除
为什么 Checkstyle RegexpSinglelineJava 在 ignoreComments 为 true 且正则表达式存在零宽匹配时会挂起?

Checkstyle 14.1.0 在被抑制的匹配项宽度为零时(例如注释中的 (?=TODO)),可能会在 SinglelineDetector.checkLine 中进入无限循环。代码调用 matcher.find(startPosition) 并设置 startPosition = matcher.end(),但对于零宽度匹配,start 和 end 相等,因此会反复找到同一个匹配项。

已合并的修复将 matcher.find(startPosition) 替换为 matcher.find(),使匹配器能够跳过空匹配继续向前推进。请升级到包含 issue #21519 修复的 Checkstyle 版本。

作为变通方法,请将零宽度模式替换为消耗字符的模式。对于本例,请使用:

<property name="format" value="TODO"/>

在 ignoreComments=true 的情况下,注释中的匹配仍会被抑制,而代码中的 TODO 会被报告。在运行修复版本之前,请避免使用 lookahead 或其他可能产生空匹配的模式。

来源 Issue #21519
故障排除
如何修复 Checkstyle RequireThis 误报:在具有同名继承字段的匿名类中出现 "Reference to instance variable needs 'Enclosing.this'"?

这是一个已知的 Checkstyle RequireThisCheck bug(#5353),至少影响 Checkstyle 8.8。当匿名类继承的父类型声明了与外部类字段同名的字段时,非限定引用会解析到匿名对象继承的字段,但 Checkstyle 会错误地将其报告为外部字段。

修复方法:升级到包含 #5353 修复的 Checkstyle 版本,最好是最新版本,然后重新运行:

java -jar checkstyle-latest-all.jar -c TestConfig.xml TestClass.java

如果暂时无法升级,请显式限定该继承的引用:

f = 1;

改为:
this.f = 1;

this.f 仍然引用从 AbstractClass 继承的字段;除非您确实需要外部实例的字段,否则不要使用 TestClass.this.f。重命名其中一个字段是另一种解决方法。

来源 Issue #5353
故障排除
如何修复 Checkstyle DescendantToken 检查在处理深度嵌套的字符串拼接时抛出的 StackOverflowError?

DescendantTokenCheck.countTokens 以递归方式遍历 AST,因此一个极深的表达式(单条语句中包含数千个 + 操作数,例如生成的代码)会在违规被报告之前就导致 JVM 栈溢出。该问题已由 PR #21902 修复,该 PR 将递归遍历替换为迭代遍历(与解析器的非递归处理方式一致,参见 JavaAstVisitorTest#testNoStackOverflowOnDeepStringConcat)——请升级到包含该修复的 Checkstyle 版本。在此之前可采用以下变通方法:(1) 增大线程栈:java -Xss8m -jar checkstyle-14.3.0-all.jar -c config.xml Test.java(逐步增大 -Xss 直至运行完成);(2) 将表达式拆分为多条较短的语句或使用中间变量,以降低 AST 深度;(3) 通过 BeforeExecutionExclusionFileFilter 排除有问题的/生成的文件。请注意,SuppressionFilter/SuppressionXpathFilter 不会有任何帮助——崩溃发生在遍历期间,此时任何违规事件尚未创建。

来源 Issue #22045