Utilitários de comparação semântica [fechado]

105

Estou tentando encontrar alguns bons exemplos de utilitários de diff / merge semântico. O paradigma tradicional de comparação de arquivos de código-fonte funciona comparando linhas e caracteres ... mas há algum utilitário por aí (para qualquer linguagem) que realmente considere a estrutura do código ao comparar arquivos?

Por exemplo, programas diff existentes reportarão "diferença encontrada no caractere 2 da linha 125. Arquivo x contém void, onde o arquivo y contém bool". Uma ferramenta especializada deve ser capaz de relatar "Tipo de retorno do método doSomething () alterado de void para bool".

Eu diria que esse tipo de informação semântica é na verdade o que o usuário está procurando ao comparar o código e deve ser o objetivo das ferramentas de programação de próxima geração. Existem exemplos disso nas ferramentas disponíveis?

jasonmray
fonte
3
Parece que alguma pesquisa foi feita sobre a distância de edição da árvore. Aplicar isso aos ASTs parece ser a primeira coisa a tentar. (Se alguém quisesse tentar escrever esse tipo de coisa.)
Jay Kominek
2
Não tenho certeza se seria realmente útil. uma diferença como a que você mencionou é mais facilmente vista do que lida, especialmente se você tiver uma ferramenta que destaque as diferenças dentro de uma linha. a capacidade de reconhecer se algum código acabou de ser movido sem alterações seria mais fácil e mais útil, imho!
UncleZeiv
2
@UncleZeiv Espero que esse recurso seja uma consequência natural da natureza da ferramenta. Além disso, seria capaz de detectar que não há alterações se alguém alterasse os estilos de chave ou indentação, por exemplo, ou reorganizasse o arquivo para agrupar métodos estáticos, etc.
jasonmray
8
Eu preciso disso no Visual Studio agora. Forçar os desenvolvedores em uma equipe a usar a mesma estrutura de formatação para facilitar as diferenças é pensar ao contrário. O código deve ser formatado de acordo com algum padrão no check-in e, sempre que um desenvolvedor abre um arquivo, ele deve ser formatado de acordo com sua preferência. Estou chocado que esse tipo de pensamento não esteja mais disseminado neste momento.
Langdon
3
IMHO este é um bom tópico para SO. Se você concorda, vote para "reabrir"
Ira Baxter

Respostas:

37

Desenvolvemos uma ferramenta capaz de lidar com precisão com este cenário. Verifique http://www.semanticmerge.com

Ele mescla (e diffs) com base na estrutura do código e não usando algoritmos baseados em texto, o que basicamente permite que você lide com casos como o seguinte, envolvendo refatoração forte. Ele também é capaz de renderizar as diferenças e os conflitos de mesclagem, como você pode ver abaixo:

insira a descrição da imagem aqui

E em vez de se confundir com os blocos de texto que estão sendo movidos, uma vez que analisa primeiro, é capaz de mostrar os conflitos por método (por elemento na verdade). Um caso como o anterior nem terá conflitos manuais para resolver.

insira a descrição da imagem aqui

É uma ferramenta de mesclagem com reconhecimento de idioma e foi ótimo finalmente poder responder a esta pergunta do SO :-)

pablo
fonte
É possível integrá-lo com o SVN?
Revious de
1
No entanto, as versões Linux e Mac são antigas.
Michael Piefel
29

O Eclipse tem esse recurso há muito tempo. É chamado de "comparação de estrutura" e é muito bom. Aqui está uma captura de tela de amostra para Java, seguida por outra para um arquivo XML:

(Observe os ícones de menos e mais nos métodos no painel superior.)

Comparador de estrutura Java do Eclipse Comparador de estrutura XML do Eclipse

Hosam Aly
fonte
3
O Structure Compare permite mesclar mudanças como outros editores de mesclagem de controle de origem? Ou seja, copie este método desta versão para a outra versão.
Jonathan Parker,
1
Sim, quando você seleciona uma alteração ou diferença (nos painéis superior ou inferior), os botões da barra de ferramentas (mostrados nas imagens) oferecem a opção de copiar a alteração da esquerda para a direita ou vice-versa.
Hosam Aly
1
Infelizmente, as capturas de tela não estão mais visíveis em sua resposta (com maior número de votos e aceitos!). Você poderia enviá-los novamente?
blubb
@blubb Obrigado por me notificar. Corrigi o erro com a imagem Java Comparer. Tentarei adicionar uma captura de tela para o comparador de estrutura XML em breve.
Hosam Aly
1
E isso funciona para outras linguagens além do Java?
einpoklum de
14

Para fazer bem as "comparações semânticas", você precisa comparar as árvores de sintaxe das línguas e levar em consideração o significado dos símbolos. Uma diferença semântica realmente boa compreenderia a semântica da linguagem e perceberia quando um bloco de código era equivalente em função a outro. Ir tão longe requer um provador de teoremas e, embora seja extremamente fofo, atualmente não é prático para uma ferramenta real.

Uma aproximação viável disso é simplesmente comparar árvores de sintaxe e relatar mudanças em termos de estruturas inseridas, excluídas, movidas ou alteradas. Chegando um pouco mais perto de uma "comparação semântica", pode-se relatar quando um identificador é alterado de forma consistente em um bloco de código.

Consulte nosso http://www.semanticdesigns.com/Products/SmartDifferencer/index.html para um mecanismo de comparação baseado em árvore de sintaxe que funciona com muitos idiomas, que faz a aproximação acima.

EDITAR janeiro de 2010: Versões disponíveis para C ++, C #, Java, PHP e COBOL. O site mostra exemplos específicos para a maioria deles.

EDITAR maio de 2010: Python e JavaScript adicionados.

EDITAR outubro de 2010: EGL adicionado.

EDITAR novembro de 2010: VB6, VBScript, VB.net adicionado

Ira Baxter
fonte
2
Olá, Ira, você publicou um artigo sobre seu algoritmo de comparação? Estou tendo problemas para encontrar literatura de diferenças de distância de edição em árvore. Obrigado, Terence.
Terence Parr de
Para ser mais específico, procurando por diff3 não simples diff2
Terence Parr
2
@Terence: Não existe nenhuma publicação de nosso algoritmo diff. É um cálculo de distância mínima de Levenstein usando árvores de sufixo para identificar subárvores iguais, com alguns huerstics para lidar com a renomeação. IIRC, Yang teve um artigo sobre isso em Software Practice and Experience. O nosso e o de Yang são diff2, não diff3.
Ira Baxter de
@IraBaxter O link está quebrado e o site parece estar fora do ar ao abrir a partir do link do google.
Răzvan Flavius ​​Panda
O site está de volta, o link deve estar OK.
Ira Baxter
12

O que você está procurando é uma "árvore diferente". Acontece que isso é muito mais difícil de fazer bem do que um simples diff textual orientado por linha, que é na verdade apenas a comparação de duas sequências planas.

" Uma abordagem de comparação estrutural XML refinada " conclui, em parte com:

Nosso estudo teórico, bem como nossa avaliação experimental mostraram que o método proposto produz resultados de similaridade estrutural melhorados em relação às alternativas existentes, embora tendo a mesma complexidade de tempo (O (N ^ 2))

(ênfase minha)

Na verdade, se você estiver procurando por mais exemplos de diferenciação de árvore, sugiro focar em XML, uma vez que isso está gerando desenvolvimentos práticos nessa área.

Bendin
fonte
Obrigado pelo link. Eu posso pensar em algumas abordagens diferentes para implementar ferramentas de diff semático, e você está correto - a maioria pode ser abstraída em uma "árvore de diff". Situações mais complexas podem até precisar ser abstraídas em um "gráfico de comparação".
jasonmray
Sim. O Rational Modeler da IBM (construído no eclipse) tenta fazer isso com modelos UML (mostrando as diferenças entre dois modelos graficamente). Não posso comentar sobre a utilidade dos resultados, pois não os uso muito.
dobrando em
Eu concordo que XML é um bom lugar para começar, já que você pode simplesmente criar esquemas para representar outras estruturas (como código java, por exemplo) e usar uma árvore-diff baseada em XML para implementar uma diferença de código.
jasonmray,
"fazer isso" => fazer algo semelhante a um "gráfico diff".
encerramento de
1
Consulte semdesigns.com/Products/SmartDifferencer/index.html para um mecanismo de comparação baseado em árvore de sintaxe que funciona com vários idiomas.
Ira Baxter
2

A solução para isso seria por idioma. Ou seja, a menos que seja projetado com uma arquitetura de plug-in que adie muito a análise do código em uma árvore e a comparação semântica com um plug-in específico de idioma, será muito difícil oferecer suporte a vários idiomas. Para quais idiomas você está interessado em ter essa ferramenta. Pessoalmente, adoraria um para C #.

Para C #, há um suplemento de diff de montagem para o Reflector, mas ele só faz uma diferença no IL, não no C #.

Você pode baixar o suplemento diff aqui [zip] ou ir para o projeto no site codeplex aqui .

Jonathan Parker
fonte
1
Consulte semdesigns.com/Products/SmartDifferencer/index.html para um mecanismo de comparação baseado em árvore de sintaxe que funciona com vários idiomas, usando exatamente o estilo do plugin de idioma. Ainda não foi lançado, mas uma versão C # está muito perto.
Ira Baxter
Janeiro de 2010: Lançamento do C # Smart Differencer.
Ira Baxter
2

Uma empresa chamada Zynamics oferece uma ferramenta de comparação semântica de nível binário. Ele usa uma linguagem de metamontagem chamada REIL para realizar a análise teórica de gráficos de 2 versões de um binário e produz um gráfico codificado por cores para ilustrar as diferenças entre eles. Não tenho certeza do preço, mas duvido que seja grátis.

David V McKay
fonte
Link para a diferença semântica de nível binário: zynamics.com/bindiff.html
emallove
2

http://prettydiff.com/

Pretty Diff reduz cada entrada para remover comentários e espaços em branco desnecessários e embeleza o código antes do algoritmo de diff. Não consigo pensar em nada para me tornar mais semântico de código do que isso. E é JavaScript escrito para que seja executado diretamente no navegador.

Austincheney
fonte
5
Então você tem uma imaginação limitada! Que tal trocar as posições de dois métodos em um arquivo, deixando-os inalterados? E as refatorações?
Robin Green
(Você não pode trocar declarações de dados em Java dessa maneira e ainda ter equivalência, devido aos inicializadores; presumo que C # tenha problemas semelhantes). Se você escolher a diferença semântica pura, estará tentando resolver a equivalência da máquina de Turing. Há uma grande variedade de resultados melhores do que a correspondência de texto puro e, pior do que Turing, é impossível.
Ira Baxter
@IraBaxter A ferramenta conceitualmente obviamente só mostrará coisas equivalentes que na verdade são equivalentes. Se codificado corretamente, não terá o tipo de problema que você está mencionando.
Răzvan Flavius ​​Panda
"Codificado corretamente" significa provar a equivalência do algoritmo se você quiser a ferramenta definitiva. As provas de equivalência de algoritmo são difíceis de Turing em geral, portanto, você não obterá tal ferramenta na prática. O que você pode obter é uma ferramenta que lida com algumas equivalências além de apenas mudanças de sintaxe. Até hoje, não vi ninguém tentar construir tal ferramenta.
Ira Baxter