Utilisation d’un formateur de code

Les formateurs de code existent pour s’assurer que le style de code écrit est cohérent dans l’ensemble du code de base. Ceci est utilisé dans de nombreux grands projets; d’Android à OpenCV. Les équipes peuvent souhaiter ajouter un formateur dans tout leur code robot pour s’assurer que le code de base maintient la lisibilité et la cohérence tout le long.

Pour cet article, nous mettons l’emphase sur l’utilisation de Spotless pour les équipes Java et wpiformat pour les équipes C++.

Spotless

Configuration

Des modifications build.gradle nécessaires sont requises pour que Spotless soit fonctionnel. Dans le bloc plugins {} de votre build.gradle, ajoutez le plugin Spotless de sorte qu’il semble similaire à celui apparaissant ci-dessous.

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

Ensuite, assurez-vous d’ajouter un bloc spotless {} nécessaire pour configurer correctement Spotless. Celui-ci peut simplement être placé à la fin de votre fichier 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()
   }
}

Exécution de Spotless

Spotless peut être exécuté en utilisant la commande ./gradlew spotlessApply qui appliquera toutes les options de mise en forme. Vous pouvez également spécifier une tâche spécifique en ajoutant simplement le nom du formateur. Un exemple est ./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

Explication des options

Chaque section format met en évidence le formatage des fichiers personnalisés dans le projet. Les java et groovyGradle sont nativement soutenus par Spotless, de sorte qu’ils sont définis différemment.

En décomposant ceci, on peut le diviser en plusieurs parties.

  • Mise en forme de Java

  • Mise en forme des fichiers Gradle

  • Mise en forme des fichiers XML

  • Mise en forme de fichiers divers

Ils sont tous similaires, à l’exception de quelques petites différences qui seront expliquées. L’exemple ci-dessous mettra l’emphase sur le bloc java {}

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

Expliquons la signification de chacune des options.

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

L’exemple ci-dessus indique à Spotless où se trouvent nos classes Java et d’exclure le dossier build. Les options restantes sont assez explicites.

  • toggleOffOn() ajoute à Spotless la possibilité d’ignorer des parties spécifiques d’un projet. L’utilisation ressemble à ce qui suit

// format:off

public void myWeirdFunction() {

}

// format:on
  • googleJavaFormat() indique à Spotless de mettre en forme selon le Guide de Style de Google

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

  • trimTrailingWhitespace() supprimera tout espace blanc supplémentaire à la fin de vos lignes

  • endWithNewline() ajoutera un caractère newline à la fin de vos classes

Dans le bloc groovyGradle, il existe une option greclipse. C’est le formateur que Spotless utilise pour mettre en forme les fichiers gradle.

Additionnellement, il existe une option eclipseWtp dans le bloc xml. Il s’agit de « Gradle Web Tools Platform » et est le formateur servant à mettre en forme les fichiers xml. Les équipes qui n’utilisent pas de fichiers XML peuvent choisir de ne pas inclure cette configuration.

Note

Une liste complète des configurations est disponible dans le fichier Spotless README

Problèmes avec les fins de ligne

Spotless tentera d’appliquer des fins de ligne par OS, ce qui signifie que les commandes Git diffs changeront constamment si deux utilisateurs sont sur des OS différents (Unix vs Windows). Il est recommandé aux équipes qui contribuent au même dépôt à partir de plusieurs OS d’utiliser un fichier .gitattributes. Ce qui suit devrait suffire pour la manipulation des fins de ligne.

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

wpiformat

Exigences

Vous pouvez installer wpiformat en tapant pip3 install wpiformat dans un terminal ou une invite de commande.

Utilisation

wpiformat peut être couru en tapant wpiformat dans une console. La mise en forme sera effectuée à l’aide de clang-format. Trois fichiers de configuration sont nécessaires (.clang-format, .styleguide, .styleguide-license). Ceux-ci doivent être présents dans la racine du projet.

Un exemple de guide de style est montré ci-dessous:

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

cppSrcFileInclude {
   \.cpp$
}

modifiableFileExclude {
   gradle/
}

Note

Les équipes peuvent adapter .styleguide et .styleguide-license comme elles le souhaitent. Il est important que ceux-ci ne sont pas supprimés, car ils sont requis pour exécuter 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