views:

750

answers:

10

I'm looking for a diff tool that can analyse my code and tell me what has changed on a construct by construct basis.

For instance, if I cut and paste a method from the start of my file and put it at the end but leave that method unchanged, I don't want it flagged. If however I insert a line of code or change something inside that method, it would flag it as changed.

I've used various diff tools, but all of them seem to fall short at telling you that lines have been inserted, removed or changed but couldn't tell what the changes were in any kind of logical fashion. It would be nice if when I periodically rearrange the layout of my code file the diff tool could keep up.

Does anyone have such a tool?

+18  A: 

I use http://winmerge.org/

I don't think you can do what you are asking, because of the way the longest common subsequence algorithms work for these tools.

Even if your functions get re-arranged, and your source file's functionality remains the same, it will still show up as a difference because of the nature of the LCS.

EDIT:
This is a bit far fetched, but if you were feeling extra ambitious, you could write your own that tailors to your exact needs.

you could use regular expressions to pull out each method in a source file, and do the LCS diff on each method individually based on its name. You could store your code a Dictionary (key,value) so that the key is the name of the method and the value is the string of the function. Then you just diff your dictionary_orig['method'] with your dictionary_new['method'].

Other than that, I don't know how you'd accomplish what you are looking for.

Robert Greiner
Actually, Winmerge has an option to detect moved text blocks. They will be marked differently from the ones changed or added/deleted.
VladV
I would still consider that "flagged"
Robert Greiner
Ira Baxter's posted an item that is potentially exactly the kind of thing programmers need for a diff, potentially it supports many languages. I'm just waiting on a response from their support team to find out if it's actually everything it promises.
BenAlabaster
A: 

I use DiffMerge, works fine! http://www.sourcegear.com/diffmerge/

Nisse
OP: "I'm looking for a diff tool that can analyse my code and tell me what has changed on a construct by construct basis". Does DiffMerge? -1.
John Saunders
A: 

DiffMerge from SourceGear is excellent, and is available at no charge.

http://www.sourcegear.com/diffmerge/

Andrey Butov
OP: "I'm looking for a diff tool that can analyse my code and tell me what has changed on a construct by construct basis". Does DiffMerge? -1
John Saunders
A: 

I use KDiff and find that it works pretty well. And is of course free.

jamesaharvey
OP: "I'm looking for a diff tool that can analyse my code and tell me what has changed on a construct by construct basis". Does DiffMerge? -1
John Saunders
A: 

It's something I've been wondering also. I don't think it exists yet. There are 'functional' (as opposed to merely text-based) diff tools available for other scenario's. E.g. Microsoft Word integrates it's own diff/merge functionality (which can be scripted, so it can be integrated with e.g. TortoiseSVN), and there are also several tools available for XML which interpret xml files and do not simply consider them as text.

I'm not sure the added value of such a tool over a good text-based diff/merge tool would be compelling enough to merit developing it. OTOH this may just be the missing link solving the 'merge pain' we all feel when confronted with a difficult merge situation.

The difficulty is of course that you have to interpret the code in the same way the C# compiler does. For now the tool that comes the closest is indeed NDepend, I think. This blog post explains some of its capabilities in this regard.

jeroenh
+6  A: 

Would you be willing to do the compare on compiled assemblies? If so, .NET Reflector has an Add-In available called Diff that will allow you to compare 2 assemblies. This would definitely not care where/how your objects are arranged inside of the source file.

Chris Porter
I was about to say that.
Ramesh
That's an interesting idea - and theoretically I don't need to diff files that aren't going into the VCS, and only compilable applications go in there, so this could work - as I said, theoretically. I'll check that avenue out.
BenAlabaster
Its not a "perfect" solution, but it gives an interesting approach to see what is different from the other side of the compiler. If you haven't used .NET Reflector, make sure to check out the other Add-Ins as they definitely make an already impressive tool even better.And to whomever down-voted this response, please explain why. If you find a flaw in my answer, you should step up and say what you find wrong with it.
Chris Porter
A: 

As many have suggested, I guess this kind of comparison will not be possible with available diff tools. Because their purpose is to say whether something changed and if you move a method from the beginning to the end, there did actually change something.

But what comes to my mind now is that you could do it by yourself. Basically invoking some diff tool, which will then return the newly inserted lines, basically the method that you have moved to the end of your file. Then you could do a comparison yourself, whether the changed lines where already present in your previous file.

Juri
+2  A: 

Beyond Compare by Scooter Software rocks for this and it is cheap ($30) too.

JohnFx
It's also been suggested Jeff used this while writing StackOverflow. http://highscalability.com/stack-overflow-architecture
John MacIntyre
+1  A: 

I know you are looking for a tool. But since I know of none, here is how I would accomplish this:

  1. Read a book on compiler design
  2. Lex/Parse your code
  3. Create an Abstract Syntax Tree
  4. Invent an algorithm for performing diffs on the Syntax tree
  5. Profit!
Carlos Rendon
Already considering this - I think it would be a great tool given that it's apparent that one doesn't yet exist. The only issue is how do you lex/parse a class that has dependencies that aren't satisfied by the file alone? It wouldn't work...
BenAlabaster
Maybe it would be a whole "project" or "solution" diff.. Your compiler already takes care of this so it shouldn't be too hard to figure out. It would also be neat to make it language agnostic if possible.. So other langs could be added easily. I'm sure quite a few people would pay for it as a product.
Carlos Rendon
See my answer below.
Ira Baxter
+3  A: 

Check out our Smart Differencer tool, which compares abstract syntax trees, and reports differences in terms of the nonterminals ("language constructs") that the ASTs represent and actions (insert, delete, move), as well as discovering consistent renaming:

http://www.semdesigns.com/Products/SmartDifferencer/index.html

At present, it only handles Java and COBOL, but it is based on DMS, which has parser for a wide variaty of languages, including C#.

EDIT 9/8/2009: C# SmartDifferencer now available for beta testers.

The tool already handles a consistent rename across the entire file as being semantically trivial (on the assumption that other files reference the renamed symbol accordingly), as well as renames within a scope. We plan on taking into account semantically trivial changes, such as moving a method declaration around in a class for Java and C#.

EDIT October 2010: Production versions available. Eval downloads accessible at the website.

Ira Baxter
Thanks for sharing
Carlos Rendon
Haven't checked this out yet, but will do when I get to the office. Sounds very promising though - I'm excited to see what it's capable of!
BenAlabaster
Okay, so I couldn't figure out where to find a download of this tool to try it out for C# - just waiting for a response from their support crew. I've got my fingers crossed that it's all I hope it will be.
BenAlabaster
The link to download the C# eval version is broken (at the time of writing this): http://www.semdesigns.com/Products/SmartDifferencer/C#FormatterEvaluationRegister.html
Richard Morgan
No eval version yet. Beta versions only. Ask at SD website.
Ira Baxter