Your plug-in can use the JDT API to search Java projects in the workspace for Java elements, such as method references, field declarations, implementors of an interface, etc.
The entry point for Java search is the SearchEngine class. You can search for particular patterns inside a Java element and scope the search to specific elements. Search patterns can be created using createPattern. A pattern is scoped using createJavaSearchScope. Once a pattern and scope are defined, the search method is used to collect the results.
Search results are reported to a SearchRequestor which you must extend in order to access the results.
A search operation will use both a pattern for describing the nature of the search, and a scope for restraining the range of investigation.
A search pattern defines how search results are found. You can either create a search pattern from a Java element (see createPatternPattern(IJavaElement element, int limitTo)) or from a string (see createPattern(String, int, int, int).) The last method supports wildcards (i.e. '*') and can be used to widen the search results.
For example, creating a search pattern for searching for references to a given method is done as follows:
// Get the method IMethod method = ...; // Create search pattern SearchPattern pattern = SearchPattern.createPattern(method, IJavaSearchConstants.REFERENCES);
Or creating a search pattern for searching for declarations of all types starting with "Obj":
// Create search pattern SearchPattern pattern = SearchPattern.createPattern("Obj*", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE);
The following search patterns are supported:
Note that these patterns are created using the following possible rules:
For example,
// a case insensitive prefix match is requested SearchPattern pattern1 = SearchPattern.createPattern("Hash", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_PREFIX_MATCH); // a camel case match is requested SearchPattern pattern2 = SearchPattern.createPattern("HM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMEL_CASE_MATCH); // a camel case with a strict expected number of parts match is requested SearchPattern pattern3 = SearchPattern.createPattern("HM", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CAMELCASE_SAME_PART_COUNT_MATCH);
Note that using the patterns created above reduce the number of possible results among others:
Hashtable
, HashMap
, HashMapEntry
, etc.HashMap
, HashMapEntry
, etc.HashMapEntry
, etc.Some references patterns can be refined by adding one or several fine grain flags to the limitTo
parameter.
For example, only the type references used in a cast expression will match the pattern created as follows:
// Get the type IType type = ...; // Create search pattern SearchPattern pattern = SearchPattern.createPattern(type, IJavaSearchConstants.REFERENCES | IJavaSearchConstants.CAST_TYPE_REFERENCE);
Note that the fine grain flags can be combined together but only for the same kind of search (e.g. only a combination of flags for type references will be meaningful if the
searchFor
parameter is set to TYPE).
Flags for type references:
instance
of
condition.Flags for field or method references:
super
qualifier).this
qualifier).If you are interested in search results in a given project or even in a given package, or if you know that search results can only be found in the hierarchy of a given type, you can create the appropriate search scope using createJavaSearchScope(IJavaElement[]) or createHierarchyScope(IType).
For example, creating a search scope on a given package is done as follows:
// Get the package IPackageFragment pkg = ...; // Create search scope IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] {pkg});
Or creating a search scope on the hierarchy of a given type is:
// Get the type IType type = ...; // Create search scope IJavaSearchScope scope = SearchEngine.createHierarchyScope(type);
Finally, you can create a search scope comprising the entire workspace using createWorkspaceScope:
// Create search scope IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
Once you have created a search pattern and a search scope, and you have extended SearchRequestor, you can start a search query as follows:
// Get the search pattern SearchPattern pattern = ...; // Get the search scope IJavaSearchScope scope = ...; // Get the search requestor SearchRequestor requestor = ...; // Search SearchEngine searchEngine = new SearchEngine(); searchEngine.search(pattern, new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, scope, requestor, null);
A notification that the search starts is sent to your search requestor using the beginReporting method. Then, each search result is reported using the acceptSearchMatch method. Finally endReporting indicates that the search has ended.
Search results are reported using the acceptSearchMatch(SearchMatch) method. Paragraphs below highlight some features of SearchMatch.
A search result can correspond to a Java element (e.g. a type declaration) or it can be contained in a Java element (e.g. a reference to a type inside a method). The search engine always tries to find the innermost Java element that corresponds to or that contains the search result. For example, searching for references to a method could find such a reference in an initializer. The initializer that contains this method reference is the element of the search match.
The search engine also tries to find the resource that contains the Java element. If the Java element is contained in a compilation unit or a class file, the resource is the corresponding IFile. If the Java element is contained in a .jar file, the returned resource is that .jar file if it is in the workspace, null otherwise.
Source positions getOffset and getLength are given relative to the compilation unit that contains the search result. If the search result is contained in a .jar file, the source positions are relative to the attached source. They are (-1, -1) if there is no source attached to the .jar file.
In most cases search results are accurate, meaning that the search engine was able to determine that the given match is what was asked for. However in some cases the search engine is unable to do so, in such cases the match is inaccurate. Some possible reasons why a match could be inaccurate are: