7

I have a number of occurrences in a new code base where there are a sequence of method calls like,

object o = something.foo();
bar(o);
something.foobar();

in consecutive lines. I would like to find / count the total number of such a sequence in my code where the name of object "something" could be different, but I want treated the same.

I want to pull these out as a method and see all the locations where this needs to be refactored. How do I go about doing something like this?

8
  • I am not aware of any tool that can do this off-the-shelf. You could write (or extend existing ) findbug plugin for doing this check : findbugs.sourceforge.net Commented Sep 23, 2013 at 4:53
  • Why not simply search the pattern with a regex in your IDE? Should give you count and locations... Commented Sep 27, 2013 at 6:53
  • @assylias Regexes might work, but I think that one could be really difficult. Also you might have to cope with all the syntax details, where there could be a cast somewhere or anything else. Commented Sep 27, 2013 at 7:10
  • @SpaceTrucker I assumed the only variable part was something, in which case it would not be very difficult. Commented Sep 27, 2013 at 7:21
  • @assylias I think that this is too easy, because then you just would have to search for usages of method foo and look if the succeeding 2 lines match that pattern. But searching for method usages is something that all modern IDEs support. Commented Sep 27, 2013 at 7:28

4 Answers 4

2

Intellij IDEA (incl. the free community version) does duplicated code detection & replacement.

If you carve out one of such occurrence into a method using its refactoring feature, it goes through the code base and asks you if you want to replace it in other places, too.

Sign up to request clarification or add additional context in comments.

Comments

2

There are tools that can do this off-the-shelf, and they are called program transformation tools.

If you really want to recognize these as consecutive line, with our DMS Software Reengineering Toolkit program transformation engine, using its Rule Specification Language (RSL). RSL lets you write patterns in terms of the language syntax of a language whose grammar is already known to DMS:

domain Java~v7;

pattern odd_pattern(IDENTIFIER: o,
                    qualifier: something,
                    IDENTIFIER: foo 
                    IDENTIFIER: bar,
                    IDENTIFIER: foobar, 
                    more: stmt_sequence): stmt_sequence
= " Object \o = \something.\foo;
    \bar(\o);
    \something.\foobar();
    \more";

This defines a pattern in terms of the surface syntax of the designated notation ("domain Java~v7"). Each pattern has a name ("odd_pattern") so that you can distinguish between many patterns. A pattern has a set of forced (clean grammar) syntax-category specified sub-patterns, named as <(non)terminal:name>. This pattern has several distinct identifiers, pattern-names o, foo, bar, foobar. I guessed you meant that something was some kind of qualifying path, but maybe you meant it to be just an identifier, too.

The pattern contents are defined in meta quotes " to distinguish the RSL pattern language text from the target language (Java) pattern text. Inside the meta quotes, \baz means the pattern variable baz of syntax category N where baz was defined as N:baz in the pattern parameter list. The same pattern variable occurring in multiple places requires identical substitutions.

Given this pattern, you can ask DMS where is matches a (Java) AST. By matching against an AST, al the problems of whitespace, comments, unnormalized strings/identifiers/numbers/etc. are eliminated. By simply counting matches, you get OP's original desired metric. [We have largely completed an extension to RSL patterns in which the elements are connected by dataflows rather than code syntax].

Presumably he wants to transform these instances into some other code, which he can do by writing, in RSL,

 rule rewrite_odd_pattern(parms): stmt_sequence
       odd_pattern(parms) -> replacement_pattern(parms);

mentioning some other "replacement_pattern" written similarly.

If OP only has a modest number of such patterns, he's probably better using regex or just slugging it out rather than getting DMS (or another program transformation tool) and setting it up. If he does this a lot, or they are scattered over very big piles of code, the patterns are complex, or he has many similar kinds of things to do, the tradeoff might tip the other way.

Comments

1

You could use a regex - for example in Netbeans, this regex:

(?s)object o = (.*?)\.foo\(\);\s+bar\(o\);\s+(\1)\.foobar\(\);

finds all lines like:

object o = xyz.foo();
bar(o);
xyz.foobar();

where xyz can be anything, provided it is the same on the first and last line.

4 Comments

Maybe you should consider blank lines and comment lines in your regex.
@SpaceTrucker blank lines are already ignored with that regex. Comments could indeed be added if required.
To do whitespace right, you need a bunch of additional regex goo inserted everywhere; likewise for comments. This gets pretty hairy for more complex patterns. And if there are arbitrary argument expressions inside the method argument parentheses (I assume Op's case isn't exactly what he showed) regex will fail you completely because it can't reliably skip over such expressions.
@IraBaxter my answer works well wiyh the given example. I agree that it won't handle any deviations easily. If the pattern is exactly as in his question all the time, that's probably the easiest solution though.
1

If your code is Java 1.6 or below, you could use Eclipse MoDisco to generate an EMF model instance of your Java projects. Then you can implement a Model Query to search for the pattern you describe. Even though the MoDisco Java model is based on Java 1.5 you can also use it for 1.6, because no syntax changes were introduced in 1.6.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.