Recherche/Corriger et tester un générateur d’adaptateurs de bibliothèques natives pour de nombreux langages

Corriger et tester un générateur d’adaptateurs de bibliothèques natives pour de nombreux langages

À utiliser pour modifier un outil qui génère des adaptateurs de bibliothèques natives pour de nombreux langages. Remonte à l’étape où naît le bug, lance des tests à la bonne échelle, ajoute des tests de régression et met à jour le journal des modifications.

Pour utiliser ces règles d'IA
## Lire d’abord les guides par tâche et corriger les entrées, pas les fichiers générés ### Commencer par les consignes propres à la tâche Avant de modifier du code ou d’exécuter des commandes spécialisées, repérez les guides courts du dépôt consacrés à chaque type de tâche. Lisez celui qui correspond au travail à réaliser au lieu de reconstituer la procédure à partir d’une vue d’ensemble. Ces guides couvrent généralement : - l’exécution de la suite complète, de la suite d’un langage cible ou d’un seul cas de test ; - le débogage du compilateur, l’inspection des arbres syntaxiques et le suivi des défauts de mémoire ; - la modification du manuel utilisateur et la validation de sa structure ; - le formatage du code source, les commentaires, les conventions de contribution et les messages de validation ; - la reproduction des échecs qui ne surviennent que dans l’intégration continue. Considérez ces guides ciblés comme canoniques lorsqu’ils fournissent des commandes, des options ou des conventions précises. Si des alias de découverte ou des liens symboliques reflètent le même guide dans plusieurs emplacements propres à différents outils, conservez une source de vérité unique et vérifiez que les liens se matérialisent correctement sur la plateforme du contributeur. ### Comprendre le système avant de le modifier Le dépôt met en œuvre un générateur de type compilateur. Il lit des déclarations natives et des descriptions d’interface, puis produit des adaptateurs qui rendent des bibliothèques natives accessibles à de nombreux langages cibles. Ce modèle entraîne trois conséquences pratiques : - les fichiers générés sont des sorties, pas l’emplacement principal où corriger le comportement ; - les entrées d’interface partagées doivent contenir le comportement commun aux langages, tandis que les vérifications d’exécution propres à une cible doivent se trouver dans le répertoire de tests correspondant ; - une modification de l’analyse syntaxique, de la résolution des types, de la propriété des objets ou de la production des adaptateurs peut toucher plusieurs moteurs cibles, même si le symptôme signalé n’apparaît que dans un seul. Fondez-vous sur les guides, les fichiers de construction et les tests du dépôt. Ne déduisez pas une procédure uniquement de noms de répertoires familiers ou de conventions employées dans un autre projet. ## Construire avec le système de build de la CI et choisir le plus petit test utile ### Construire à partir de la bonne forme de source Utilisez le système de construction principal employé par l’intégration continue. Une copie issue du contrôle de version peut nécessiter une étape d’amorçage pour générer les fichiers de configuration, alors qu’une archive de publication peut déjà les contenir. La séquence normale consiste à amorcer si nécessaire, configurer, puis construire. Conservez les options de configuration prises en charge, telles que le préfixe d’installation et les réglages des dépendances facultatives. Un système de construction secondaire peut exister, mais ne le substituez pas silencieusement au système principal lorsque vous diagnostiquez une défaillance de la chaîne principale. Les tests et les exemples peuvent appeler un lanceur prévu pour l’arborescence non installée, qui oriente l’environnement d’exécution vers le répertoire de la bibliothèque fraîchement construite ; utilisez ce lanceur afin que les tests portent sur la copie de travail actuelle plutôt que sur une version installée. Si un composant auxiliaire de mise en cache de la compilation appartient au graphe de construction et de test par défaut, incluez-le, sauf si le guide canonique restreint explicitement l’exécution. ### Choisir le test pertinent le plus restreint Adaptez la commande à la portée de la modification : - exécutez un seul test d’adaptateur généré pendant l’itération sur un comportement localisé ; - exécutez la suite complète du langage cible concerné lorsque le comportement de son moteur change ; - exécutez les suites partagées lorsque l’analyseur syntaxique, le système de types, la propriété des objets ou la logique commune de production change ; - n’utilisez l’exécution parallèle que si le dépôt la prend en charge ; - pour une exécution large, utilisez un mode qui poursuit après les erreurs lorsque recueillir tous les échecs est plus utile que s’arrêter au premier. Les cibles de test codent souvent la forme de la source, par exemple le mode langage natif, le mode orienté objet ou le mode multmodule. Utilisez le suffixe correspondant au cas et exécutez la cible de nettoyage associée avant de conclure qu’un artefact généré obsolète constitue une nouvelle défaillance. ### Vérifier le même parcours que l’automatisation Lorsqu’une défaillance ne survient que dans l’intégration continue, reproduisez l’environnement de l’exécutant avec l’image de conteneur maintenue par le dépôt et les véritables scripts d’installation. Préférez l’outil qui reproduit l’exécutant hébergé à un environnement improvisé. Confirmez les mêmes versions de dépendances, variables d’environnement, mode de construction et cible de test avant d’attribuer l’écart au code source. Une correction de défaut ou une fonctionnalité doit normalement comporter un test de régression. Ne déclarez pas une modification vérifiée au seul motif que le compilateur s’est construit correctement ; la production des adaptateurs, la compilation du code généré et le comportement à l’exécution dans le langage cible sont des points de contrôle distincts. ## Trouver l’étape de la chaîne où naît un bug et ne jamais réentrer dans l’analyseur ### Suivre les étapes de traitement Suivez le comportement dans l’ordre de la chaîne : 1. Le préprocesseur développe les entrées d’interface et les directives conditionnelles. 2. L’analyseur lexical transforme le texte d’entrée en unités lexicales. 3. L’analyseur syntaxique applique la grammaire et crée un arbre de nœuds porteurs d’attributs. 4. Le système de types résout les noms, les équivalences, les modèles et les conversions. 5. Les passes sur l’arbre ajoutent ou normalisent les informations nécessaires aux étapes suivantes. 6. Un moteur propre à un langage cible parcourt l’arbre et produit le code des adaptateurs. Repérez l’étape la plus précoce où l’état réel s’écarte de l’état attendu. Un adaptateur mal formé ne prouve pas que le moteur cible est en cause ; celui-ci peut produire fidèlement un nœud syntaxique, un type, un indicateur de propriété ou une règle de conversion erronés créés plus tôt. ### Utiliser les abstractions fondamentales du modèle Les nœuds syntaxiques se comportent comme des objets clé-valeur et sont parcourus par des passes partagées et des moteurs de langage. Inspectez les attributs au moment de leur création, puis à nouveau au moment de leur consommation. Les tables de conversion de types déterminent comment les valeurs natives franchissent la frontière vers les langages cibles ; lorsque la conversion est incorrecte, vérifiez la priorité de sélection et l’équivalence des types avant de modifier le texte produit. L’instanciation des modèles repose sur le même mécanisme d’équivalence des types ; isolez donc la correspondance des spécialisations du formatage des adaptateurs. Examinez l’analyse partagée de la propriété et de l’allocation avant d’ajouter des contournements de durée de vie propres à un moteur. ### Respecter les limites d’un analyseur syntaxique non réentrant Considérez l’analyseur syntaxique comme non réentrant tant que l’implémentation n’a pas prouvé le contraire. Les points d’entrée qui l’encapsulent peuvent écraser son état global, notamment la position d’entrée courante, les valeurs sémantiques et le symbole d’anticipation. Ne les appelez jamais récursivement depuis une action de grammaire. Lorsqu’une règle de grammaire doit construire une nouvelle liste de paramètres ou une sous-syntaxe apparentée, réutilisez les productions existantes de la grammaire au sein de l’analyse en cours au lieu de lancer une analyse imbriquée. Validez la modification avec un cas de régression correspondant à la norme de langage la plus ancienne qui introduit la construction grammaticale. ### Utiliser les mécanismes de débogage pris en charge Utilisez les options de débogage documentées du dépôt, les représentations textuelles ou structurées de l’arbre, les assistants du débogueur, les enveloppes d’exécution, les variables de sélection des fonctionnalités et les diagnostics des réserves de mémoire. Pour une défaillance propre à l’automatisation, reproduisez l’environnement automatisé avant d’intensifier l’instrumentation. Gardez les modifications de diagnostic temporaires et ne transformez pas un contournement local en comportement de production sans test en échec qui en démontre la nécessité. ## Placer chaque test de régression dans l’entrée partagée ou dans le script du langage ### Placer le comportement au bon niveau Un test possède normalement une entrée d’interface partagée qui pilote la génération et, éventuellement, un script d’exécution dans le langage cible qui exerce l’adaptateur généré. Placez dans l’entrée partagée les exigences de grammaire et d’adaptation indépendantes du langage. Placez dans le script d’exécution correspondant la syntaxe propre au langage cible, les vérifications à l’exécution et les cas limites propres à ce langage. Enregistrez les nouveaux cas dans le groupe de la suite qui correspond à leur portée réelle. Un préfixe de nom de test lié à une norme de langage doit représenter la norme la plus ancienne qui a introduit la construction grammaticale, et non une norme plus récente employée par un exemple pratique. Déterminez la construction isolément, puis placez le test dans le groupe de norme correspondant. ### Rendre les échecs observables Utilisez des assistants de vérification qui restent actifs dans les modes d’exécution optimisés. Si un langage cible peut retirer son instruction de vérification intégrée pendant l’optimisation, ne vous appuyez jamais sur cette instruction pour couvrir une régression. Employez des assistants explicites pour l’égalité, les conditions et les exceptions attendues, qui affichent des valeurs utiles en cas d’échec. Gardez les commentaires de test brefs et non évidents. Expliquez un contournement du compilateur ou un piège sémantique en une seule ligne concise ; ne racontez pas ce que le code exprime déjà. Un test de régression doit échouer avant la correction, réussir après celle-ci et exercer le comportement public plutôt qu’un assistant interne accessoire. ### Valider l’impact partagé Pour les modifications de l’analyseur syntaxique ou du système de types commun, testez davantage que le moteur initialement en échec lorsque le parcours concerné est partagé. Pour un comportement propre à un moteur, n’élargissez pas l’exécution sans preuve. Nettoyez les fichiers générés entre des configurations de test sensiblement différentes et distinguez, dans le rapport, l’échec de génération, l’échec de compilation native et l’échec à l’exécution. ## Garder les commits sans changements étrangers et noter chaque changement visible dans le journal ### Respecter les conventions du code source et des commentaires Utilisez les contrôles de formatage et le formateur du dépôt au lieu de normaliser manuellement du code sans rapport avec la tâche. Respectez le style établi des commentaires du langage natif, les règles de citation des unités lexicales, la largeur de ligne et les conventions d’en-tête de fonction. Les fichiers de grammaire peuvent imposer des règles plus strictes au nouveau code ; suivez-les et évitez toute refactorisation sans rapport lors de la modification d’un analyseur syntaxique de production. Avant la validation, examinez le diff pour repérer les fichiers générés, les remplacements globaux accidentels et les modifications extérieures au sous-système visé. Le texte de validation doit être simple, concis et exact. N’attribuez pas à un outil automatisé la qualité de coauteur. Si le projet exige de signaler une assistance automatisée importante, utilisez la mention d’assistance approuvée sans identité de messagerie. ### Consigner les modifications visibles par l’utilisateur Toute correction de défaut, nouvelle fonctionnalité, modification de comportement, modification d’avertissement ou dépréciation visible par l’utilisateur doit comporter une entrée dans le journal des modifications courant. Décrivez ce que l’utilisateur observe, et non les noms d’assistants internes ni les détails de refactorisation. Respectez le format établi du dépôt pour la date et le numéro de sujet, placez les nouvelles entrées dans l’ordre attendu et signalez explicitement les risques de compatibilité. Les modifications purement internes sans effet observable ne nécessitent pas d’entrée destinée à l’utilisateur. ### Maintenir la documentation destinée aux développeurs et aux utilisateurs Lorsque vous modifiez le manuel, conservez des ancres de titre stables et descriptives plutôt que des ancres numériques générées. Utilisez les classes de contenu documentées pour le code, les exemples en langage cible, les sessions d’interpréteur de commandes et les diagrammes. Faites pointer les liens entre documents vers des cibles stables, puis exécutez le générateur de table des matières et les contrôles de documentation. La documentation destinée aux développeurs doit expliquer le modèle d’objets interne, les attributs de l’arbre, le système de types et la procédure d’extension. La documentation destinée aux utilisateurs doit se concentrer sur la syntaxe prise en charge et le comportement observable. Vérifiez à la fois la structure rendue et les cibles des liens ; la réussite d’une modification du source ne prouve pas à elle seule que le manuel reste navigable.