Blog 2 min de lecture

Détectez les noms obscurcis dans un projet C/C++

Share this article
Détectez les noms obscurcis dans un projet C/C++

Combien de fois êtes-vous tombé sur du code comme celui-ci ?

obfuscatednames

Dans certains cas, un tel code ne pose peut-être pas de problème majeur. Mais si les développeurs utilisent fréquemment cette pratique de codage, elle peut devenir coûteuse pour l'entreprise. Chaque nouvel arrivant qui doit déboguer le code ou ajouter une nouvelle fonctionnalité passera beaucoup de temps à essayer de comprendre la base de code existante.

Comment détecter ces noms obscurcis afin de les refactoriser ?

1. Avec clang-query et les AST Matchers

LibASTMatchers de Clang est une bibliothèque puissante pour faire correspondre des nœuds de l'AST et exécuter du code qui utilise les nœuds correspondants. Combinée avec LibTooling, LibASTMatchers aide à écrire des outils de transformation de code ou des outils de requête.

L'outil clang-query est fondé sur LibASTMatchers et offre un moyen simple d'interroger les nœuds AST d'un fichier source donné.

Par exemple, si nous voulons détecter les fonctions dont le nom ne contient qu'un seul caractère, nous pouvons exécuter cet AST matcher :

functionDecl(matchesName("^[a-zA-Z]$"))

Les AST Matchers offrent un moyen puissant d'interroger une base de code. En voici une définition rapide tirée de la documentation des AST Matchers.

Les AST matchers sont des prédicats sur les nœuds de l'AST. Les matchers sont créés en appelant des fonctions de création qui permettent de construire un arbre de matchers, où les matchers internes servent à rendre la correspondance plus spécifique.

Par exemple, pour créer un matcher qui correspond à toutes les déclarations de classes ou d'unions dans l'AST d'une unité de traduction, vous pouvez appeler recordDecl(). Pour affiner la correspondance, par exemple pour trouver toutes les déclarations de classes ou d'unions portant le nom «Foo», insérez un matcher hasName: l'appel recordDecl(hasName("Foo")) retourne un matcher qui correspond aux classes ou unions nommées «Foo», dans n'importe quel espace de noms. Par défaut, les matchers qui acceptent plusieurs matchers internes utilisent un allOf()implicite. Cela permet d'affiner encore la correspondance, par exemple pour trouver toutes les classes qui dérivent de «Bar» : recordDecl(hasName("Foo"), isDerivedFrom("Bar")).

2. Avec CppDepend et CQLinq

CppDepend est livré avec CQLinq, un langage de requête pour interroger votre base de code.

CQLinq définit plusieurs domaines prédéfinis que vous pouvez interroger, notamment : Types; Methods; Fields; Namespaces; Projects

Ces domaines énumèrent non seulement tous les éléments de code de la base de code interrogée, mais aussi tous les éléments de code tiers utilisés par la base de code (comme par exemple le type string et toutes les méthodes et tous les champs du type string utilisés par la base de code).

La syntaxe est aussi simple que :

from m in Methods where m.NbLinesOfCode > 30 select m

Et pour détecter les fonctions dont le nom ne contient qu'un seul caractère, nous pouvons exécuter la requête CQLinq suivante :

Untitled2

Conclusion :

Ne sous-estimez pas l'importance des noms de symboles ; de bons noms rendent une base de code plus facile à comprendre et à maintenir. Automatiser votre processus de build pour détecter les symboles mal nommés peut contribuer à améliorer la qualité globale de votre base de code.

Share this article