使用代码格式化程序

存在代码格式化程序,以确保编写的代码样式在整个代码库中保持一致。这在许多大型项目中都得到过应用。从Android到OpenCV。团队可能希望在整个机器人代码中添加格式化程序,以确保代码库始终保持可读性和一致性。

在本文中,我们将重点介绍Java团队使用Spotpot <https://github.com/diffplug/spotless> __和C ++团队使用wpiformat <https://github.com/wpilibsuite/styleguide/blob/main/wpiformat/README.rst>__。

一尘不染

配置

为了实现Spotless功能,需要进行必要的build.gradle更改。在build.gradle的plugins {}块中,添加Spotless插件,使其看起来类似于以下内容。

plugins {
   id "java"
   id "edu.wpi.first.GradleRIO" version "2024.1.1"
   id 'com.diffplug.spotless' version '6.20.0'
}

然后确保您添加了一个必需的``spotless {}’’块以正确配置一尘不染。这可以放在build.gradle的末尾。

spotless {
   java {
      target fileTree('.') {
            include '**/*.java'
            exclude '**/build/**', '**/build-*/**'
      }
      toggleOffOn()
      googleJavaFormat()
      removeUnusedImports()
      trimTrailingWhitespace()
      endWithNewline()
   }
   groovyGradle {
      target fileTree('.') {
            include '**/*.gradle'
            exclude '**/build/**', '**/build-*/**'
      }
      greclipse()
      indentWithSpaces(4)
      trimTrailingWhitespace()
      endWithNewline()
   }
   format 'xml', {
      target fileTree('.') {
            include '**/*.xml'
            exclude '**/build/**', '**/build-*/**'
      }
      eclipseWtp('xml')
      trimTrailingWhitespace()
      indentWithSpaces(2)
      endWithNewline()
   }
   format 'misc', {
      target fileTree('.') {
            include '**/*.md', '**/.gitignore'
            exclude '**/build/**', '**/build-*/**'
      }
      trimTrailingWhitespace()
      indentWithSpaces(2)
      endWithNewline()
   }
}

Running Spotless

可以使用../gradlew spotlessApply来运行Spotless,这将应用所有格式选项。您还可以仅通过添加格式化程序的名称来指定特定任务。一个示例是``./gradlew spotlessmiscApply’’。

In addition to formatting code, Spotless can also ensure the code is correctly formatted; this can be used by running ./gradlew spotlessCheck. Thus, Spotless can be used as a CI check, as shown in the following GitHub Actions workflow:

on: [push]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  spotless:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest
    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-java@v4
        with:
          distribution: 'zulu'
          java-version: 17
      - run: ./gradlew spotlessCheck

选项说明

每个``格式’’部分突出显示项目中自定义文件的格式。 Java和GroovyGradle本身受Spotless的支持,因此它们的定义有所不同。

分解这一点,我们可以将其分为多个部分。

  • 格式化Java

  • 格式化Gradle文件

  • 格式化XML文件

  • 格式化其他文件

它们都是相似的,除了一些小的差异将被解释。下面的示例将突出显示“ java {}”块。

java {
   target fileTree('.') {
      include '**/*.java'
      exclude '**/build/**', '**/build-*/**'
   }
   toggleOffOn()
   googleJavaFormat()
   removeUnusedImports()
   trimTrailingWhitespace()
   endWithNewline()
}

让我们解释每个选项的含义。

target fileTree('.') {
   include '**/*.java'
   exclude '**/build/**', '**/build-*/**'
}

上面的例子告诉我们Java类在哪里,并排除了build目录。其余选项都不言自明。

  • toggleOffOn()增加了使项目Spotless的能力。用法如下所示

// format:off

public void myWeirdFunction() {

}

// format:on
  • ``googleJavaFormat()``告诉Spotless地根据`Google样式指南<https://google.github.io/styleguide/javaguide.html>`__

  • removeUnusedImports() will remove any unused imports from any of your Java classes

  • ``trimTrailingWhitespace()``将删除行尾的所有多余空格

  • ``endWithNewline()``将在课程末尾添加换行符

在groovyGradle块中,有一个Greclipse选项。这是一尘不染的格式程序,用于格式化gradle文件。

另外,在xml块中有一个“ eclipseWtp”选项。这代表“ Gradle Web工具平台”,并且是格式化“ xml”文件的格式化程序。不使用任何XML文件的团队可能希望不包括此配置。

备注

完整的配置列表位于`Spotless README <https://github.com/diffplug/spotless>`__

线尾问题

Spotless将尝试在每个OS上应用行尾,这意味着如果两个用户使用不同的OS(Unix与Windows),则Git差异将不断变化。建议从多个操作系统向同一存储库做出贡献的团队使用.gitattributes文件。以下内容足以处理行尾。

*.gradle text eol=lf
*.java text eol=lf
*.md text eol=lf
*.xml text eol=lf

WPI格式

要求

您可以通过在终端或命令提示符中键入“ pip3 install wpiformat”来安装`wpiformat <https://github.com/wpilibsuite/styleguide/blob/main/wpiformat/README.rst>`__。

用法

可以通过在控制台中键入``wpiformat’’来运行wpiformat。这将使用``clang-format’’格式化。需要三个配置文件(“ .clang-format”,“。styleguide”,“。styleguide-license”)。这些必须存在于项目根目录中。

  • ``.clang-format’’::download:下载<https://raw.githubusercontent.com/wpilibsuite/allwpilib/main/.clang-format>

  • ``.styleguide-license’’::download:下载<https://raw.githubusercontent.com/wpilibsuite/allwpilib/main/.styleguide-license>

样式指南示例如下所示:

cppHeaderFileInclude {
   \.h$
   \.hpp$
   \.inc$
   \.inl$
}

cppSrcFileInclude {
   \.cpp$
}

modifiableFileExclude {
   gradle/
}

备注

团队可以根据需要调整.styleguide和.styleguide-license。重要的是不要删除它们,因为它们是运行wpiformat所必需的!

You can turn this into a CI check by running git --no-pager diff --exit-code HEAD, as shown in the example GitHub Actions workflow below:

name: Lint and Format

on:
  pull_request:
  push:
jobs:
  wpiformat:
    name: "wpiformat"
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Fetch all history and metadata
        run: |
          git checkout -b pr
          git branch -f main origin/main
      - name: Set up Python 3.8
        uses: actions/setup-python@v5
        with:
          python-version: 3.8
      - name: Install wpiformat
        run: pip3 install wpiformat==2024.32
      - name: Run
        run: wpiformat
      - name: Check output
        run: git --no-pager diff --exit-code HEAD