views:

229

answers:

8

I've been reading Josh Bloch's 'Effective Java 2nd Edition'. Item 43 states 'Return empty arrays or collections, not nulls'. My question is how can I search for all methods in a project that return an implementation of java.util.Collection interface? IDE that is used is Eclipse, but any way of finding the right result is acceptable, e.g. regex or some other IDE.

A: 

If there is no way to do this with the existing user interface, you can always use reflection to walk through the code. It is not that much work, a couple of nested loops.

starblue
A: 

intellij IDEA has structural/expression based searches,so by searching for all methods that return Collection, you can at least get something close.

Chii
+1  A: 

I don't know of a way to find all methods whose return type is any arbitrary implementation of java.util.Collection (including ones you may define yourself).

If you can accept solutions that are a bit more limited, then a few possibilities come to mind:

  1. Go to any class that imports java.util.Collection, double-click on "Collection", right-click on "Collection", and select "References > Project".

  2. Likewise for any particular collection type of interest.

  3. Go to any method returning a collection type, double-click on its return type, and search for that type as above.

  4. Go to any class that imports any java.util.anything, drag across "java.util." omitting the class following that package prefix, and right-click-search for project references as above.

For all of the above, the "Search" view will show you an expandable outline of the places in the project where the selected item occurs. You can traverse that outline (using either the keyboard -- with enter to select -- or the mouse -- clicking to select) to examine places those uses. I don't see a way to limit the viewed references to "method return type", but at least you'll be able to move quickly to relevant places in the code to eyeball for the specific usage type of interest.

(With all these, you can click on the small downward-pointing triangle in the top of the "Search" tab and filter on the type of usage to be included in the display, such as excluding import statements.)

joel.neely
+1  A: 

Plugin time! I whipped up something that does most of the work...

Grab

http://javadude.com/misc/collectionmarker.zip

http://javadude.com/misc/collectionmarker-source.zip (if interested)

Unzip collectionmarker.zip into your eclipse dir (your eclipse dir should contain a plugins dir)

Restart eclipse

There will be two little eclipse icons on the toolbar - one clears markers, one adds them.

This plugin searches everything in your workspace; it ignores selections. (It's quick n dirty)

Hope this helps! -- Scott

Scott Stanchfield
can't see these two little eclipse icons... do you have any tutorial maybe?
Boris Pavlović
email me at [email protected] to chat about this
Scott Stanchfield
A: 

Found this in Eclipse Help:

To search for methods with a specific return type, use "* " as follows:

  1. Open the search dialog and click on the Java Search tab.
  2. Type '*' and the return type, separated by a space, in the Search string.
  3. Select the Case sensitive checkbox.
  4. Select Method and Declarations and then click Search.

It can help finding all methods that return specific types but not implementations of some interface.

Boris Pavlović
A: 

PMD can check for this, as can SemmleCode, if your IDE does not support structural search.

Torsten Marek
+3  A: 

Thanks for mentioning SemmleCode. To find all methods in the source that return a subtype of java.util.Collection, you write:

import default

class CollectionType extends RefType {
  CollectionType() {
    this.getASupertype*().hasQualifiedName("java.util","Collection")
  }
}

from Method m
where m.getType() instanceof CollectionType
      and
      m.fromSource()
select m

That is, we first define what we mean by a CollectionType: all types that have java.util.Collection as a supertype. There's a star behind getASupertype because we want to apply that operation zero or more times. Next we just select those methods whose return type is such a CollectionType and which occur in the source.

Go on, try it out :-) It's an easy exercise to further refine the query to those methods that are supposed to return a CollectionType but may return null. All this can be done interactively, with auto-completion while you develop the query, and continuous checking to help you get it right. You can view the results in many different ways and navigate between analysis results and code with ease.

-Oege [disclosure: I'm the CEO of Semmle]

+1  A: 

In IntelliJ IDEA invoke Structural Search, choose existing template "methods of the class". The action will add following template:

class $Class$ { 
  $ReturnType$ $MethodName$($ParameterType$ $Parameter$);
}

Set text constraint for "ReturnType" variable (Edit variables action) to be java.util.Collection, specify "Apply constraint within hierarchy" to search for descendants. For "MethodName" variable specify that it is target of the search. That start searching, enjoy :)

nicity
IntelliJ has a warning/error you can turn on which find places you have returned null for a Collection/Map type (another if you return null for an array) which would make this search redundant. ;) You can add an @NotNull annotation to detect when a value could be null but is not allowed to be.
Peter Lawrey