Aller au contenu

Linters & Formatters

Automatiser le style de code et détecter les problèmes avant qu'ils n'atteignent la production.


Formatter vs Linter

Deux familles d'outils complémentaires, souvent confondues :

  • Formatter = correcteur orthographique automatique — il reformate sans poser de question.
  • Linter = relecture par un collègue senior — il signale les problèmes, et parfois les corrige.
Formatter Linter
Action Reformate automatiquement Signale (et parfois corrige)
Scope Style uniquement Bugs, pratiques, complexité
Subjectivité Zéro (règles fixes) Configurable
Exemples Prettier, Black ESLint, Ruff

Pourquoi les deux ?

Un formatter garantit un style uniforme sans débat. Un linter détecte les bugs potentiels, les imports inutilisés, la complexité excessive. Les deux ensemble forment un filet de sécurité complet.


JavaScript / TypeScript

npm install --save-dev eslint prettier eslint-config-prettier
npm install --save-dev eslint prettier eslint-config-prettier

eslint-config-prettier

Ce paquet désactive les règles ESLint qui entrent en conflit avec Prettier. Indispensable pour éviter les guerres entre les deux outils.

Créez .eslintrc.json à la racine du projet :

.eslintrc.json
{
  "env": {
    "browser": true,
    "node": true,
    "es2021": true
  },
  "extends": [
    "eslint:recommended",  // (1)!
    "prettier"             // (2)!
  ],
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "rules": {
    "no-unused-vars": "warn",       // (3)!
    "no-console": "warn",
    "eqeqeq": "error",             // (4)!
    "no-var": "error"
  }
}
  1. Règles recommandées par l'équipe ESLint — bon point de départ.
  2. Désactive les règles de formatage gérées par Prettier.
  3. "warn" au lieu de "error" — signale sans bloquer le build.
  4. Interdit == au profit de === — évite les conversions implicites.

Créez .prettierrc :

.prettierrc
{
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "es5",
  "printWidth": 80
}

Ajoutez ces scripts à votre package.json :

package.json (extrait)
{
  "scripts": {
    "lint": "eslint .",
    "format": "prettier --write .",
    "check": "prettier --check . && eslint ."
  }
}

Avant — code mal formaté avec des problèmes :

app.js (avant)
const   x=1
var y = 2
if(x==y){
console.log("égaux")
}

Après npm run format puis npm run lint --fix :

app.js (après)
const x = 1;
const y = 2; // (1)!
if (x === y) { // (2)!
  console.log('égaux');
}
  1. var remplacé par const (règle no-var).
  2. == remplacé par === (règle eqeqeq).
Commande Rôle
npm run lint Analyse ESLint (signale les erreurs)
npx eslint --fix . Corrige automatiquement ce qui peut l'être
npm run format Reformate tout avec Prettier
npm run check Vérifie formatage + lint (idéal pour la CI)

Python

pip install ruff black
pip install ruff black

Versions épinglées

En production, épinglez les versions dans requirements-dev.txt :

requirements-dev.txt
ruff==0.8.6
black==24.10.0

Installez ensuite avec pip install -r requirements-dev.txt.

Tout se configuré dans pyproject.toml :

pyproject.toml
[tool.ruff]
line-length = 88            # (1)!
target-version = "py311"

[tool.ruff.lint]
select = [
    "E",    # pycodestyle errors
    "W",    # pycodestyle warnings
    "F",    # pyflakes
    "I",    # isort (tri des imports)
    "B",    # flake8-bugbear
    "C4",   # flake8-comprehensions
    "UP",   # pyupgrade
]
ignore = ["E501"]           # (2)!

[tool.black]
line-length = 88
target-version = ["py311"]
  1. 88 caractères — la valeur par défaut de Black, Ruff s'y aligne.
  2. La longueur de ligne est gérée par Black, pas besoin que Ruff la signale aussi.

Avant — code Python avec des problèmes :

app.py (avant)
import os, sys
import json
import os

def calculer(x,y):
    result=x+y
    unused_var = 42
    return(result)

Après black . puis ruff check --fix . :

app.py (après)
import json
import sys  # (1)!


def calculer(x, y):
    result = x + y
    return result  # (2)!
  1. Import dupliqué os supprimé, imports triés par isort.
  2. Variable inutilisée unused_var supprimée, parenthèses inutiles retirées.
Commande Rôle
ruff check . Analyse Ruff (signale les erreurs)
ruff check --fix . Corrige automatiquement
black . Reformate tout avec Black
black --check . Vérifie le formatage sans modifier (CI)

Pre-commit hooks

Les hooks pre-commit exécutent automatiquement les linters et formatters à chaque git commit. Plus besoin d'y penser — si le code ne passe pas, le commit est refusé.

Installation

pip install pre-commit
pip install pre-commit

Configuration

Créez .pre-commit-config.yaml à la racine du projet :

.pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: black
        name: black
        entry: black
        language: system
        types: [python]
      - id: ruff
        name: ruff
        entry: ruff check --fix
        language: system
        types: [python]
      - id: prettier
        name: prettier
        entry: prettier --write
        language: system
        types_or: [javascript, typescript, json, yaml, markdown]
      - id: eslint
        name: eslint
        entry: eslint --fix
        language: system
        types_or: [javascript, typescript]

Activation

pre-commit install

À partir de maintenant, chaque git commit déclenche automatiquement les vérifications. Si un fichier est reformaté, le commit est annulé — il suffit de git add les modifications et de recommiter.

Environnement airgap (sans accès Internet)

Utilisez repo: local (comme dans l'exemple ci-dessus) au lieu de repos distants comme https://github.com/pre-commit/mirrors-prettier. Les hooks local utilisent les outils déjà installés sur votre machine — aucun téléchargement nécessaire.

Démonstration

$ git commit -m "feat: add new feature"
black....................................................................Passed
ruff.....................................................................Passed
prettier.................................................................Passed
eslint...................................................................Passed
[main abc1234] feat: add new feature

Récapitulatif des commandes

Outil Commande Rôle
Prettier prettier --write . Reformater JS/TS/JSON/YAML/MD
Prettier prettier --check . Vérifier le formatage (CI)
ESLint eslint . Analyser le code JS/TS
ESLint eslint --fix . Corriger automatiquement
Black black . Reformater le code Python
Black black --check . Vérifier le formatage (CI)
Ruff ruff check . Analyser le code Python
Ruff ruff check --fix . Corriger automatiquement
pre-commit pre-commit install Activer les hooks
pre-commit pre-commit run --all-files Exécuter sur tous les fichiers