Utilitaires de Diff sémantique [fermé]

105

J'essaie de trouver de bons exemples d'utilitaires de diff / fusion sémantique. Le paradigme traditionnel de la comparaison de fichiers de code source fonctionne en comparant des lignes et des personnages .. mais sont - il des services là - bas (pour une langue) qui considèrent en fait la structure de code lorsque l'on compare les fichiers?

Par exemple, les programmes de diff existants rapporteront "la différence trouvée au caractère 2 de la ligne 125. Le fichier x contient void, où le fichier y contient le booléen". Un outil spécialisé devrait être capable de rapporter "Le type de retour de la méthode doSomething () a changé de void en bool".

Je dirais que ce type d'informations sémantiques est en fait ce que l'utilisateur recherche lors de la comparaison de code, et devrait être l'objectif des outils de programmation de nouvelle génération. Y a-t-il des exemples de cela dans les outils disponibles?

jasonmray
la source
3
On dirait que des recherches ont été effectuées sur la distance d'édition des arbres. Appliquer cela aux AST semble être la première chose à essayer. (Si quelqu'un voulait essayer d'écrire ce genre de chose.)
Jay Kominek
2
Je ne sais pas si cela serait vraiment utile. une différence comme celle que vous avez mentionnée est plus facile à voir qu'à lire, surtout si vous disposez d'un outil mettant en évidence les différences dans une ligne. la capacité de reconnaître si du code vient d'être déplacé inchangé serait plus facile et plus utile, à mon humble avis!
UncleZeiv
2
@UncleZeiv J'espère que cette fonctionnalité découlerait naturellement de la nature de l'outil. De plus, il serait capable de détecter qu'il n'y a pas de changement si quelqu'un a changé les styles d'accolades ou d'indentation, par exemple, ou réorganisé le fichier afin que les méthodes statiques soient groupées, etc.
jasonmray
8
J'en ai besoin dans Visual Studio maintenant. Forcer les développeurs au sein d'une équipe à utiliser la même structure de formatage pour faciliter les différences est une réflexion en arrière. Le code doit être formaté selon une norme lors de l'enregistrement, et chaque fois qu'un développeur ouvre un fichier, il doit être formaté à son goût. Je suis choqué que ce genre de pensée ne soit pas plus répandu à ce stade.
Langdon
3
IMHO c'est un bon sujet pour SO. Si vous êtes d'accord, votez pour "rouvrir"
Ira Baxter

Réponses:

37

Nous avons développé un outil capable de gérer précisément ce scénario. Vérifiez http://www.semanticmerge.com

Il fusionne (et diffs) en fonction de la structure du code et n'utilise pas d'algorithmes basés sur du texte, ce qui vous permet essentiellement de traiter des cas comme celui-ci, impliquant un refactor fort. Il est également capable de rendre à la fois les différences et les conflits de fusion comme vous pouvez le voir ci-dessous:

entrez la description de l'image ici

Et au lieu de se confondre avec les blocs de texte déplacés, puisqu'il analyse en premier, il est capable d'afficher les conflits par méthode (par élément en fait). Un cas comme le précédent n'aura même pas de conflits manuels à résoudre.

entrez la description de l'image ici

C'est un outil de fusion compatible avec le langage et cela a été formidable de pouvoir enfin répondre à cette question SO :-)

Pablo
la source
Est-il possible de l'intégrer avec SVN?
Revious le
1
Cependant, les versions Linux et Mac sont anciennes.
Michael Piefel
29

Eclipse a cette fonctionnalité depuis longtemps. Ça s'appelle "Structure Compare", et c'est très sympa. Voici un exemple de capture d'écran pour Java, suivi d'une autre pour un fichier XML:

(Notez les icônes moins et plus sur les méthodes dans le volet supérieur.)

Comparateur de structure Java d'Eclipse Comparateur de structure XML d'Eclipse

Hosam Aly
la source
3
La comparaison de structure vous permet-elle de fusionner des modifications comme d'autres éditeurs de fusion de contrôle de source? Ie Copiez cette méthode de cette version vers l'autre version.
Jonathan Parker
1
Oui, lorsque vous sélectionnez un changement ou une différence (dans les volets supérieur ou inférieur), les boutons de la barre d'outils (illustrés dans les captures d'écran) vous donnent la possibilité de copier le changement de gauche à droite ou vice versa.
Hosam Aly
1
Malheureusement, les captures d'écran ne sont plus visibles dans votre réponse (la plus élevée et acceptée!). Pourriez-vous les soumettre à nouveau?
blubb
@blubb Merci de m'avoir prévenu. J'ai corrigé l'erreur avec l'image Java Comparer. J'essaierai bientôt d'ajouter une capture d'écran pour le XML Structure Comparer.
Hosam Aly
1
Et cela fonctionne-t-il pour des langages autres que Java?
einpoklum
14

Pour bien faire des «comparaisons sémantiques», vous devez comparer les arbres de syntaxe des langages, et prendre en compte la signification des symboles. Un très bon diff sémantique comprendrait la sémantique du langage et réaliserait quand un bloc de code était équivalent en fonction à un autre. Aller aussi loin nécessite un prouveur de théorème, et bien que ce soit extrêmement mignon, ce n'est actuellement pas pratique pour un vrai outil.

Une approximation viable de ceci consiste simplement à comparer les arborescences de syntaxe et à signaler les changements en termes de structures insérées, supprimées, déplacées ou modifiées. En se rapprochant un peu plus d'une «comparaison sémantique», on pourrait signaler lorsqu'un identifiant est modifié de manière cohérente dans un bloc de code.

Consultez notre http://www.semanticdesigns.com/Products/SmartDifferencer/index.html pour un moteur de comparaison basé sur une arborescence de syntaxe qui fonctionne avec de nombreux langages, qui fait l'approximation ci-dessus.

EDIT Jan 2010: Versions disponibles pour C ++, C #, Java, PHP et COBOL. Le site Web présente des exemples spécifiques pour la plupart d'entre eux.

EDIT Mai 2010: Python et JavaScript ajoutés.

EDIT Oct 2010: EGL ajouté.

EDIT Nov 2010: VB6, VBScript, VB.net ajoutés

Ira Baxter
la source
2
Salut Ira, avez-vous publié un article sur votre algorithme de diff? J'ai du mal à trouver de la littérature sur les différences de distance dans les arbres. Merci, Terence.
Terence Parr
Pour être plus précis, recherchez diff3 not plain diff2
Terence Parr
2
@Terence: Il n'existe aucune publication de notre algorithme diff. Il s'agit d'un calcul de distance minimale de Levenstein utilisant des arbres de suffixes pour identifier des sous-arbres égaux, avec quelques huerstics pour gérer le changement de nom. IIRC, Yang avait un article à ce sujet dans Software Practice and Experience. Le nôtre et celui de Yang sont diff2, pas diff3.
Ira Baxter
@IraBaxter Le lien est actuellement rompu et le site semble être en panne lors de l'ouverture à partir du lien google.
Răzvan Flavius ​​Panda
Le site est de retour, le lien devrait être OK.
Ira Baxter
12

Ce que vous cherchez, c'est un "arbre diff". Il s'avère que c'est beaucoup plus difficile à faire qu'un simple diff textuel orienté ligne, qui n'est en réalité que la comparaison de deux séquences plates.

" Une approche de comparaison structurelle XML à grain fin" se termine, en partie par:

Notre étude théorique ainsi que notre évaluation expérimentale ont montré que la méthode proposée donne de meilleurs résultats de similarité structurelle par rapport aux alternatives existantes, tout en ayant la même complexité temporelle (O (N ^ 2))

(c'est moi qui souligne)

En effet, si vous recherchez plus d'exemples de différenciation d'arbres, je vous suggère de vous concentrer sur XML, car cela a entraîné des développements pratiques dans ce domaine.

bendin
la source
Merci pour le lien. Je peux penser à quelques approches différentes pour implémenter des outils de diff sématiques, et vous avez raison - la plupart peuvent être résumées dans un "arbre diff". Des situations plus complexes peuvent même devoir être résumées dans un "graph diff".
jasonmray
Oui. Le Rational Modeler d'IBM (construit sur eclipse) essaie de faire cela avec des modèles UML (montrant graphiquement les différences entre deux modèles). Je ne peux pas commenter l'utilité des résultats car je ne les utilise pas beaucoup.
bendin
Je conviens que XML est un bon point de départ, car vous pouvez simplement créer des schémas pour représenter d'autres structures (comme le code java, par exemple), et utiliser un tree-diff basé sur XML pour implémenter un code diff.
jasonmray
"do this" => faire quelque chose qui ressemble à un "graph diff".
bendin
1
Voir semdesigns.com/Products/SmartDifferencer/index.html pour un moteur de comparaison basé sur une arborescence de syntaxe qui fonctionne avec de nombreux langages.
Ira Baxter
2

La solution à cela serait sur une base par langue. C'est-à-dire qu'à moins qu'il soit conçu avec une architecture de plugin qui reporte une grande partie de l'analyse du code dans un arbre et la comparaison sémantique à un plugin spécifique à un langage, il sera très difficile de prendre en charge plusieurs langues. Pour quelle (s) langue (s) souhaitez-vous disposer d'un tel outil? Personnellement, j'en aimerais un pour C #.

Pour C #, il existe un complément d'assembly diff pour Reflector, mais il ne fait qu'un diff sur l'IL et non sur le C #.

Vous pouvez télécharger le complément diff ici [zip] ou aller au projet sur le site codeplex ici .

Jonathan Parker
la source
1
Voir semdesigns.com/Products/SmartDifferencer/index.html pour un moteur de comparaison basé sur une arborescence de syntaxe qui fonctionne avec de nombreux langages, en utilisant exactement le style du plugin de langage. Pas encore publié, mais une version C # est très proche.
Ira Baxter
Janvier 2010: C # Smart Differencer est publié.
Ira Baxter
2

Une société appelée Zynamics propose un outil de diff sémantique de niveau binaire. Il utilise un langage de méta-assemblage appelé REIL pour effectuer une analyse théorique des graphes de 2 versions d'un binaire, et produit un graphique à code couleur pour illustrer les différences entre elles. Je ne suis pas sûr du prix, mais je doute que ce soit gratuit.

David V McKay
la source
Lien vers la diff sémantique de niveau binaire: zynamics.com/bindiff.html
emallove
2

http://prettydiff.com/

Pretty Diff minimise chaque entrée pour supprimer les commentaires et les espaces blancs inutiles, puis embellit le code avant l'algorithme de diff. Je ne peux pas penser de toute façon à devenir plus sémantique du code que cela. Et, son JavaScript écrit donc il s'exécute directement dans le navigateur.

Austincheney
la source
5
Alors vous avez une imagination limitée! Pourquoi ne pas échanger les positions de deux méthodes dans un fichier tout en les laissant inchangées? Et les refactorisations?
Robin Green
(Vous ne pouvez pas permuter les déclarations de données en Java de cette façon, et avoir toujours une équivalence, en raison des initialiseurs; je suppose que C # a des problèmes similaires). Si vous optez pour une différence sémantique pure, vous essayez de résoudre l'équivalence de la machine de Turing. Il y a beaucoup de possibilités pour faire mieux que la correspondance de texte pure, et pire que Turing impossible.
Ira Baxter
@IraBaxter Conceptuellement, l'outil ne montrera évidemment que des choses équivalentes qui sont en fait équivalentes. S'il est correctement codé, il n'aura pas le type de problème que vous mentionnez.
Răzvan Flavius ​​Panda
«Correctement codé» signifie prouver l'équivalence de l'algorithme si vous voulez l'outil ultime. Les preuves d'équivalence d'algorithmes sont très difficiles en général, vous n'allez donc pas obtenir un tel outil en pratique. Ce que vous pourriez obtenir est un outil qui gère certaines équivalences autres que de simples changements de syntaxe. À ce jour, je n'ai vu personne tenter de créer un tel outil.
Ira Baxter