Aller au contenu

Code mort

Du code est mort quand on peut prouver qu'il n'a aucun effet sur le comportement du programme. repowarden distingue trois cas, qui ne se prouvent pas de la même façon :

Catégorie Définition Exemples Preuve repowarden
Inaccessible instructions qu'aucun chemin d'exécution n'atteint code après un return, if (false) analyse du flot de contrôle prouvé : bloquant
Inutilisé dans sa portée déclaration jamais référencée là où elle est visible import, variable locale, paramètre ou membre privé jamais lus analyse des références du fichier prouvé : bloquant
Non référencé dans le projet élément visible de l'extérieur que rien dans le projet n'utilise méthode publique, export, fichier, dépendance graphe d'appels depuis les points d'entrée candidat : avertissement

Les deux premiers cas sont certains : l'outil ne devine rien. Le troisième ne l'est pas toujours, car du code peut être appelé sans référence visible :

  • réflexion et injection (beans Spring, Class.forName, getattr) ;
  • appels depuis l'extérieur : API publique d'une bibliothèque, routes HTTP, tâches planifiées ;
  • sérialisation (Jackson, JPA), templates, configuration, autre langage.

C'est pourquoi un candidat n'est jamais bloquant par défaut : un humain confirme.

Seulement le nouveau code mort

repowarden ne signale que le code mort introduit par la PR (lignes ajoutées ou modifiées depuis la base). Un projet existant n'est pas noyé sous son historique : la dette ne grossit plus, et on la réduit à son rythme.

Outils, par langage

Langage Prouvé Candidats
Java (Maven, Gradle) PMD : imports, champs, méthodes et variables privés inutilisés — (Spring et réflexion rendent l'analyse trop incertaine)
TypeScript / JavaScript tsc : variables, paramètres, imports inutilisés, code inaccessible knip s'il est installé dans le projet : fichiers, exports, dépendances
Python ruff (F401, F811, F841), vulture à 100 % de confiance vulture en dessous de 100 % (le pourcentage est affiché)
Go staticcheck (U1000 : identifiants non exportés inutilisés) —

En CI, l'action installe PMD pour un projet Java (version et empreinte figées). Les autres outils sont ceux du projet. Un outil absent est signalé, sans faire échouer même le mode strict : la détection reste une aide.

Analyse partielle

Quand un langage a plusieurs outils (Python : ruff et vulture ; JavaScript : tsc et knip) et qu'il n'en est installé qu'un seul, l'analyse est partielle : repowarden le signale en nommant ce qui n'a pas été analysé (« Python : vulture absent : fonctions et classes inutilisées non analysées (pip install vulture) »). Et surtout, sans résultat sur ce qui a été analysé, le message de fin n'est plus le feu vert « Aucun nouveau code mort », mais « Aucun nouveau code mort dans ce qui a été analysé : analyse partielle, voir ci-dessus ». Aucun outil du langage n'est là : le message « code mort non analysé » reste, et compte aussi comme une analyse partielle.

Utilisation

  • CI : vérification deadcode, incluse par défaut dans l'action (checks:).
  • Poste : repowarden code-mort [base] analyse ta branche comme la CI : commits, modifications en cours et nouveaux fichiers. Base par défaut : origin/main ; sur une branche sans modification, rien n'est analysé.

Réglages

[repowarden]
    deadcode = block               # défaut : le prouvé bloque, les candidats avertissent
    # deadcode = warn              # rien ne bloque
    # deadcode = strict            # candidats bloquants aussi
    deadcodeIgnore = src/generated/* legacy/*   # chemins ignorés
    # skip = deadcode              # désactiver la vérification

Un faux positif ponctuel se déclare aussi avec l'annotation de l'outil (@SuppressWarnings("PMD.UnusedPrivateMethod"), # noqa: F401, // @ts-expect-error…), visible en revue.