1. Overview
1.概述
In this article, we’ll explore the gradle-lint plugin.
在本文中,我们将探讨 gradle-lint 插件。
First, we’ll see when to use it. Then, we’ll walk through the plugin configuration options. Next, we’ll use some of its predefined rules. Finally, we’ll generate lint reports.
首先,我们将了解何时使用该插件。然后,我们将了解插件的配置选项。接下来,我们将使用一些预定义规则。最后,我们将生成检查报告。
2. What’s Gradle Lint Plugin?
2.什么是 Gradle Lint 插件?
The Gradle Lint plugin helps with linting Gradle configuration files. It enforces build script structure throughout our code base. The plugin can keep the Gradle Wrapper version up to date, prevent bad practices across build files, and remove unused dependencies.
Gradle Lint 插件有助于Gradle配置文件的校验。它在整个代码库中强制执行构建脚本结构。该插件可以保持 Gradle Wrapper 版本最新,防止构建文件中的不良做法,并 删除未使用的依赖。
Practically, we use predefined rules or write custom ones. Then, we configure the plugin to consider them as violations or ignore them. The linter runs at the end of most Gradle tasks.
实际上,我们可以使用预定义规则或编写自定义规则。然后,我们对插件进行配置,将其视为违规或忽略。该插件在大多数 Gradle 任务的最后运行。
By default, it doesn’t modify the code directly but shows warnings instead. That’s helpful because other Gradle tasks won’t fail due to the plugin. Additionally, those warnings won’t get lost since they are visible at the end of the logs.
默认情况下,它不会直接修改代码,而是显示警告。这很有帮助,因为其他 Gradle 任务不会因为该插件而失败。此外,这些警告不会丢失,因为它们在日志末尾可见。
Furthermore, gradle-lint provides a fixGradleLint command to auto-fix most lint violations.
此外,gradle-lint 还提供了 fixGradleLint 命令,用于自动修复大多数违反校验规定的行为。
Internally, the Gradle Lint Plugin exploits Groovy AST and Gradle Model to apply lint rules. This showcases that the plugin is tightly coupled to the Groovy AST. Because of that, the plugin doesn’t support Kotlin build scripts.
在内部,Gradle Lint 插件利用 Groovy AST 和 Gradle Model 来应用检查规则。这表明该插件与 Groovy AST 紧密耦合。因此,插件不支持 Kotlin 构建脚本。
3. Setup
3.设置
There are three ways to set up the Gradle Lint plugin: in the build.gradle, an initialization script, or a script plugin. Let’s explore each one of them.
有三种方法可以设置 Gradle Lint 插件:在 build.gradle 中、初始化脚本或 脚本插件。让我们逐一探讨。
3.1. Using build.gradle
3.1.使用 build.gradle
Let’s add the gradle-lint plugin to our build.gradle:
让我们将 gradle-lint 插件添加到 build.gradle 中:
plugins {
id "nebula.lint" version "17.8.0"
}
The plugin should be applied to the root project when using a multi-module project. Since we’ll be using a multi-module project, let’s apply the plugin to the root project:
使用多模块项目时,应将插件应用于根项目。由于我们将使用多模块项目,因此让我们将插件应用到根项目:
allprojects {
apply plugin :"nebula.lint"
gradleLint {
rules = [] // we'll add rules here
}
}
Later on, we’ll add lint rules inside the gradleLint.rules array.
稍后,我们将在 gradleLint.rules 数组中添加校验规则。
3.2. Using Init Scripts
3.2.使用初始化脚本
Apart from build.gradle, we can use init scripts to configure our plugin:
除了 build.gradle 之外,我们还可以使用 init scripts 来配置我们的插件:
import com.netflix.nebula.lint.plugin.GradleLintPlugin
initscript {
repositories { mavenCentral() }
dependencies {
classpath 'com.netflix.nebula:gradle-lint-plugin:17.8.0'
}
}
allprojects {
apply plugin: GradleLintPlugin
gradleLint {
rules=[]
}
}
This lint.gradle script is identical to our setup earlier. To apply it, we’ll pass the –init-script flag to our tasks:
这个 lint.gradle 脚本与我们之前的设置完全相同。要应用它,我们将向任务传递 -init-script 标志:
./gradlew build --init-script lint.gradle
An interesting use case is to pass a different init script depending on the environment where the tasks are running. A downside is that we’ll always have to pass the –init-script flag.
一个有趣的用例是根据任务运行的环境传递不同的启动脚本。缺点是我们必须始终传递 -init-script 标记。
3.3. Using Script Plugins
3.3.使用脚本插件
Let’s apply a script plugin directly to our build.gradle:
让我们直接在 build.gradle 中应用 script 插件:
plugins{
id "nebula.lint" version "17.8.0"
}
apply from: "gradle-lint-intro.gradle"
The gradle-lint-intro.gradle content will be injected as if it were part of the build script:
gradle-lint-intro.gradle内容将像构建脚本的一部分一样被注入:
allprojects {
apply plugin: "nebula.lint"
gradleLint {
rules= []
}
}
In this article, we’ll keep our gradle-lint configuration in the build.gradle script.
在本文中,我们将在 build.gradle 脚本中保留 gradle-lint 配置。
4. Configuration
4.配置
Let’s review the different configuration options available in the grade-lint plugin.
让我们回顾一下 grade-lint 插件中的不同配置选项。
4.1. Execution
4.1.执行
The command to execute the Gradle Lint plugin is ./gradlew lintGradle. We can call it in isolation or during another task.
执行 Gradle Lint 插件的命令是 ./gradlew lintGradle。我们可以单独或在其他任务中调用它。
By default, the plugin automatically runs at the end of all tasks except these – help, tasks, dependencies, dependencyInsight, components, model, projects, wrapper, and properties:
默认情况下,插件会在所有任务结束时自动运行,但以下任务除外:help、tasks、dependencies、dependencyInsight、components、model、projects、wrapper和properties:
./gradlew build
This build task ends by calling ./gradlew lintGradle. The linter shows violations as warnings.
该 build 任务通过调用 ./gradlew lintGradle 结束。林特将违规行为显示为警告。
Besides, we can prevent the linter from running in a specific task by applying the skipForTask method:
此外,我们还可以通过应用 skipForTask 方法来防止在特定任务中运行衬垫程序:
gradleLint {
skipForTask('build')
}
Here, we prevent the plugin from running during the build task.
在这里,我们要防止插件在构建任务期间运行。
In case we want to disable the plugin for all tasks, we can use the alwaysRun flag:
如果我们想在所有任务中禁用该插件,可以使用 alwaysRun 标记:
gradleLint {
alwaysRun = false
}
This is particularly useful when we want to separately call ./gradlew lintGradle at a specific point in time.
当我们想在特定时间点分别调用 ./gradlew lintGradle 时,这一点尤其有用。
It’s important to note that calling the plugin in isolation marks the lint violations as errors, not warnings.
需要注意的是,单独调用该插件会将违反 lint 的行为标记为错误,而不是警告。
4.2. Rules Definition
4.2.规则定义
Gradle Lint plugin allows us to configure two groups of rules: violation rules (via rules and critcalRules options) and ignored rules (using excludedRules, ignore, and fixme properties). Let’s explore them.
Gradle Lint 插件允许我们配置两组规则:违反规则(通过 rules 和 critcalRules 选项)和忽略规则(使用 excludedRules, ignore 和 fixme 属性)。让我们一起来探索它们。
First, the rules property takes an array of lint rules. When violations defined by the rules are met, the linter raises warnings. But if the Gradle Lint Plugin is running in isolation, those warnings make the build fail.
首先,rules 属性接收一个 lint 规则数组。如果违反了规则中的规定,林特尔就会发出警告。但如果 Gradle Lint Plugin 独立运行,这些警告会导致构建失败。
Next, let’s explore the criticalRules option. We add a rule to the gradleLint.criticalRules property when we want the rule violation to trigger a task failure. The plugin offers a specific criticalLintGradle task to only lint critical rules:
接下来,让我们探讨一下 criticalRules 选项。当我们希望违反规则触发任务失败时,我们将规则添加到 gradleLint.criticalRules 属性中。该插件提供了一个特定的 criticalLintGradle 任务,仅用于检查关键规则:
./gradlew criticalLintGradle -PgradleLint.criticalRules=undeclared-dependency
Here, the -PgradleLint.criticalRules option adds the undeclared-dependency rule to criticalRules. Then, the criticalLintGradle task only lints rules defined in criticalRules.
在这里,-PgradleLint.criticalRules 选项将 undeclared-dependency 规则添加到 criticalRules 中。然后,criticalLintGradle 任务将只执行 criticalRules 中定义的规则。
Continuing, the excludedRules option takes a list of rules to ignore. It comes in handy when we want to ignore a specific rule from a group rule:
继续,excludedRules 选项将接收一个要忽略的规则列表。当我们想从组规则中忽略特定规则时,该选项就派上用场了:
gradleLint {
rules= ['all-dependency']
excludedRules= ['undeclared-dependency']
}
We’ve excluded the undeclared-dependency rule from our previous all-dependency group rule. A group rule allows us to apply a set of rules at once.
我们已将 undeclared-dependency 规则排除在之前的 all-dependency 组规则之外。 组规则允许我们同时应用一组规则。
Finally, we can prevent the linter from scanning parts of our build files by wrapping them in the ignore property:
最后,我们可以用 ignore 属性来封装构建文件中的部分内容,以防止线程扫描这些内容:
dependencies {
testImplementation('junit:junit:4.13.1')
gradleLint.ignore('dependency-parentheses') {
implementation("software.amazon.awssdk:sts")
}
}
We’ve intentionally guarded aws-sts against the dependency-parenthesis rule. It won’t be listed when we run the linter:
我们有意使 aws-sts 免受 依赖-括弧规则的影响。当我们运行内部程序时,它将不会被列出:
warning dependency-parentheses parentheses are unnecessary for dependencies
gradle-lint-intro/build.gradle:11
testImplementation('junit:junit:4.13.1')
The dependency-parentheses warns against the unnecessary use of parentheses in the Gradle dependencies declaration.
依赖关系括号警告在 Gradle 依赖关系声明中不要使用不必要的括号。
Besides, we can swap the ignore for the fixme property if we want to temporarily ignore a rule:
此外,如果我们想暂时忽略某条规则,可以将 ignore 属性换成 fixme 属性:
gradleLint.fixme('2029-04-23', 'dependency-parentheses') {
implementation('software.amazon.awssdk:sts')
}
Here, the aws-sts dependency will trigger an unused-dependency violation after April, the 23rd 2029.
在这里,aws-sts 依赖关系将在 2029 年 4 月 23 日之后触发未使用依赖关系违规。
It’s important to note that the ignore and fixme properties are only effective on resolved dependencies. They don’t work on wrapped declarations in a build file:
需要注意的是,ignore 和 fixme 属性仅对已解决的依赖关系有效。它们对构建文件中的包装声明不起作用:。
dependencies {
gradleLint.ignore('unused-dependency') {
implementation "software.amazon.awssdk:sts"
}
}
We’ve intentionally guarded aws-sts against the unused dependency rule. We don’t use it directly in our code. But for some reason, it’s required by AWS WebIdentityTokenCredentialsProvider. Unfortunately, the linter won’t catch that because it doesn’t evaluate unresolved dependencies.
我们有意防止 aws-sts 使用未使用的依赖规则。我们不会在代码中直接使用它。但出于某种原因,AWS WebIdentityTokenCredentialsProvider 需要使用它。不幸的是,内部函数不会捕捉到这一点,因为它不会评估未解决的依赖关系。
4.3. Overriding Configuration Properties
4.3.覆盖配置属性
Gradle Lint allows us to override some configuration properties in the command line. We do this by using the -PgradleLint option followed by any valid file configuration option.
Gradle Lint 允许我们在命令行中覆盖某些配置属性。我们可以使用 -PgradleLint 选项,然后再加上任何有效的文件配置选项。
Let’s add the unused-dependency rule to our initial empty rules array:
让我们将 unused-dependency 规则添加到初始的空 rules 数组中:
gradleLint {
rules= ['unused-dependency']
}
Next, let’s prevent the linter from applying it by excluding it via the command line:
接下来,让我们通过命令行将其排除在外,以防止印字机应用它:
./gradlew lintGradle -PgradleLint.excludedRules=unused-dependency
This is the equivalent of setting excludedRules=[“unused-dependency”] in the configuration file.
这相当于在配置文件中设置 excludedRules=[“unused-dependency”] 。
We can use this pattern for all the other properties, especially when running in CI environments. Multiple values should be comma-separated.
我们可以将此模式用于所有其他属性,尤其是在CI 环境中运行时。多个值应以逗号分隔。
5. Built-in Rules
5.内置规则
The Gradle Lint plugin has several built-in lint rules. Let’s explore some of them.
Gradle Lint 插件有几个内置的 lint 规则。让我们来探讨其中的一些。
5.1. Minimum Dependency Version Rule
5.1.最小依赖版本规则
First, let’s see the minimum-dependency-version rule. It shows violations for dependencies that have a strictly lower version than a predefined one:
首先,让我们看看 minimum-dependency-version 规则。如果依赖项的版本严格低于预定义的版本,它就会显示违规行为:
gradleLint {
rules= ['minimum-dependency-version']
}
We’ll need to provide the comma-separated list of minimum dependency versions in the minVersions property. But, as of this writing, the GradleLintExtension doesn’t have the minVersions property. Therefore, let’s set it via the command line:
我们需要在 minVersions 属性中提供以逗号分隔的最小依赖关系版本列表。但是,截至本文撰写之时,GradleLintExtension 还没有 minVersions 属性。因此,让我们通过命令行来设置它:
./gradlew lintGradle -PgradleLint.minVersions=junit:junit:5.0.0
Here, the linter warns against the use of junit versions lower than 5.0.0:
在此,打印机警告不要使用junit低于 5.0.0的版本:
> Task :lintGradle FAILED
This project contains lint violations. A complete listing of the violations follows.
Because none were serious, the build's overall status was unaffected.
warning minimum-dependency-version junit:junit is below the minimum version of 5.0.0 (no auto-fix available). See https://github.com/nebula-plugins/gradle-lint-plugin/wiki/Minimum-Dependency-Version-Rule for more details
? 1 problem (0 errors, 1 warning)
To apply fixes automatically, run fixGradleLint, review, and commit the changes.
Running ./gradlew fixGradleLint effectively updates junit versions to 5.0.0.
运行 ./gradlew fixGradleLint 可有效地将 junit 版本更新为 5.0.0. 。
5.2. Undeclared Dependency Rule
5.2.未声明的从属关系规则
Next, we’ll learn about the undeclared-dependency rule. It ensures we have explicitly declared transitive dependencies that we directly use in our code:
接下来,我们将学习 undeclared-dependency 规则。它确保我们已显式声明代码中直接使用的过渡依赖:
gradleLint {
rules= ['undeclared-dependency']
}
Now, let’s execute the lintGradle task:
现在,让我们执行 lintGradle 任务:
> Task :lintGradle FAILED
This project contains lint violations. A complete listing of the violations follows.
Because none were serious, the build's overall status was unaffected.
warning undeclared-dependency one or more classes in org.hamcrest:hamcrest-core:1.3 are required by your code directly
warning undeclared-dependency one or more classes in org.apache.httpcomponents:httpcore:4.4.13 are required by your code directly
? 2 problems (0 errors, 2 warnings)
To apply fixes automatically, run fixGradleLint, review, and commit the changes.
We can see that we have two dependencies directly required by our code. The linter adds them after we run the fixlintGradle task:
我们可以看到,我们的代码直接需要两个依赖项。在我们运行 fixlintGradle 任务后,linter 会添加它们:
> Task :fixLintGradle
This project contains lint violations. A complete listing of my attempt to fix them follows. Please review and commit the changes.
fixed undeclared-dependency one or more classes in org.hamcrest:hamcrest-core:1.3 are required by your code directly
fixed undeclared-dependency one or more classes in org.apache.httpcomponents:httpcore:4.4.13 are required by your code directly
Corrected 2 lint problems
Besides, as of this writing, it’s impossible to feed custom rules to the plugin. An alternative could be to fork the library and add custom rules directly.
此外,截至本文撰写之时,还无法向插件提供自定义规则。另一种方法是分叉库并直接添加自定义规则。
Finally, we should be careful when using outdated rules. The archaic-wrapper rule was removed in 2018. Some sections of the documentation are yet to be updated.
最后,我们在使用过时的规则时应小心谨慎。archaic-wrapper 规则已于 2018 年删除。文档的某些部分尚未更新。
6. Generating Reports
6.生成报告
Now, let’s generate reports using the generateGradleLintReport task:
现在,让我们使用 generateGradleLintReport 任务生成报告:
./gradlew generateGradleLintReport
By default, the report format is HTML. The plugin places all report files in the build/reports/gradleLint folder. Our HTML report will be named gradle-5.html, where gradle-5 is our root project name.
默认情况下,报告格式为 HTML。插件会将所有报告文件放在 build/reports/gradleLint 文件夹中。我们的 HTML 报告将命名为 gradle-5.html,其中 gradle-5 是我们的根项目名称。
The other available options are xml and text:
其他可用选项为xml和text:。
gradleLint {
reportFormat = 'text'
reportOnlyFixableViolations = true
}
We’ve used the reportFormat property to directly output the report in plain text. Additionally, our report only contains fixable violations thanks to the activated reportOnlyFixableViolations flag.
我们使用 reportFormat 属性直接以纯文本输出报告。此外,由于激活了reportOnlyFixableViolations标志.,我们的报告只包含可修复的违规行为。
7. Conclusion
7.结论
In this article, we explored the gradle-lint plugin. First, we saw its utility. Then, we listed the different configuration options. Next, we used some predefined rules. Finally, we generated lint reports.
在本文中,我们探讨了 gradle-lint 插件。首先,我们了解了它的实用性。然后,我们列出了不同的配置选项。接着,我们使用了一些预定义的规则。最后,我们生成了检查报告。
As always, the code for this article is available over on GitHub.
与往常一样,本文的代码可在 GitHub 上获取。