Un graphe de code typé
Une affirmation sur la structure d'un code doit être calculée.
Muundo analyse un arbre de sources avec tree-sitter et rend ce qui s'y trouve vraiment : les entités, les appels entre elles, les métriques par entité, les dépendances et l'accessibilité. Sans serveur de langage, sans compilation, sans réseau — il lit les fichiers.
Apache‑2.0 · treize grammaires pour douze langages · rien ne quitte la machine
Ce que c'est
Un modèle répond. Un graphe montre.
Demandez à un modèle si une fonction est récursive : il vous dira quelque chose. Demandez-le au graphe : il désigne l'arête.
Cette différence est toute la raison d'être de l'outil. Un constat que l'on va rattacher à un article d'une norme, et montrer à quelqu'un dont l'audit est le métier, ne peut pas reposer sur une phrase plausible. Il doit reposer sur quelque chose qu'un tiers recalcule à partir des mêmes fichiers pour obtenir la même réponse.
Muundo calcule donc. Il analyse chaque fichier avec tree-sitter — l'analyseur qu'un éditeur utilise pour la coloration syntaxique, ce qui veut dire aucun système de construction, aucune résolution de dépendances et aucune exécution de votre code — et transforme les arbres en un rapport que vous pouvez lire, comparer et conserver.
Muundo veut dire structure en swahili.
Les entités et les appels entre elles
Chaque fonction, méthode, classe et module que l'arbre déclare, avec son fichier et sa ligne, et une arête pour chaque appel qui se résout.
Des métriques par entité
Complexité cyclomatique, nombre d'appelants et d'appelés, profondeur d'imbrication — calculés depuis l'arbre, non estimés depuis un nombre de lignes.
L'accessibilité
Quelles entités sont atteignables depuis les points d'entrée, et lesquelles ne le sont pas. Le code mort est une question de graphe, et c'est comme telle qu'elle est traitée.
Ce qui a été lu
L'empreinte de chaque fichier que l'analyse a lu. verify relit l'arbre et dit si elle correspond toujours.
Langages
Treize grammaires pour douze langages.
Ada et C ne sont pas décoratifs. C'est dans ces langages qu'est écrit le code de l'avionique, du ferroviaire et des dispositifs médicaux, et ce sont d'ordinaire ceux qu'un outil d'analyse laisse de côté.
Treize grammaires, douze langages : typescript et tsx sont deux grammaires tree-sitter pour un seul langage, d'où l'écart entre les deux nombres. Une compilation peut en embarquer moins ; muundo info affiche celles que la vôtre accepte.
Chaque champ du rapport est rempli par tout extracteur dont le langage possède la construction. Cette règle est vérifiée par un jeu d'essai qui écrit une fonction dans chaque langage et lit ce qui revient — parce que, vu du dehors, un champ non rempli et une construction absente se ressemblent : les deux sont vides.
L'utiliser
Une bibliothèque, une commande et un serveur HTTP.
Il n'est pas encore publié sur un dépôt de paquets : vous le compilez. Une chaîne d'outils Rust stable suffit pour la commande ; le module Python demande maturin.
Depuis le terminal
cargo build --release --workspace
./target/release/muundo analyze --root ./src > report.json
./target/release/muundo verify --report report.json --root ./src
analyze, metrics, fragility, hotspots, verify et info.
Depuis Python
report = muundo.MuundoAnalyzer(
"./src", ["c", "cpp"]
).analyze()
for edge in report.call_edges:
print(edge.caller, "->", edge.callee)
L'analyse syntaxique coûte cher : elle a lieu une fois par analyseur et reste en cache pour la durée de vie de l'instance. Construisez-en un nouveau pour repartir de zéro.
Complétude
Lisez ces deux champs avant de citer un chiffre.
Un graphe qui écarte en silence ce sur quoi il a échoué produit des nombres assurés portant sur un sous-ensemble, sans que rien ne dise au lecteur lequel.
Un rapport n'est complet que si skipped_files et partial_analysis sont tous deux vides, et ils ne veulent pas dire la même chose. Le premier liste des fichiers entiers qui n'ont jamais été lus. Le second liste des étapes qui se sont arrêtées en chemin sur des fichiers qui, eux, l'ont été. L'un ou l'autre suffit à faire de chaque nombre du rapport un nombre portant sur un sous-ensemble.
if not report.is_complete:
print("not read:", report.skipped_files)
print("stopped early:", report.partial_analysis)
Rien n'est écarté en silence et rien n'est arrondi. C'est l'affirmation qui mérite d'être vérifiée, et c'est celle dont dépend tout le reste du rapport.
Limites
Ce qu'il ne fera pas.
Chacun de ces points a l'air d'une fonction manquante et se trouve être un refus assumé. Faire mieux supposerait soit d'exécuter votre code, soit de construire un moteur sémantique complet pour chaque langage, et l'un comme l'autre est le métier de quelqu'un d'autre.
Il n'exécute pas votre code
Tout vient de l'arbre syntaxique. Un appel qui ne passe que par la réflexion, un import dynamique ou une répartition par chaîne de caractères n'est pas une arête, parce que statiquement il n'en est pas une.
Les imports se résolvent statiquement
Un chemin réécrit par un système de construction, un alias défini dans la configuration d'un empaqueteur, une réexportation avec joker — le résolveur dit ce qu'il peut prouver depuis les fichiers, et s'arrête là.
Les surcharges restent fusionnées
Deux méthodes portant un même nom forment une seule entité. Les séparer demande de résoudre les types, et un consommateur qui dispose des types peut les séparer lui-même.
Il ne déclare rien comme sûr
Il n'existe aucun indicateur « cette fonction assainit ». Qu'une fonction rende une valeur sûre dépend de sa destination, que le graphe ignore.
Le raisonnement derrière chacun, et ceux qui ont été essayés puis retirés, est consigné dans les décisions de conception.
Licence
Apache-2.0. Il n'y a rien à acheter.
Aucune clé de licence, aucun palier, aucune télémétrie, aucun compte. Lisez-le, exécutez-le, dérivez-le, embarquez-le dans quelque chose que vous vendez.
Les questions et les défauts vont au suivi des tickets : c'est là que les réponses sont écrites et restent lisibles. Muundo est l'un des outils construits ici ; les autres sont nommés ci-dessous, et certains sont vendus.