Abonnement à ma liste de contacts

Etoiles inactivesEtoiles inactivesEtoiles inactivesEtoiles inactivesEtoiles inactives
 

Introduction

Les commentaires sont souvent les grands oubliés du développement logiciel. Par manque de temps, par habitude ou simplement parce qu'ils sont perçus comme une contrainte supplémentaire, ils sont parfois réduits à quelques lignes laconiques... quand ils existent.

Pourtant, un commentaire peut devenir bien plus qu'une simple note destinée aux développeurs. En adoptant une structure précise, il peut servir de véritable source d'informations exploitables automatiquement par le code.

Le snippet PHP que nous allons découvrir illustre parfaitement cette idée. À partir d'un bloc de commentaires, il extrait des métadonnées telles que l'auteur, la date, la version ou encore la valeur de retour d'une fonction. Plus intéressant encore : les utilisateurs peuvent définir leurs propres annotations, à condition qu'elles commencent par le caractère @.

Avant d'entrer dans les détails, précisons ce que l'on entend ici par snippet. Ce terme désigne un petit morceau de code autonome, généralement conçu pour répondre à un besoin précis ou illustrer une technique particulière. Le code présenté dans cet article est donc un snippet dédié à l'analyse de commentaires structurés.

Noton aussi que le but ultime est de pouvoir générer nos dossiers de programmation à des fin de documentation. 

Le système que je vous propose ici intègre une souplesse particulièrement développée !

La problématique

Les commentaires suivent rarement un format homogène. Deux développeurs peuvent documenter la même fonctionnalité de façons très différentes :

/* Auteur : Pierre Version 1.0 */

ou :

/** 
* @author Pierre
* @version 1.0
*/

Cette absence de standardisation complique considérablement l'exploitation automatique des informations présentes dans les commentaires.

L'objectif du snippet est donc de résoudre plusieurs problèmes :

  • identifier automatiquement des informations importantes dans un commentaire ;
  • accepter des valeurs réparties sur plusieurs lignes ;
  • nettoyer le contenu récupéré afin qu'il soit facilement exploitable ;
  • permettre aux utilisateurs d'ajouter leurs propres annotations personnalisées sans modifier le code PHP.

Le fonctionnement

Le principe est simple : parcourir un bloc de commentaires, détecter toutes les lignes commençant par @ (et c'est en ce sens que je qualifie ce code de souple), puis construire un tableau associatif contenant les informations extraites.

Prenons cet exemple de code commenté avec ma normalisation :

/**
* @auteur : sebastien
* @date: 15 fev 202
* @action : ce code permet de trouver
* tout ce qui permet de trouver un
* élément dans une liste
* @version : 1.2
* @url : https://www.sebastien-lhuillier.com
* @return: Une retour
* qui peut être développé
* sur plusieurs
* lignes
*/

Le résultat obtenu sera un tableau semblable à celui-ci :

Array ( 
[auteur] => sebastien
[date] => 15 fev 2022
[action] => ce code permet de trouver tout ce qui permet de trouver un élément dans une liste
[version] => 1.2
[url] => http://www.aujourdhuianancy.com
[return] => Un retour qui peut lui aussi être développé sur plusieurs lignes
)

L'extraction avec preg_match_all

Tout repose sur cette expression :

preg_match_all( '/^\s*\*\s*@(\w+)\s*:?\s*(.*?)(?=^\s*\*\s*@\w+\s*:|^\s*\*+\/)/ms', $comment, $matches, PREG_SET_ORDER );

Décomposons-la.

Début d'une annotation

^\s*\*\s*@

Cette partie recherche :

  • ^ : le début d'une ligne ;
  • \s* : zéro ou plusieurs espaces ;
  • \* : le caractère * présent dans les commentaires PHP de type documentation ;
  • \s* : d'éventuels espaces ;
  • @ : le symbole annonçant une annotation.

Elle permet donc d'identifier les lignes comme :

 * @auteur : sebastien

Le nom de l'annotation

(\w+)

Le groupe capturant récupère le nom situé après @.

Ainsi @auteur produira : auteur

Le caractère \w représente les lettres, les chiffres et le caractère _.

Le séparateur facultatif

\s*:?\s*

Cette partie accepte différentes écritures :

  • @date: 15 fev
  • @date : 15 fev
  • @date 15 fev

Le caractère : est donc optionnel grâce à ?.

La valeur associée

(.*?)

Ce second groupe capturant récupère le contenu de l'annotation.

Le quantificateur *? est dit non gourmand (lazy). Il capture le minimum nécessaire jusqu'à rencontrer la condition définie plus loin dans l'expression. Cette subtilité est essentielle pour éviter qu'une annotation ne "dévore" les suivantes.

Le regard vers l'avant (lookahead)

(?=^\s*\*\s*@\w+\s*:|^\s*\*+\/)

Il s'agit d'un lookahead positif.

Il indique au moteur regex où s'arrêter, sans inclure cette partie dans le résultat.

Deux cas sont prévus :

^\s*\*\s*@\w+\s*:

Une nouvelle annotation commence.

Ou :

^\s*\*+\/

La fin du commentaire est atteinte. Grâce à ce mécanisme, les annotations multi-lignes sont correctement prises en charge.

Les modificateurs m et s

Enfin, deux options sont activées :

/ms
  • m (multiline) : les ancres ^ et $ fonctionnent sur chaque ligne ;
  • s (dotall) : le caractère . peut également correspondre aux retours à la ligne.

Sans ces modificateurs, l'expression régulière ne pourrait pas analyser correctement les blocs de commentaires.

Le nettoyage des valeurs

Une fois les données extraites, plusieurs traitements sont appliqués.

Suppression des astérisques

$value = preg_replace('/^\s*\*\s?/m', '', $value);

Transforme :

* qui peut être développé 
* sur plusieurs lignes

en :

qui peut être développé 
sur plusieurs lignes

Fusion des lignes

$value = preg_replace('/\s*\R\s*/', ' ', $value);

Le symbole \R représente n'importe quel type de retour à la ligne. Les différentes lignes sont regroupées en une seule phrase.

Réduction des espaces multiples

$value = preg_replace('/\s+/', ' ', $value);

Cette expression remplace toute succession d'espaces par un espace unique.

Enfin :

trim($value);

supprime les espaces inutiles en début et en fin de chaîne.

Des annotations entièrement personnalisables

L'un des aspects les plus intéressants de ce snippet réside dans sa souplesse.

Le code ne repose sur aucune liste prédéfinie d'annotations autorisées. Il récupère simplement le mot placé après @ :

@(\w+)

Cela signifie que chacun peut enrichir ses commentaires avec ses propres métadonnées.

Par exemple :

 * @priorite : élevée 
* @ticket : BUG-1254 *
* @responsable : Sébastien

seront automatiquement transformés en :

Array ( [priorite] => élevée [ticket] => BUG-1254 [responsable] => Sébastien )

Le snippet devient ainsi un véritable petit moteur d'extraction de métadonnées.

Il est important de noter que, dans sa forme actuelle, l'expression (\w+) n'accepte que les lettres, les chiffres et les caractères de soulignement. Une annotation comme :

@Une-autre-valeur

ne sera donc pas correctement interprétée à cause du tiret (-).

Pour prendre en charge ce type de nom, il faudrait adapter la regex :

@([\w-]+)

Les utilisateurs pourraient alors définir librement des clés telles que :

@nom-projet
@niveau-priorite
@date-livraison

Conclusion

Ce snippet démontre qu'un commentaire n'est pas forcément destiné à rester passif. Avec quelques expressions régulières bien pensées, il devient possible de transformer une simple documentation en source de données structurées.
L'approche présentée offre plusieurs avantages : elle améliore la lisibilité du code, facilite la maintenance et permet même d'automatiser certaines tâches grâce aux métadonnées extraites.
Et puisque chacun peut enrichir ses commentaires avec ses propres annotations commençant par @, il devient très simple d'adapter le système aux besoins spécifiques d'un projet.
Finalement, commenter son code ne revient plus seulement à expliquer ce qu'il fait : c'est aussi lui fournir des informations exploitables par la machine.

 

Vous retrouverez ici tous mes articles explicatifs de mes concepts, mes résultats d'analyses techniques m'ayant permi d'aboutir à un fonctionnement de mes applicatifs très fonctionnel

Rapport sondage marche

Voici le rapport statistique du sondage (auquel vous pouvez toujours répondre) que j'ai lancé sur le sujet