Context-aware merge?
Is there any diff/merge tool for programming languages, that works in a syntax-aware way (like XML Diff Tool), doing more than compare line-by-line (and optionally ignoring whitespace).
I'm interested in a program actually following the language syntax and delimeters, suggesting changes without breaking syntactic correctness, or bundling statements separated over multiple lines. Example behavior would be:
*upon finding an if(){
which introduces an extra nesting level automatically bundle the closing brace }
several lines below with it.)
*keep matching syntax elements together, avoid silliness like removing a block tends to create:
int function_A()
{
int ret;
ret = something;
ret += something_else;
return ret;
}
int function_B()
{
if(valid)
{
int ret;
ret = something;
ret += something_else;
return ret;
}
else return -1;
}
Personally, I'd love to find software capable of handling C++ syntax, but knowing about solutions for other languages would be interesting too.
Semantic Merge.
Languages supported, from the website:
We started with C# and Vb.net, then added Java. Now C is already supported and then we’ll focus on C++, Objective-C and JavaScript, depending on your feedback
While KDiff3 does not compare syntax elements in a grammar context, it does have a higher granularity than "the whole line changed", and it will highlighting exactly what parts within a line that is changed.
And in my experience it has a very good algorithm for detecting changes. Given your example above, it correctly compares function_A and function_B out of the box:
And even so, should the algorithm fail to match what you want, for instance like the following:
you can always override manually by placing sync marks where you want to have it perform the comparision.
Alternative 1:
Alternative 2:
Sounds like you'd be interested in Bram Cohen's (BitTorrent creator) Patience Diff algorithm (which is used in the bazaar version control system).
See The diff problem has been solved and especially Patience Diff Advantages:
Excerpt from second link:
Another advantage of patience diff is that it frequently doesn't match lines which just plain shouldn't match. For example, if you've completely rewritten a section of code it shouldn't match up the blank lines in each version, as this example shows. Finally, there's this example:
void func1() { x += 1 } +void functhreehalves() { + x += 1.5 +} + void func2() { x += 2 }
Which is straightforward and obvious, but frequently diff algorithms will interpret it like this:
void func1() { x += 1 +} + +void functhreehalves() { + x += 1.5 } void func2() { x += 2 }