tags:

views:

95

answers:

2

I am trying to find some mysterious bugs in an application, and believe the cause may be some hard casts on interfaces. Such casts are unsafe in Delphi, for example

ISomeInterface(CurrentObj)

which should be

CurrentObj as ISomeInterface

In light of the lack of compiler warnings which in my opinion should be emitted for hard casts, my question is how to easily find these casts in a codebase? Some sort of regex grep search perhaps? The codebase is large and it would take forever to search manually for it.

+1  A: 

If you know the name of the interface you could use the following regular expression in the Find in Files Dialog.

ITest\([^)]+\)

Where ITest is the name of your interface

Robert Love
Wouldn't work with nested parens, like in `ITest(CreateMyObject(...))`. It's probably good enough to stop as soon as you've matched the open paren.
Joe White
+6  A: 

You don't say which flavor of regular expressions you're using. I'm going to assume PCRE (Perl-compatible regular expressions), which means these examples won't work with the goofball "regular expressions" option in the IDE's Find dialog. However, they'll work with any self-respecting grep tool, as well as with the built-in regexes in Perl, Ruby, .NET, and many other languages.

You could start with something like this:

\w+\s*\(

which would search for one or more word characters, followed by zero or more spaces, followed by an open parenthesis. This would match:

TObject (Foo)

but depending on your regex library, and which options you use, and how you pass the input into it, might or not match if there's a line break before the open paren:

TObject
  (Foo)

and definitely wouldn't work if there's a comment in between, like this pathological case:

X := ISomeInterface // come back and look at this cast, it's dangerous
  (CurrentObj);

But for most well-formatted code, it will be good enough.

Now your problem is that it's giving you way more than just the typecasts -- it's also giving you just about every method call in your code. So some refinement is needed.

If your code follows the typical Delphi coding style, then this would probably work much better:

\b[TIE][A-Z]\w+\s*\(

and make sure you do a case-sensitive match. This will match anyplace where you have a word boundary, followed by a capital T (the traditional prefix for most classes and types) or capital I (the prefix for interfaces) or capital E (the prefix for Exception descendants), followed by another capital letter, then some number of upper- or lowercase letters or digits or underscores, followed by optional spaces and an open paren. There's a good chance this is what you need.

However, if you have any type names that don't follow the usual naming conventions (e.g. TfcTreeView that has a lowercase letter after the T), or if you ever rely on Delphi's case-insensitivity (e.g. if there's any chance you might ever have code like tobject(Foo) or even Tobject(Foo)), then it gets harder. If that's the case, post some details and I may be able to make suggestions.

Joe White