第三十五章. 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 插件提供了对 Sonar,一个基于 web 的代码质量监测平台的集成。该插件添加了 sonarAnalyze task ,用来分析一个project 及子project 都应用了哪个插件。分析结果存储于 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 task 是一项需要显式执行的独立任务,不依赖于任何其他 task。除了源代码之外,该 task 还分析了类文件和测试结果文件(如果有)。为获得最佳结果,建议在分析前运行一次完整的构建。在典型的设置中,会每天在构建服务器上运行一次分析。
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 插件应用于该project。
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” ).

Project 设置会决定这个项目将如何进行分析。默认配置非常适合于分析标准 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 project 设置
Example 35.3. Configuring Sonar project settings

build.gradle

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

在上面的例子中, sonarserverdatabaseproject 块分别配置的是 SonarRootModel SonarServer SonarDatabase SonarProject 类型的对象。可以查阅它们的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 插件应用于层次结构的最顶层项目。通常(但不是一定)会是根项目。在该project 中的 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 .

这些 Projects 也可以单独配置。例如,设置 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. 分析自定义的Source Sets

35.3. Analyzing Custom Source Sets

默认情况下,Sonar 插件将分析 main source set 里的生产源文件,以及 test source sets 里的测试源文件。它的分析独立于项目的源目录布局。根据需要,可以添加额外的 source sets。
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. 分析自定义的Source Sets
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 插件提供了hooks,用于 Sonar 属性传给代码分析器前的后置处理。相同的hook 可以用来添加额外的属性,并且不会被插件的对象模型所覆盖。
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 hook:
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 hook:
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的hook。对于第三方 Sonar 插件的配置,请参阅插件的文档。
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 插件向project 中添加了以下任务。
The Sonar plugin adds the following tasks to the project.

表 35.1. 声纳插件 - 任务
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.