Semantic Diff Utilities [chiuso]


105

Sto cercando di trovare alcuni buoni esempi di utilità semantiche diff / merge. Il paradigma tradizionale del confronto dei file del codice sorgente funziona confrontando linee e caratteri .. ma ci sono utilità là fuori (per qualsiasi lingua) che effettivamente considerano la struttura del codice quando si confrontano i file?

Ad esempio, i programmi diff esistenti riporteranno "la differenza trovata al carattere 2 della riga 125. Il file x contiene void, dove il file y contiene bool". Uno strumento specializzato dovrebbe essere in grado di segnalare "Il tipo restituito del metodo doSomething () è cambiato da void a bool".

Direi che questo tipo di informazioni semantiche è in realtà ciò che l'utente sta cercando quando confronta il codice e dovrebbe essere l'obiettivo degli strumenti di programmazione di prossima generazione. Ci sono esempi di questo negli strumenti disponibili?


3
Sembra che siano state fatte delle ricerche sulla distanza di modifica dell'albero. Applicarlo agli AST sembra che sarebbe la prima cosa da provare. (Se qualcuno volesse provare a scrivere questo genere di cose.)
Jay Kominek

2
Non sono sicuro che sarebbe davvero utile. una differenza come quella che hai citato è più visibile che letta, soprattutto se hai uno strumento che evidenzia le differenze all'interno di una riga. la capacità di riconoscere se qualche codice è stato appena spostato invariato sarebbe più facile e più utile, imho!
UncleZeiv

2
@UncleZeiv Spero che questa funzionalità derivi naturalmente dalla natura dello strumento. Inoltre, sarebbe in grado di rilevare che non ci sono modifiche se qualcuno passasse e cambiasse la parentesi graffa o gli stili di rientro, ad esempio, o riorganizzasse il file in modo che i metodi statici siano raggruppati, ecc.
jasonmray

8
Ne ho bisogno in Visual Studio ora. Costringere gli sviluppatori all'interno di un team a utilizzare la stessa struttura di formattazione per facilitare le differenze è pensare al contrario. Il codice dovrebbe essere formattato secondo uno standard al momento del check-in e ogni volta che uno sviluppatore apre un file, dovrebbe essere formattato a proprio piacimento. Sono scioccato che questo tipo di pensiero non sia più diffuso a questo punto.
Langdon

3
IMHO questo è un ottimo argomento per SO. Se sei d'accordo, vota per "riaprire"
Ira Baxter

Risposte:


37

Abbiamo sviluppato uno strumento in grado di affrontare con precisione questo scenario. Controlla http://www.semanticmerge.com

Si fonde (e diffonde) in base alla struttura del codice e non utilizza algoritmi basati su testo, il che consente fondamentalmente di gestire casi come il seguente, coinvolgendo un forte refactor. È anche in grado di rendere sia le differenze che i conflitti di unione come puoi vedere di seguito:

inserisci qui la descrizione dell'immagine

E invece di confondersi con i blocchi di testo spostati, poiché analizza prima, è in grado di visualizzare i conflitti in base al metodo (per elemento in effetti). Un caso come il precedente non avrà nemmeno conflitti manuali da risolvere.

inserisci qui la descrizione dell'immagine

È uno strumento di fusione che riconosce la lingua ed è stato fantastico poter finalmente rispondere a questa domanda SO :-)


È possibile integrarlo con SVN?
Revious

1
Tuttavia, le versioni Linux e Mac sono antiche.
Michael Piefel

29

Eclipse ha questa funzione da molto tempo. Si chiama "Structure Compare" ed è molto carino. Ecco uno screenshot di esempio per Java, seguito da un altro per un file XML:

(Notare le icone meno e più sui metodi nel riquadro superiore.)

Java Structure Comparer di Eclipse XML Structure Comparer di Eclipse


3
Structure Compare ti consente di unire le modifiche come altri editor di unione del controllo del codice sorgente? Cioè copia questo metodo da questa versione all'altra versione.
Jonathan Parker

1
Sì, quando selezioni una modifica o una differenza (nei riquadri superiore o inferiore), i pulsanti della barra degli strumenti (mostrati nelle schermate) ti danno la possibilità di copiare la modifica da sinistra a destra o viceversa.
Hosam Aly

1
Sfortunatamente, gli screenshot non sono più visibili nella tua risposta (votata più in alto e accettata!). Potresti inviarli di nuovo?
blubb

@blubb Grazie per avermi informato. Ho corretto l'errore con l'immagine Java Comparer. Cercherò di aggiungere presto uno screenshot per XML Structure Comparer.
Hosam Aly

1
E funziona per linguaggi diversi da Java?
einpoklum

14

Per fare bene i "confronti semantici", è necessario confrontare gli alberi della sintassi delle lingue e tenere conto del significato dei simboli. Una differenza semantica davvero buona comprenderebbe la semantica del linguaggio e si renderebbe conto quando un blocco di codice era equivalente in funzione a un altro. Andare così lontano richiede un dimostratore di teoremi e, sebbene sarebbe estremamente carino, al momento non è pratico per uno strumento reale.

Un'approssimazione praticabile di questo è semplicemente il confronto degli alberi della sintassi e la segnalazione delle modifiche in termini di strutture inserite, eliminate, spostate o modificate. Avvicinandosi un po 'a un "confronto semantico", si potrebbe segnalare quando un identificatore viene modificato in modo coerente in un blocco di codice.

Vedere il nostro http://www.semanticdesigns.com/Products/SmartDifferencer/index.html per un motore di confronto basato su albero della sintassi che funziona con molte lingue, che fa l'approssimazione di cui sopra.

EDIT Gennaio 2010: versioni disponibili per C ++, C #, Java, PHP e COBOL. Il sito web mostra esempi specifici per la maggior parte di questi.

EDIT Maggio 2010: Python e JavaScript aggiunti.

EDIT Ott 2010: EGL aggiunto.

EDIT Nov 2010: aggiunti VB6, VBScript, VB.net


2
Ciao Ira, hai pubblicato un articolo sul tuo algoritmo di diff? Ho problemi a trovare la letteratura sulle differenze a distanza con modifica ad albero. Grazie, Terence.
Terence Parr

Per essere più precisi, cercando diff3 non semplice diff2
Terence Parr

2
@Terence: non esiste alcuna pubblicazione del nostro algoritmo diff. È un calcolo della distanza minima di Levenstein che utilizza alberi dei suffissi per identificare sottoalberi uguali, con alcuni huerstics per gestire la ridenominazione. IIRC, Yang aveva un articolo su questo in Software Practice and Experience. Il nostro e quello di Yang sono diff2, non diff3.
Ira Baxter

@IraBaxter Il collegamento è attualmente interrotto e il sito sembra non funzionare quando si apre dal collegamento di Google.
Răzvan Flavius ​​Panda

Il sito è stato eseguito il backup, il collegamento dovrebbe essere OK.
Ira Baxter

12

Quello che stai cercando è un "albero diff". Si scopre che questo è molto più difficile da fare bene di un semplice diff testuale orientato alla linea, che in realtà è solo il confronto di due sequenze piatte.

" A Fine-Grained XML Structural Comparison Approach " si conclude, in parte con:

Il nostro studio teorico e la nostra valutazione sperimentale hanno mostrato che il metodo proposto produce risultati di similarità strutturale migliorati rispetto alle alternative esistenti, pur avendo la stessa complessità temporale (O (N ^ 2))

(enfasi mia)

In effetti, se stai cercando altri esempi di differenziazione ad albero, suggerisco di concentrarti su XML poiché questo ha guidato sviluppi pratici in quell'area.


Grazie per il collegamento. Posso pensare ad alcuni approcci diversi per l'implementazione di strumenti diff sematici, e hai ragione - la maggior parte può essere astratta in un "diff ad albero". Le situazioni più complesse potrebbero anche dover essere astratte in un "grafico diff".
jasonmray

Sì. Rational Modeler di IBM (basato su eclipse) tenta di farlo con i modelli UML (mostrando graficamente le differenze tra due modelli). Non posso commentare l'utilità dei risultati perché non lo uso molto.
bendin

Sono d'accordo sul fatto che XML sia un buon punto di partenza, poiché puoi semplicemente inventare schemi per rappresentare altre strutture (come il codice java, ad esempio) e utilizzare un diff ad albero basato su XML per implementare un diff di codice.
jasonmray

"do this" => fai qualcosa di simile a un "graph diff".
bendin

1
Vedi semdesigns.com/Products/SmartDifferencer/index.html per un motore di confronto basato sull'albero della sintassi che funziona con molte lingue.
Ira Baxter


2

La soluzione a questo sarebbe in base alla lingua. Ad esempio, a meno che non sia progettato con un'architettura a plug-in che differisce gran parte dell'analisi del codice in un albero e il confronto semantico con un plug-in specifico della lingua, sarà molto difficile supportare più lingue. Per quale lingua sei interessato ad avere uno strumento del genere. Personalmente ne vorrei uno per C #.

Per C # esiste un componente aggiuntivo per le differenze di assemblaggio in Reflector, ma esegue solo una differenza sull'IL, non sul C #.

Puoi scaricare l'add-in diff qui [zip] o andare al progetto sul sito di codeplex qui .


1
Vedi semdesigns.com/Products/SmartDifferencer/index.html per un motore di confronto basato sull'albero della sintassi che funziona con molte lingue, utilizzando esattamente lo stile del plugin del linguaggio. Non ancora rilasciato, ma una versione C # è molto vicina.
Ira Baxter

Gennaio 2010: viene rilasciato C # Smart Differencer.
Ira Baxter

2

Una società chiamata Zynamics offre uno strumento di diff semantico a livello binario. Utilizza un linguaggio meta-assembly chiamato REIL per eseguire l'analisi teorica dei grafi di 2 versioni di un binario e produce un grafico con codice colore per illustrare le differenze tra loro. Non sono sicuro del prezzo, ma dubito che sia gratuito.


Collegamento al diff semantico a livello binario: zynamics.com/bindiff.html
emallove

2

http://prettydiff.com/

Pretty Diff minimizza ogni input per rimuovere commenti e spazi bianchi non necessari e quindi abbellisce il codice prima dell'algoritmo diff. Non riesco comunque a pensare di diventare più semantico del codice di questo. E il suo JavaScript scritto, quindi viene eseguito direttamente nel browser.


5
Allora hai un'immaginazione limitata! Che ne dici di scambiare le posizioni di due metodi in un file lasciandoli invariati? E i refactoring?
Robin Green

(Non è possibile scambiare dichiarazioni di dati in Java in questo modo e avere ancora l'equivalenza, a causa degli inizializzatori; presumo che C # abbia problemi simili). Se scegli la differenza semantica pura, allora stai cercando di risolvere l'equivalenza della macchina di Turing. C'è un sacco di possibilità per fare meglio della pura corrispondenza del testo, e peggio di Turing impossibile.
Ira Baxter

@IraBaxter Lo strumento concettualmente mostrerà ovviamente solo cose equivalenti che in realtà sono equivalenti. Se codificato correttamente, non avrà il tipo di problema che stai menzionando.
Răzvan Flavius ​​Panda

"Codificato correttamente" significa dimostrare l'equivalenza dell'algoritmo se si desidera lo strumento definitivo. Le prove di equivalenza degli algoritmi sono difficili da Turing in generale, quindi non otterrai uno strumento del genere nella pratica. Quello che potresti ottenere è uno strumento che gestisce alcune equivalenze oltre alle semplici modifiche alla sintassi. Ad oggi, non ho visto nessuno tentare di costruire uno strumento del genere.
Ira Baxter
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.