第三十五章. Sonar 插件

Chapter 35. The Sonar Plugin

你可能会想使用新的 Sonar Runner 插件 来代替现在这个插件。尤其是因为只有 Sonar Runner 插件支持 Sonar 3.4 及更高的版本。
You may wish to use the new Sonar Runner Plugin instead of this plugin. In particular, only the Sonar Runner plugin supports Sonar 3.4 and higher.

Sonar 是一个用于监控代码质量的基于 Web 的平台,Sonar 插件提供了对它的集成。该插件添加了一个 sonarAnalyze 任务,用来分析一个项目及其子项目都应用了哪些插件,分析的结果存在 Sonar 数据库中。该插件基于 Sonar Runner,并且需要 Sonar 2.11 或更高的版本。
The Sonar plugin provides integration with Sonar, a web-based platform for monitoring code quality. The plugin adds a sonarAnalyze task that analyzes the project to which the plugin is applied, as well as its subprojects. The results are stored in the Sonar database. The plugin is based on the Sonar Runner and requires Sonar 2.11 or higher.

这个 sonarAnalyze 任务是一个需要显式执行的独立任务, 并且不依赖于其他任务。除了源代码之外,该任务还分析了类文件和测试结果文件(如果有)。为获得最佳结果,建议在分析之前运行一次完整的构建。在典型设置中,会每天在构建服务器上执行一次分析。
The sonarAnalyze task is a standalone task that needs to be executed explicitly and doesn't depend on any other tasks. Apart from source code, the task also analyzes class files and test result files (if available). For best results, it is therefore recommended to run a full build before the analysis. In a typical setup, analysis would be performed once per day on a build server.

35.1. 用法

35.1. Usage

最低要求是必须配置在项目中应用 Sonar 插件。
At a minimum, the Sonar plugin has to be applied to the project.

示例 35.1. 应用 Sonar 插件 - Example 35.1. Applying the Sonar plugin

build.gradle

apply plugin: "sonar"

除非 Sonar 是在本地上运行,并且有默认的配置,否则有必要配置 Sonar 服务器及数据库的连接设置。
Unless Sonar is run locally and with default settings, it is necessary to configure connection settings for the Sonar server and database.

示例 35.2. 配置 Sonar 连接设置 - Example 35.2. Configuring Sonar connection settings

build.gradle

sonar {
    server {
        url = "http://my.server.com"
    }
    database {
        url = "jdbc:mysql://my.server.com/sonar"
        driverClassName = "com.mysql.jdbc.Driver"
        username = "Fred Flintstone"
        password = "very clever"
    }
}

或者也可以从命令行设置其中一些或全部的连接设置(见《第 35.6 节,“从命令行中配置 Sonar 设置”》)。
Alternatively, some or all connection settings can be set from the command line (see Section 35.6, “Configuring Sonar Settings from the Command Line”).

项目设置决定了项目的分析方式。默认配置非常适合分析标准的 Java 项目,并且可以通过多种方式进行自定义。
Project settings determine how the project is going to be analyzed. The default configuration works well for analyzing standard Java projects and can be customized in many ways.

示例 35.3. 配置 Sonar 项目的设置 - Example 35.3. Configuring Sonar project settings

build.gradle

sonar {
    project {
        coberturaReportPath = file("$buildDir/cobertura.xml")
    }
}

在上面的例子中,sonarserverdatabaseproject 块分别配置的是SonarRootModelSonarServerSonarDatabaseSonarProject 类型的对象。有关详细信息,可以参阅其 API 文档。
The sonar, server, database, and project blocks in the examples above configure objects of type SonarRootModel, SonarServer, SonarDatabase, and SonarProject, respectively. See their API documentation for further information.

35.2. 分析多项目构建

35.2. Analyzing Multi-Project Builds

Sonar 插件能够立即分析整个项目的层次结构。这将在 Sonar Web 界面中生成一个层次图,该层次图包含了一些综合指标且能够深入到子项目中。同时,它也比分别分析每个项目更快。
The Sonar plugin is capable of analyzing a whole project hierarchy at once. This yields a hierarchical view in the Sonar web interface with aggregated metrics and the ability to drill down into subprojects. It is also faster than analyzing each project separately.

要分析项目的层次结构,需要将 Sonar 插件应用于层次结构的最顶层项目。这通常(但也不一定)会是根项目。在该项目的 sonar 块配置的是一个 SonarRootModel 类型的对象。它包含了所有全局配置,最重要的是服务器和数据库的连接设置。
To analyze a project hierarchy, the Sonar plugin needs to be applied to the top-most project of the hierarchy. Typically (but not necessarily) this will be the root project. The sonar block in that project configures an object of type SonarRootModel. It holds all global configuration, most importantly server and database connection settings.

示例 35.4. 在多项目构建中的全局配置 - Example 35.4. Global configuration in a multi-project build

build.gradle

apply plugin: "sonar"

sonar {
    server {
        url = "http://my.server.com"
    }
    database {
        url = "jdbc:mysql://my.server.com/sonar"
        driverClassName = "com.mysql.jdbc.Driver"
        username = "Fred Flintstone"
        password = "very clever"
    }
}

在这个层次结构中的每个项目都有其自己的项目配置。共同的值可以在父构建脚本中设置。
Each project in the hierarchy has its own project configuration. Common values can be set from a parent build script.

示例 35.5. 多项目构建中的共同项目配置 - Example 35.5. Common project configuration in a multi-project build

build.gradle

subprojects {
    sonar {
        project {
            sourceEncoding = "UTF-8"
        }
    }
}

在子项目中的 sonar 块配置的是一个 SonarProjectModel 类型的对象。
The sonar block in a subproject configures an object of type SonarProjectModel.

项目也可以单独配置。例如,设置 skip 属性为true 以防止一个项目(及其子项目)被分析。所跳过的项目不会显示在 Sonar Web 界面中。
Projects can also be configured individually. For example, setting the skip property to true prevents a project (and its subprojects) from being analyzed. Skipped projects will not be displayed in the Sonar web interface.

示例 35.6. 多项目构建中的单独项目配置 - Example 35.6. Individual project configuration in a multi-project build

build.gradle

project(":project1") {
    sonar {
        project {
            skip = true
        }
    }
}

另一种典型的每个项目配置是配置要分析的编程语言。请注意,每一个项目 Sonar 只能分析一种语言。
Another typical per-project configuration is the programming language to be analyzed. Note that Sonar can only analyze one language per project.

示例 35.7. 配置要分析的语言 - Example 35.7. Configuring the language to be analyzed

build.gradle

project(":project2") {
    sonar {
        project {
            language = "groovy"
        }
    }
}

当一次只设置一个属性时,等效属性的语法更加简洁:
When setting only a single property at a time, the equivalent property syntax is more succinct:

示例 35.8. 使用属性语法 - Example 35.8. Using property syntax

build.gradle

project(":project2").sonar.project.language = "groovy"

35.3. 分析自定义源集

35.3. Analyzing Custom Source Sets

默认情况下,Sonar 插件将分析在 main 源集里的生产源文件和 test 源集里的测试源文件。它们的分析独立于项目的源目录布局。根据需求,可以添加其他的源集。
By default, the Sonar plugin will analyze the production sources in the main source set and the test sources in the test source set. This works independent of the project's source directory layout. Additional source sets can be added as needed.

示例 35.9. 分析自定义的源集 - Example 35.9. Analyzing custom source sets

build.gradle

sonar.project {
    sourceDirs += sourceSets.custom.allSource.srcDirs
    testDirs += sourceSets.integTest.allSource.srcDirs
}

35.4. 分析非 Java 语言

35.4. Analyzing languages other than Java

要分析非 Java 语言编写的代码,请安装相应的 Sonar 插件,并相应地设置 sonar.project.language
To analyze code written in a language other than Java, install the corresponding Sonar plugin, and set sonar.project.language accordingly:

示例 35.10. 分析非 Java 语言 - Example 35.10. Analyzing languages other than Java

build.gradle

sonar.project {
    language = "grvy" // set language to Groovy
}

从 Sonar 3.4 开始,每个项目只能分析一种语言。不过,你可以为多项目构建中的每个项目设置不同的语言。
As of Sonar 3.4, only one language per project can be analyzed. You can, however, set a different language for each project in a multi-project build.

35.5. 设置自定义的 Sonar 属性

35.5. Setting Custom Sonar Properties

最终,大多数配置都会以被称为 Sonar 属性的键值对的形式传递给 Sonar 代码分析器。在 API 文档中的 SonarProperty 注解显示了插件的对象模型的属性如何映射到相应的 Sonar 属性。Sonar 插件在传递给代码分析器之前提供了后置处理的 Sonar 属性的钩子。相同的钩子可以用来添加插件的对象模型所未涵盖的其他属性。
Eventually, most configuration is passed to the Sonar code analyzer in the form of key-value pairs known as Sonar properties. The SonarProperty annotations in the API documentation show how properties of the plugin's object model get mapped to the corresponding Sonar properties. The Sonar plugin offers hooks to post-process Sonar properties before they get passed to the code analyzer. The same hooks can be used to add additional properties which aren't covered by the plugin's object model.

对于全局的 Sonar 属性,可以使用 SonarRootModel 上的 withGlobalProperties 钩子:
For global Sonar properties, use the withGlobalProperties hook on SonarRootModel:

示例 35.11. 设置自定义的全局属性 - Example 35.11. Setting custom global properties

build.gradle

sonar.withGlobalProperties { props ->
    props["some.global.property"] = "some value"
    // non-String values are automatically converted to Strings
    props["other.global.property"] = ["foo", "bar", "baz"]
}

对于每个项目的 Sonar 属性,使用 SonarProject 上的 withProjectProperties 钩子:
For per-project Sonar properties, use the withProjectProperties hook on SonarProject:

示例 35.12. 设置自定义的项目属性 - Example 35.12. Setting custom project properties

build.gradle

sonar.project.withProjectProperties { props ->
    props["some.project.property"] = "some value"
    // non-String values are automatically converted to Strings
    props["other.project.property"] = ["foo", "bar", "baz"]
}

Sonar 的可用属性列表可以在 Sonar 文档中找到。注意,对于这些属性的大部分,在 Sonar 插件的对象模型中都具有等效的属性,且没有必要使用 withGlobalPropertieswithProjectProperties 的钩子。
A list of available Sonar properties can be found in the Sonar documentation. Note that for most of these properties, the Sonar plugin's object model has an equivalent property, and it isn't necessary to use a withGlobalProperties or withProjectProperties hook. For configuring a third-party Sonar plugin, consult the plugin's documentation.

35.6. 从命令行配置 Sonar 的设置

35.6. Configuring Sonar Settings from the Command Line

下面的属性可以从命令行中或者是作为 sonarAnalyze 任务的参数这来设置。任务参数将覆盖构建脚本中设置的任何相应值。
The following properties can alternatively be set from the command line, as task parameters of the sonarAnalyze task. A task parameter will override any corresponding value set in the build script.

  • server.url
  • database.url
  • database.driverClassName
  • database.username
  • database.password
  • showSql
  • showSqlResults
  • verbose
  • forceAnalysis

下面是一个完整的例子:
Here is a complete example:

gradle sonarAnalyze --server.url=http://sonar.mycompany.com --database.password=myPassword --verbose

如果你需要从命令行设置其他属性,可以使用系统属性来做:
If you need to set other properties from the command line, you can use system properties to do so:

示例 35.13. 实现自定义命令行属性 - Example 35.13. Implementing custom command line properties

build.gradle

sonar.project {
    language = System.getProperty("sonar.language", "java")
}

但是,请记住,通常最好将配置保留在构建脚本中,并在源代码管理下。
However, keep in mind that it is usually best to keep configuration in the build script and under source control.

35.7. 任务

35.7. Tasks

Sonar 插件向项目添加了以下任务。
The Sonar plugin adds the following tasks to the project.

表 35.1. Sonar 插件——任务 - Table 35.1. Sonar plugin - tasks

任务名称
Task name
依赖于
Depends on
类型
Type
描述
Description
sonarAnalyze - SonarAnalyze 分析项目层次结构,并将结果存储在 Sonar 数据库。
Analyzes a project hierarchy and stores the results in the Sonar database.