You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
PHP : les constantes de classe typées disparaissent du graphe #17
Pilote du 2026-10-11 sur projet A (PHP 8.4) et projet B (PHP 8.5). La grammaire tree-sitter-php (0.24.1 embarquée, 0.25.1 dernière) ne reconnaît pas les constantes de classe typées (PHP 8.3) : public const string X = '...';.
Toute constante typée est absente du graphe : 427 fichiers sur 3 219 dans projet A, 157 sur 517 dans projet B.
Une classe qui ne contient que des constantes typées disparaît entièrement : la déclaration de classe devient un nœud ERROR (cas réel : src/Http/UserAgents.php de projet A).
Test isolé : la même classe sans le type ne produit aucune erreur. La PR amont tree-sitter-php#214 (« PHP 8.3 support ») couvre la lecture dynamique de constante, pas le type. Aucune issue ouverte en amont.
Outcome attendu
Une constante typée est un nœud du graphe, rattaché à sa classe, quel que soit le reste du contenu de la classe.
Acceptance criteria
Une classe ne contenant que des constantes typées apparaît dans le graphe, avec ses constantes
graphify extract sur projet A n'émet plus d'avertissement « syntax error » pour UserAgents.php
Test de régression avec une fixture PHP qui échoue avant le correctif
La grammaire corrigée est figée par commit (pas de branche flottante)
Hints
Cause : grammar.js de tree-sitter/tree-sitter-php, règle const_declaration sans type optionnel
Correctif dans un fork de la grammaire, référencé par pyproject.toml, puis proposé en amont
graphify/extractors/engine.py:8693 : enregistrement de parse_errors
Hors scope
Autres syntaxes PHP 8.4 / 8.5 non vérifiées (property hooks, visibilité asymétrique) : issue séparée si constatées
Le diagnostic initial est à corriger, constaté par test isolé (tree-sitter-php 0.24.1) :
Affirmation de l'issue
Constat
La grammaire ne connaît pas le type des constantes
Faux : supporté depuis tree-sitter/tree-sitter-php#205 (2024). public const string X, ?string, union, classe, enum, interface, trait : 0 erreur
Toute constante typée est absente du graphe
Vrai, mais aussi pour les non typées : Graphify ne crée pas de nœud de constante PHP, un accès Foo::BAR devient une arête references_constant vers la classe. Choix de conception, hors de cette issue
427 et 157 fichiers touchés
Ce sont les fichiers qui contiennent une constante typée, pas ceux en erreur
Vrai défaut : une constante de classe dont le nom est un mot réservé (DEFAULT, PRIVATE, CLASS, NEW...). 61 mots cassent quand la constante est typée, 7 même sans type (VOID, TRUE...). Selon la récupération d'erreur, la classe entière devient un nœud ERROR et disparaît du graphe. Projet A : 2 fichiers en erreur sur 2 943, dont une classe perdue. Projet B : 0 sur 476.
Amont : tree-sitter/tree-sitter-php#295 (issue) et Graphify-Labs#307 (PR ouverte le 2026-10-08, CI verte, en attente de relecture) corrigent exactement ce cas. Pas de correctif maison ni de PR amont en doublon.
Une classe PHP dont les constantes portent un nom de mot réservé (DEFAULT, PRIVATE, CLASS, VOID...), typées ou non, s'analyse sans erreur : la classe reste dans le graphe, avec ses arêtes contains, imports et references_constant.
uv.lock : seulement les deux blocs tree-sitter-php.
tests/test_php_keyword_constant_names.py : 7 déclarations à nom réservé sans parse_errors, et une classe ne contenant que des constantes qui garde son nœud et son arête references_constant.
Fork de la grammaire : test/corpus/bugs.txt, cas « Reserved keywords as typed class constant names » (final, optionnel, union, type nommé ; classe, interface, enum).
Commit figé par référence directe PEP 508 plutôt que [tool.uv.sources] : l'installation quotidienne passe par pip install "graphifyy @ git+...", et pip ignore tool.uv.sources. Vérifié dans un venv propre : pip construit le binding depuis la racine du dépôt, sans sous-répertoire.
Alternative écartée : attendre la publication de 0.25.2 sur PyPI, sans date connue.
Graphify ne crée pas de nœud de constante PHP, typée ou non. L'objectif « de 0 à toutes les constantes typées » ne pouvait donc pas être atteint par la grammaire.
Selon le contenu des chaînes (;, parenthèses), la récupération d'erreur avale soit la constante, soit toute la classe. La fixture reproduit le second cas.
Les 2 fichiers en erreur sur le projet A étaient l'un « 0 symbole » (avertissement affiché), l'autre silencieux parce que le seuil d'avertissement n'a rien vu disparaître.
Test de régression : 8 échecs avec tree-sitter-php 0.24.1, 8 réussites avec le commit figé
Suite complète : 7536 passed, 14 skipped, 0 failed (référence main : 7528 + 8 nouveaux)
ruff : All checks passed ; pyright sur le nouveau fichier : 0 erreur
Grammaire, tree-sitter test (CLI 0.27.0) : 157/157 ; le nouveau cas échoue sur le master amont
Mesure, avant puis après, différentiel complet des nœuds et des arêtes : projet A, 2 fichiers en erreur de syntaxe deviennent 0 ; la classe disparue revient (1 nœud, contains + 8 imports qui visaient un nœud sans source), une position de constructeur corrigée, rien d'autre ne change. Projet B : 0 fichier en erreur avant comme après, graphe identique.
Activity
github-actions commentedon Oct 11, 2026
Thanks for opening this issue, @alexwrite. A maintainer will take a look soon.
If you would like to discuss it in real time, come say hi on our Discord server. For longer-form questions and ideas there is also GitHub Discussions.
To help us triage, please make sure the report includes what you expected, what actually happened, and the steps (and a small sample) to reproduce it.
alexwrite commentedon Oct 11, 2026
Prise en charge.
Le diagnostic initial est à corriger, constaté par test isolé (tree-sitter-php 0.24.1) :
public const string X,?string, union, classe, enum, interface, trait : 0 erreurFoo::BARdevient une arêtereferences_constantvers la classe. Choix de conception, hors de cette issueVrai défaut : une constante de classe dont le nom est un mot réservé (
DEFAULT,PRIVATE,CLASS,NEW...). 61 mots cassent quand la constante est typée, 7 même sans type (VOID,TRUE...). Selon la récupération d'erreur, la classe entière devient un nœudERRORet disparaît du graphe. Projet A : 2 fichiers en erreur sur 2 943, dont une classe perdue. Projet B : 0 sur 476.Amont : tree-sitter/tree-sitter-php#295 (issue) et Graphify-Labs#307 (PR ouverte le 2026-10-08, CI verte, en attente de relecture) corrigent exactement ce cas. Pas de correctif maison ni de PR amont en doublon.
Périmètre de fichiers visé :
pyproject.toml,uv.lock: tree-sitter-php figé sur un commit du forkalexwrite/tree-sitter-php(commits de Lack of NoneType handling in serve.py - causes AttributeError: 'NoneType' object has no attribute 'lower' Graphify-Labs/graphify#307, auteur conservé, plus un test de corpus)tests/test_php_keyword_constant_names.py: test de régressionalexwrite commentedon Oct 11, 2026
Fait
DEFAULT,PRIVATE,CLASS,VOID...), typées ou non, s'analyse sans erreur : la classe reste dans le graphe, avec ses arêtescontains,importsetreferences_constant.Comment
pyproject.toml:40:tree-sitter-phpfigé suralexwrite/tree-sitter-php@9678351(branchefix/keyword-constant-names= commits de fix: parse keyword identifiers in expressions and constants tree-sitter/tree-sitter-php#307, auteur conservé, plus un test de corpus).uv.lock: seulement les deux blocs tree-sitter-php.tests/test_php_keyword_constant_names.py: 7 déclarations à nom réservé sansparse_errors, et une classe ne contenant que des constantes qui garde son nœud et son arêtereferences_constant.test/corpus/bugs.txt, cas « Reserved keywords as typed class constant names » (final, optionnel, union, type nommé ; classe, interface, enum).Pourquoi ce choix
[tool.uv.sources]: l'installation quotidienne passe parpip install "graphifyy @ git+...", et pip ignoretool.uv.sources. Vérifié dans un venv propre : pip construit le binding depuis la racine du dépôt, sans sous-répertoire.Apprentissages
;, parenthèses), la récupération d'erreur avale soit la constante, soit toute la classe. La fixture reproduit le second cas.Faiblesses restantes
uv lock --checkéchoue, mais il échouait déjà surmain(dérive du verrou antérieure, sans lien avec ce lot).Foo::BARvers un autre fichier ne crée aucune arête siFoon'est pas aussi utilisé comme type dans le fichier appelant. Repéré en écrivant le test.Quality
main: 7528 + 8 nouveaux)tree-sitter test(CLI 0.27.0) : 157/157 ; le nouveau cas échoue sur le master amontcontains+ 8importsqui visaient un nœud sans source), une position de constructeur corrigée, rien d'autre ne change. Projet B : 0 fichier en erreur avant comme après, graphe identique.Merge fix/php-typed-class-constants (#17)