blob: 350c0c976ae0f1d93c23e7f185428741f4480cdd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
package org.eclipse.dltk.core.search;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.IMethod;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.RuntimePerformanceMonitor;
import org.eclipse.dltk.core.RuntimePerformanceMonitor.PerformanceNode;
import org.eclipse.dltk.core.WorkingCopyOwner;
import org.eclipse.dltk.core.index2.search.NewSearchEngine;
import org.eclipse.dltk.core.search.indexing.IndexManager;
import org.eclipse.dltk.internal.compiler.env.AccessRuleSet;
import org.eclipse.dltk.internal.core.ModelManager;
import org.eclipse.dltk.internal.core.Openable;
import org.eclipse.dltk.internal.core.search.IndexQueryRequestor;
import org.eclipse.dltk.internal.core.search.MethodNameMatchRequestorWrapper;
import org.eclipse.dltk.internal.core.search.MethodNameRequestorWrapper;
import org.eclipse.dltk.internal.core.search.PatternSearchJob;
import org.eclipse.dltk.internal.core.search.TypeNameMatchRequestorWrapper;
import org.eclipse.dltk.internal.core.search.TypeNameRequestorWrapper;
import org.eclipse.dltk.internal.core.search.matching.MixinPattern;
import org.eclipse.dltk.internal.core.util.HandleFactory;
import org.eclipse.osgi.util.NLS;
/**
* A {@link SearchEngine} searches for Script elements following a search
* pattern. The search can be limited to a search scope.
* <p>
* Various search patterns can be created using the factory methods
* {@link SearchPattern#createPattern(String, int, int, int)},
* {@link SearchPattern#createPattern(IModelElement, int)},
* {@link SearchPattern#createOrPattern(SearchPattern, SearchPattern)}.
* </p>
* <p>
* For example, one can search for references to a method in the hierarchy of a
* type, or one can search for the declarations of types starting with
* "Abstract" in a project.
* </p>
* <p>
* This class may be instantiated; it is not intended to be subclassed.
* </p>
*/
public class SearchEngine {
// Search engine now uses basic engine functionalities
private BasicSearchEngine basicEngine;
private NewSearchEngine newSearchEngine;
/**
* Creates a new search engine.
*/
public SearchEngine() {
this.basicEngine = new BasicSearchEngine();
this.newSearchEngine = new NewSearchEngine();
}
/**
* Creates a new search engine with a list of working copies that will take
* precedence over their original compilation units in the subsequent search
* operations.
* <p>
* Note that passing an empty working copy will be as if the original
* compilation unit had been deleted.
* </p>
* <p>
* The given working copies take precedence over primary working copies (if
* any).
*
* @param workingCopies
* the working copies that take precedence over their original
* compilation units
*
*/
public SearchEngine(ISourceModule[] workingCopies) {
int length = workingCopies.length;
ISourceModule[] units = new ISourceModule[length];
System.arraycopy(workingCopies, 0, units, 0, length);
this.basicEngine = new BasicSearchEngine(units);
}
/**
* Creates a new search engine with the given working copy owner. The
* working copies owned by this owner will take precedence over the primary
* compilation units in the subsequent search operations.
*
* @param workingCopyOwner
* the owner of the working copies that take precedence over
* their original compilation units
*
*/
public SearchEngine(WorkingCopyOwner workingCopyOwner) {
this.basicEngine = new BasicSearchEngine(workingCopyOwner);
}
/**
* Returns a Script search scope limited to the hierarchy of the given type.
* The Script elements resulting from a search with this scope will be types
* in this hierarchy, or members of the types in this hierarchy.
*
* @param type
* the focus of the hierarchy scope
* @return a new hierarchy scope
* @exception ModelException
* if the hierarchy could not be computed on the given type
*/
public static IDLTKSearchScope createHierarchyScope(IType type)
throws ModelException {
return BasicSearchEngine.createHierarchyScope(type);
}
/**
* Returns a Script search scope limited to the hierarchy of the given type.
* When the hierarchy is computed, the types defined in the working copies
* owned by the given owner take precedence over the original compilation
* units. The Script elements resulting from a search with this scope will
* be types in this hierarchy, or members of the types in this hierarchy.
*
* @param type
* the focus of the hierarchy scope
* @param owner
* the owner of working copies that take precedence over original
* compilation units
* @return a new hierarchy scope
* @exception ModelException
* if the hierarchy could not be computed on the given type
*
*/
public static IDLTKSearchScope createHierarchyScope(IType type,
WorkingCopyOwner owner) throws ModelException {
return BasicSearchEngine.createHierarchyScope(type, owner);
}
/**
* Returns a Script search scope limited to the super hierarchy of the given
* type. The Script elements resulting from a search with this scope will be
* types in this super hierarchy, or members of the types in this super
* hierarchy.
*
* @param type
* the focus of the hierarchy scope
* @return a new super hierarchy scope
* @exception ModelException
* if the hierarchy could not be computed on the given type
*/
public static IDLTKSearchScope createSuperHierarchyScope(IType type)
throws ModelException {
return BasicSearchEngine.createSuperHierarchyScope(type);
}
/**
* Returns a Script search scope limited to the super hierarchy of the given
* type. When the super hierarchy is computed, the types defined in the
* working copies owned by the given owner take precedence over the original
* compilation units. The Script elements resulting from a search with this
* scope will be types in this super hierarchy, or members of the types in
* this super hierarchy.
*
* @param type
* the focus of the hierarchy scope
* @param owner
* the owner of working copies that take precedence over original
* compilation units
* @return a new super hierarchy scope
* @exception ModelException
* if the hierarchy could not be computed on the given type
*
*/
public static IDLTKSearchScope createSuperHierarchyScope(IType type,
WorkingCopyOwner owner) throws ModelException {
return BasicSearchEngine.createSuperHierarchyScope(type, owner);
}
/**
* Returns a Script search scope limited to the given Script elements. The
* Script elements resulting from a search with this scope will be children
* of the given elements.
* <p>
* If an element is an IScriptProject, then the project's source folders,
* its jars (external and internal) and its referenced projects (with their
* source folders and jars, recursively) will be included. If an element is
* an IProjectFragment, then only the package fragments of this package
* fragment root will be included. If an element is an IScriptFolder, then
* only the compilation unit and class files of this package fragment will
* be included. Subpackages will NOT be included.
* </p>
* <p>
* In other words, this is equivalent to using
* SearchEngine.createJavaSearchScope(elements, true).
* </p>
*
* @param elements
* the Script elements the scope is limited to
* @return a new Script search scope
*
*/
public static IDLTKSearchScope createSearchScope(IModelElement[] elements,
IDLTKLanguageToolkit toolkit) {
return BasicSearchEngine.createSearchScope(elements, toolkit);
}
public static IDLTKSearchScope createSearchScope(IModelElement element) {
return BasicSearchEngine.createSearchScope(
new IModelElement[] { element },
DLTKLanguageManager.getLanguageToolkit(element));
}
/**
* Returns a Script search scope limited to the given Script elements. The
* Script elements resulting from a search with this scope will be children
* of the given elements.
*
* If an element is an IScriptProject, then the project's source folders,
* its jars (external and internal) and - if specified - its referenced
* projects (with their source folders and jars, recursively) will be
* included. If an element is an IProjectFragment, then only the package
* fragments of this package fragment root will be included. If an element
* is an IScriptFolder, then only the compilation unit and class files of
* this package fragment will be included. Subpackages will NOT be included.
*
* @param elements
* the Script elements the scope is limited to
* @param includeReferencedProjects
* a flag indicating if referenced projects must be recursively
* included
* @return a new Script search scope
*
*/
public static IDLTKSearchScope createSearchScope(IModelElement[] elements,
boolean includeReferencedProjects, IDLTKLanguageToolkit toolkit) {
return BasicSearchEngine.createSearchScope(elements,
includeReferencedProjects, toolkit);
}
/**
* Returns a Script search scope limited to the given Script elements. The
* Script elements resulting from a search with this scope will be children
* of the given elements.
*
* If an element is an IScriptProject, then it includes: - its source
* folders if IJavaSearchScope.SOURCES is specified, - its application
* libraries (internal and external jars, class folders that are on the raw
* buildpath, or the ones that are coming from a buildpath path variable, or
* the ones that are coming from a buildpath container with the
* K_APPLICATION kind) if IJavaSearchScope.APPLICATION_LIBRARIES is
* specified - its system libraries (internal and external jars, class
* folders that are coming from an IBuildpathContainer with the K_SYSTEM
* kind) if IJavaSearchScope.APPLICATION_LIBRARIES is specified - its
* referenced projects (with their source folders and jars, recursively) if
* IJavaSearchScope.REFERENCED_PROJECTS is specified. If an element is an
* IProjectFragment, then only the package fragments of this package
* fragment root will be included. If an element is an IScriptFolder, then
* only the compilation unit and class files of this package fragment will
* be included. Subpackages will NOT be included.
*
* @param elements
* the Script elements the scope is limited to
* @param includeMask
* the bit-wise OR of all include types of interest
* @return a new Script search scope
* @see IJavaSearchScope#SOURCES
* @see IJavaSearchScope#APPLICATION_LIBRARIES
* @see IJavaSearchScope#SYSTEM_LIBRARIES
* @see IJavaSearchScope#REFERENCED_PROJECTS
*
*/
public static IDLTKSearchScope createSearchScope(IModelElement[] elements,
int includeMask, IDLTKLanguageToolkit toolkit) {
return BasicSearchEngine.createSearchScope(elements, includeMask,
toolkit);
}
public static IDLTKSearchScope createSearchScope(IModelElement element,
int includeMask) {
return BasicSearchEngine.createSearchScope(
new IModelElement[] { element }, includeMask,
DLTKLanguageManager.getLanguageToolkit(element));
}
/**
* Create a type name match on a given type with specific modifiers.
*
* @param type
* The java model handle of the type
* @param modifiers
* Modifiers of the type
* @return A non-null match on the given type.
*/
public static TypeNameMatch createTypeNameMatch(IType type, int modifiers) {
return BasicSearchEngine.createTypeNameMatch(type, modifiers);
}
/**
* Returns a Script search scope with the workspace as the only limit.
*
* @return a new workspace scope
*/
public static IDLTKSearchScope createWorkspaceScope(
IDLTKLanguageToolkit toolkit) {
return BasicSearchEngine.createWorkspaceScope(toolkit);
}
/**
* Returns a new default Script search participant.
*
* @return a new default Script search participant
*
*/
public static SearchParticipant getDefaultSearchParticipant() {
return BasicSearchEngine.getDefaultSearchParticipant();
}
/**
* Searches for matches of a given search pattern. Search patterns can be
* created using helper methods (from a String pattern or a Script element)
* and encapsulate the description of what is being searched (for example,
* search method declarations in a case sensitive way).
*
* @param pattern
* the pattern to search
* @param participants
* the particpants in the search
* @param scope
* the search scope
* @param requestor
* the requestor to report the matches to
* @param monitor
* the progress monitor used to report progress
* @exception CoreException
* if the search failed. Reasons include:
* <ul>
* <li>the buildpath is incorrectly set</li>
* </ul>
*
*/
public void search(SearchPattern pattern, SearchParticipant[] participants,
IDLTKSearchScope scope, SearchRequestor requestor,
IProgressMonitor monitor) throws CoreException {
if (this.newSearchEngine.isEnabled(scope.getLanguageToolkit())) {
this.newSearchEngine.search(pattern, participants, scope, requestor,
monitor);
} else {
this.basicEngine.search(pattern, participants, scope, requestor,
monitor);
}
}
public List searchSourceOnly(SearchPattern pattern,
SearchParticipant[] participants, IDLTKSearchScope scope,
IProgressMonitor monitor) throws CoreException {
return this.basicEngine.searchSourceOnly(pattern, participants, scope,
monitor);
}
/**
* Searches for all top-level types and member types in the given scope. The
* search can be selecting specific types (given a package exact full name
* or a type name with specific match mode).
*
* @param packageExactName
* the exact package full name of the searched types.<br>
* If you want to use a prefix or a wild-carded string for
* package, you need to use
* {@link #searchAllTypeNames(char[], int, char[], int, int, IJavaSearchScope, TypeNameRequestor, int, IProgressMonitor)}
* method instead.
* @param typeName
* the dot-separated qualified name of the searched type (the
* qualification include the enclosing types if the searched type
* is a member type), or a prefix for this type, or a wild-carded
* string for this type.
* @param matchRule
* type name match rule one of
* <ul>
* <li>{@link SearchPattern#R_EXACT_MATCH} if the package name
* and type name are the full names of the searched types.</li>
* <li>{@link SearchPattern#R_PREFIX_MATCH} if the package name
* and type name are prefixes of the names of the searched types.
* </li>
* <li>{@link SearchPattern#R_PATTERN_MATCH} if the package name
* and type name contain wild-cards.</li>
* <li>{@link SearchPattern#R_CAMELCASE_MATCH} if type name are
* camel case of the names of the searched types.</li>
* </ul>
* combined with {@link SearchPattern#R_CASE_SENSITIVE}, e.g.
* {@link SearchPattern#R_EXACT_MATCH} |
* {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case
* sensitive match is requested, or
* {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case
* sensitive match is requested.
* @param searchFor
* determines the nature of the searched elements
* <ul>
* <li>{@link IDLTKSearchConstants#CLASS}: only look for
* classes</li>
* <li>{@link IDLTKSearchConstants#INTERFACE}: only look for
* interfaces</li>
* <li>{@link IDLTKSearchConstants#ENUM}: only look for
* enumeration</li>
* <li>{@link IDLTKSearchConstants#ANNOTATION_TYPE}: only look
* for annotation type</li>
* <li>{@link IDLTKSearchConstants#CLASS_AND_ENUM}: only look for
* classes and enumerations</li>
* <li>{@link IDLTKSearchConstants#CLASS_AND_INTERFACE}: only
* look for classes and interfaces</li>
* <li>{@link IDLTKSearchConstants#TYPE}: look for all types (ie.
* classes, interfaces, enum and annotation types)</li>
* </ul>
* @param scope
* the scope to search in
* @param nameRequestor
* the requestor that collects the results of the search
* @param waitingPolicy
* one of
* <ul>
* <li>{@link IDLTKSearchConstants#FORCE_IMMEDIATE_SEARCH} if the
* search should start immediately</li>
* <li>{@link IDLTKSearchConstants#CANCEL_IF_NOT_READY_TO_SEARCH}
* if the search should be cancelled if the underlying indexer
* has not finished indexing the workspace</li>
* <li>{@link IDLTKSearchConstants#WAIT_UNTIL_READY_TO_SEARCH} if
* the search should wait for the underlying indexer to finish
* indexing the workspace</li>
* </ul>
* @param progressMonitor
* the progress monitor to report progress to, or
* <code>null</code> if no progress monitor is provided
* @exception ModelException
* if the search failed. Reasons include:
* <ul>
* <li>the buildpath is incorrectly set</li>
* </ul>
*
*/
public void searchAllTypeNames(final char[] packageExactName,
final char[] typeName, final int matchRule, int searchFor,
IDLTKSearchScope scope, final TypeNameRequestor nameRequestor,
int waitingPolicy, IProgressMonitor progressMonitor)
throws ModelException {
searchAllTypeNames(packageExactName, SearchPattern.R_EXACT_MATCH,
typeName, matchRule, searchFor, scope, nameRequestor,
waitingPolicy, progressMonitor);
}
/**
* Searches for all top-level types and member types in the given scope. The
* search can be selecting specific types (given a package name using
* specific match mode and/or a type name using another specific match
* mode).
*
* @param packageName
* the full name of the package of the searched types, or a
* prefix for this package, or a wild-carded string for this
* package.
* @param typeName
* the dot-separated qualified name of the searched type (the
* qualification include the enclosing types if the searched type
* is a member type), or a prefix for this type, or a wild-carded
* string for this type.
* @param packageMatchRule
* one of
* <ul>
* <li>{@link SearchPattern#R_EXACT_MATCH} if the package name
* and type name are the full names of the searched types.</li>
* <li>{@link SearchPattern#R_PREFIX_MATCH} if the package name
* and type name are prefixes of the names of the searched types.
* </li>
* <li>{@link SearchPattern#R_PATTERN_MATCH} if the package name
* and type name contain wild-cards.</li>
* <li>{@link SearchPattern#R_CAMELCASE_MATCH} if type name are
* camel case of the names of the searched types.</li>
* </ul>
* combined with {@link SearchPattern#R_CASE_SENSITIVE}, e.g.
* {@link SearchPattern#R_EXACT_MATCH} |
* {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case
* sensitive match is requested, or
* {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case
* sensitive match is requested.
* @param typeMatchRule
* one of
* <ul>
* <li>{@link SearchPattern#R_EXACT_MATCH} if the package name
* and type name are the full names of the searched types.</li>
* <li>{@link SearchPattern#R_PREFIX_MATCH} if the package name
* and type name are prefixes of the names of the searched types.
* </li>
* <li>{@link SearchPattern#R_PATTERN_MATCH} if the package name
* and type name contain wild-cards.</li>
* <li>{@link SearchPattern#R_CAMELCASE_MATCH} if type name are
* camel case of the names of the searched types.</li>
* </ul>
* combined with {@link SearchPattern#R_CASE_SENSITIVE}, e.g.
* {@link SearchPattern#R_EXACT_MATCH} |
* {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case
* sensitive match is requested, or
* {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case
* sensitive match is requested.
* @param searchFor
* determines the nature of the searched elements
* <ul>
* <li>{@link IDLTKSearchConstants#CLASS}: only look for
* classes</li>
* <li>{@link IDLTKSearchConstants#INTERFACE}: only look for
* interfaces</li>
* <li>{@link IDLTKSearchConstants#ENUM}: only look for
* enumeration</li>
* <li>{@link IDLTKSearchConstants#ANNOTATION_TYPE}: only look
* for annotation type</li>
* <li>{@link IDLTKSearchConstants#CLASS_AND_ENUM}: only look for
* classes and enumerations</li>
* <li>{@link IDLTKSearchConstants#CLASS_AND_INTERFACE}: only
* look for classes and interfaces</li>
* <li>{@link IDLTKSearchConstants#TYPE}: look for all types (ie.
* classes, interfaces, enum and annotation types)</li>
* </ul>
* @param scope
* the scope to search in
* @param nameRequestor
* the requestor that collects the results of the search
* @param waitingPolicy
* one of
* <ul>
* <li>{@link IDLTKSearchConstants#FORCE_IMMEDIATE_SEARCH} if the
* search should start immediately</li>
* <li>{@link IDLTKSearchConstants#CANCEL_IF_NOT_READY_TO_SEARCH}
* if the search should be cancelled if the underlying indexer
* has not finished indexing the workspace</li>
* <li>{@link IDLTKSearchConstants#WAIT_UNTIL_READY_TO_SEARCH} if
* the search should wait for the underlying indexer to finish
* indexing the workspace</li>
* </ul>
* @param progressMonitor
* the progress monitor to report progress to, or
* <code>null</code> if no progress monitor is provided
* @exception ModelException
* if the search failed. Reasons include:
* <ul>
* <li>the buildpath is incorrectly set</li>
* </ul>
*
*/
public void searchAllTypeNames(final char[] packageName,
final int packageMatchRule, final char[] typeName,
final int typeMatchRule, int searchFor, IDLTKSearchScope scope,
final TypeNameRequestor nameRequestor, int waitingPolicy,
IProgressMonitor progressMonitor) throws ModelException {
TypeNameRequestorWrapper requestorWrapper = new TypeNameRequestorWrapper(
nameRequestor);
this.basicEngine.searchAllTypeNames(packageName, packageMatchRule,
typeName, typeMatchRule, searchFor, scope, requestorWrapper,
waitingPolicy, progressMonitor);
}
/**
* Searches for all top-level types and member types in the given scope. The
* search can be selecting specific types (given a package name using
* specific match mode and/or a type name using another specific match
* mode).
* <p>
* Provided {@link TypeNameMatchRequestor} requestor will collect
* {@link TypeNameMatch} matches found during the search.
* </p>
*
* @param packageName
* the full name of the package of the searched types, or a
* prefix for this package, or a wild-carded string for this
* package. May be <code>null</code>, then any package name is
* accepted.
* @param packageMatchRule
* one of
* <ul>
* <li>{@link SearchPattern#R_EXACT_MATCH} if the package name
* and type name are the full names of the searched types.</li>
* <li>{@link SearchPattern#R_PREFIX_MATCH} if the package name
* and type name are prefixes of the names of the searched types.
* </li>
* <li>{@link SearchPattern#R_PATTERN_MATCH} if the package name
* and type name contain wild-cards.</li>
* <li>{@link SearchPattern#R_CAMELCASE_MATCH} if type name are
* camel case of the names of the searched types.</li>
* </ul>
* combined with {@link SearchPattern#R_CASE_SENSITIVE}, e.g.
* {@link SearchPattern#R_EXACT_MATCH} |
* {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case
* sensitive match is requested, or
* {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case
* sensitive match is requested.
* @param typeName
* the dot-separated qualified name of the searched type (the
* qualification include the enclosing types if the searched type
* is a member type), or a prefix for this type, or a wild-carded
* string for this type. May be <code>null</code>, then any type
* name is accepted.
* @param typeMatchRule
* one of
* <ul>
* <li>{@link SearchPattern#R_EXACT_MATCH} if the package name
* and type name are the full names of the searched types.</li>
* <li>{@link SearchPattern#R_PREFIX_MATCH} if the package name
* and type name are prefixes of the names of the searched types.
* </li>
* <li>{@link SearchPattern#R_PATTERN_MATCH} if the package name
* and type name contain wild-cards.</li>
* <li>{@link SearchPattern#R_CAMELCASE_MATCH} if type name are
* camel case of the names of the searched types.</li>
* </ul>
* combined with {@link SearchPattern#R_CASE_SENSITIVE}, e.g.
* {@link SearchPattern#R_EXACT_MATCH} |
* {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case
* sensitive match is requested, or
* {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case
* sensitive match is requested.
* @param searchFor
* determines the nature of the searched elements
* <ul>
* <li>{@link IJavaSearchConstants#CLASS}: only look for
* classes</li>
* <li>{@link IJavaSearchConstants#INTERFACE}: only look for
* interfaces</li>
* <li>{@link IJavaSearchConstants#ENUM}: only look for
* enumeration</li>
* <li>{@link IJavaSearchConstants#ANNOTATION_TYPE}: only look
* for annotation type</li>
* <li>{@link IJavaSearchConstants#CLASS_AND_ENUM}: only look for
* classes and enumerations</li>
* <li>{@link IJavaSearchConstants#CLASS_AND_INTERFACE}: only
* look for classes and interfaces</li>
* <li>{@link IJavaSearchConstants#TYPE}: look for all types (ie.
* classes, interfaces, enum and annotation types)</li>
* </ul>
* @param scope
* the scope to search in
* @param nameMatchRequestor
* the {@link TypeNameMatchRequestor requestor} that collects
* {@link TypeNameMatch matches} of the search.
* @param waitingPolicy
* one of
* <ul>
* <li>{@link IJavaSearchConstants#FORCE_IMMEDIATE_SEARCH} if the
* search should start immediately</li>
* <li>{@link IJavaSearchConstants#CANCEL_IF_NOT_READY_TO_SEARCH}
* if the search should be cancelled if the underlying indexer
* has not finished indexing the workspace</li>
* <li>{@link IJavaSearchConstants#WAIT_UNTIL_READY_TO_SEARCH} if
* the search should wait for the underlying indexer to finish
* indexing the workspace</li>
* </ul>
* @param progressMonitor
* the progress monitor to report progress to, or
* <code>null</code> if no progress monitor is provided
* @exception JavaModelException
* if the search failed. Reasons include:
* <ul>
* <li>the classpath is incorrectly set</li>
* </ul>
* @since 3.3
*/
public void searchAllTypeNames(final char[] packageName,
final int packageMatchRule, final char[] typeName,
final int typeMatchRule, int searchFor, IDLTKSearchScope scope,
final TypeNameMatchRequestor nameMatchRequestor, int waitingPolicy,
IProgressMonitor progressMonitor) throws ModelException {
TypeNameMatchRequestorWrapper requestorWrapper = new TypeNameMatchRequestorWrapper(
nameMatchRequestor, scope);
this.basicEngine.searchAllTypeNames(packageName, packageMatchRule,
typeName, typeMatchRule, searchFor, scope, requestorWrapper,
waitingPolicy, progressMonitor);
}
/**
* Searches for all top-level types and member types in the given scope
* matching any of the given qualifications and type names in a case
* sensitive way.
*
* @param qualifications
* the qualified name of the package/enclosing type of the
* searched types
* @param typeNames
* the simple names of the searched types
* @param scope
* the scope to search in
* @param nameRequestor
* the requestor that collects the results of the search
* @param waitingPolicy
* one of
* <ul>
* <li>{@link IDLTKSearchConstants#FORCE_IMMEDIATE_SEARCH} if the
* search should start immediately</li>
* <li>{@link IDLTKSearchConstants#CANCEL_IF_NOT_READY_TO_SEARCH}
* if the search should be cancelled if the underlying indexer
* has not finished indexing the workspace</li>
* <li>{@link IDLTKSearchConstants#WAIT_UNTIL_READY_TO_SEARCH} if
* the search should wait for the underlying indexer to finish
* indexing the workspace</li>
* </ul>
* @param progressMonitor
* the progress monitor to report progress to, or
* <code>null</code> if no progress monitor is provided
* @exception ModelException
* if the search failed. Reasons include:
* <ul>
* <li>the buildpath is incorrectly set</li>
* </ul>
*
*/
public void searchAllTypeNames(final char[][] qualifications,
final char[][] typeNames, IDLTKSearchScope scope,
final TypeNameRequestor nameRequestor, int waitingPolicy,
IProgressMonitor progressMonitor) throws ModelException {
TypeNameRequestorWrapper requestorWrapper = new TypeNameRequestorWrapper(
nameRequestor);
this.basicEngine.searchAllTypeNames(qualifications, typeNames,
SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE,
IDLTKSearchConstants.TYPE, scope, requestorWrapper,
waitingPolicy, progressMonitor);
}
/**
* Searches for all top-level types and member types in the given scope
* matching any of the given qualifications and type names in a case
* sensitive way.
* <p>
* Provided {@link TypeNameMatchRequestor} requestor will collect
* {@link TypeNameMatch} matches found during the search.
* </p>
*
* @param qualifications
* the qualified name of the package/enclosing type of the
* searched types. May be <code>null</code>, then any package
* name is accepted.
* @param typeNames
* the simple names of the searched types. If this parameter is
* <code>null</code>, then no type will be found.
* @param scope
* the scope to search in
* @param nameMatchRequestor
* the {@link TypeNameMatchRequestor requestor} that collects
* {@link TypeNameMatch matches} of the search.
* @param waitingPolicy
* one of
* <ul>
* <li>{@link IJavaSearchConstants#FORCE_IMMEDIATE_SEARCH} if the
* search should start immediately</li>
* <li>{@link IJavaSearchConstants#CANCEL_IF_NOT_READY_TO_SEARCH}
* if the search should be cancelled if the underlying indexer
* has not finished indexing the workspace</li>
* <li>{@link IJavaSearchConstants#WAIT_UNTIL_READY_TO_SEARCH} if
* the search should wait for the underlying indexer to finish
* indexing the workspace</li>
* </ul>
* @param progressMonitor
* the progress monitor to report progress to, or
* <code>null</code> if no progress monitor is provided
* @exception JavaModelException
* if the search failed. Reasons include:
* <ul>
* <li>the classpath is incorrectly set</li>
* </ul>
*/
public void searchAllTypeNames(final char[][] qualifications,
final char[][] typeNames, IDLTKSearchScope scope,
final TypeNameMatchRequestor nameMatchRequestor, int waitingPolicy,
IProgressMonitor progressMonitor) throws ModelException {
TypeNameMatchRequestorWrapper requestorWrapper = new TypeNameMatchRequestorWrapper(
nameMatchRequestor, scope);
this.basicEngine.searchAllTypeNames(qualifications, typeNames,
SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE,
IDLTKSearchConstants.TYPE, scope, requestorWrapper,
waitingPolicy, progressMonitor);
}
/**
* Searches for all declarations of the fields accessed in the given
* element. The element can be a compilation unit, a source type, or a
* source method. Reports the field declarations using the given requestor.
* <p>
* Consider the following code: <code>
* <pre>
* class A {
* int field1;
* }
*
* class B extends A {
* String value;
* }
*
* class X {
* void test() {
* B b = new B();
* System.out.println(b.value + b.field1);
* };
* }
* </pre>
* </code> then searching for declarations of accessed fields in method
* <code>X.test()</code> would collect the fields <code>B.value</code> and
* <code>A.field1</code>.
* </p>
*
* @param enclosingElement
* the method, type, or compilation unit to be searched in
* @param requestor
* a callback object to which each match is reported
* @param monitor
* the progress monitor used to report progress
* @exception ModelException
* if the search failed. Reasons include:
* <ul>
* <li>the element doesn't exist</li>
* <li>the buildpath is incorrectly set</li>
* </ul>
*
*/
public void searchDeclarationsOfAccessedFields(
IModelElement enclosingElement, SearchRequestor requestor,
IProgressMonitor monitor) throws ModelException {
this.basicEngine.searchDeclarationsOfAccessedFields(enclosingElement,
requestor, monitor);
}
/**
* Searches for all declarations of the types referenced in the given
* element. The element can be a compilation unit, a source type, or a
* source method. Reports the type declarations using the given requestor.
* <p>
* Consider the following code: <code>
* <pre>
* class A {
* }
*
* class B extends A {
* }
*
* interface I {
* int VALUE = 0;
* }
*
* class X {
* void test() {
* B b = new B();
* this.foo(b, I.VALUE);
* };
* }
* </pre>
* </code> then searching for declarations of referenced types in method
* <code>X.test()</code> would collect the class <code>B</code> and the
* interface <code>I</code>.
* </p>
*
* @param enclosingElement
* the method, type, or compilation unit to be searched in
* @param requestor
* a callback object to which each match is reported
* @param monitor
* the progress monitor used to report progress
* @exception ModelException
* if the search failed. Reasons include:
* <ul>
* <li>the element doesn't exist</li>
* <li>the buildpath is incorrectly set</li>
* </ul>
*
*/
public void searchDeclarationsOfReferencedTypes(
IModelElement enclosingElement, SearchRequestor requestor,
IProgressMonitor monitor) throws ModelException {
this.basicEngine.searchDeclarationsOfReferencedTypes(enclosingElement,
requestor, monitor);
}
/**
* Searches for all declarations of the methods invoked in the given
* element. The element can be a compilation unit, a source type, or a
* source method. Reports the method declarations using the given requestor.
* <p>
* Consider the following code: <code>
* <pre>
* class A {
* void foo() {
* };
*
* void bar() {
* };
* }
*
* class B extends A {
* void foo() {
* };
* }
*
* class X {
* void test() {
* A a = new B();
* a.foo();
* B b = (B) a;
* b.bar();
* };
* }
* </pre>
* </code> then searching for declarations of sent messages in method
* <code>X.test()</code> would collect the methods <code>A.foo()</code>,
* <code>B.foo()</code>, and <code>A.bar()</code>.
* </p>
*
* @param enclosingElement
* the method, type, or compilation unit to be searched in
* @param requestor
* a callback object to which each match is reported
* @param monitor
* the progress monitor used to report progress
* @exception ModelException
* if the search failed. Reasons include:
* <ul>
* <li>the element doesn't exist</li>
* <li>the buildpath is incorrectly set</li>
* </ul>
*
*/
public void searchDeclarationsOfSentMessages(IModelElement enclosingElement,
SearchRequestor requestor, IProgressMonitor monitor)
throws ModelException {
this.basicEngine.searchDeclarationsOfSentMessages(enclosingElement,
requestor, monitor);
}
public static ISourceModule[] searchMixinSources(
final IDLTKSearchScope scope, String key,
IDLTKLanguageToolkit toolkit,
final Map<ISourceModule, Set<String>> keysByModule) {
return searchMixinSources(scope, key, toolkit, keysByModule,
new NullProgressMonitor());
}
/**
* @param scope
* @param searchPattern
* @param toolkit
* @param keysByModule
* is filled with search results if not <code>null</code>
* @param monitor
* @return
* @since 2.0
*/
public static ISourceModule[] searchMixinSources(
final IDLTKSearchScope scope, String searchPattern,
IDLTKLanguageToolkit toolkit,
final Map<ISourceModule, Set<String>> keysByModule,
IProgressMonitor monitor) {
PerformanceNode p = RuntimePerformanceMonitor.begin();
final long startTime = DLTKCore.VERBOSE_MIXIN
? System.currentTimeMillis()
: 0;
// Index requestor
final Map<String, ISourceModule> processed = new HashMap<>();
IndexQueryRequestor searchRequestor = new IndexQueryRequestor() {
final HandleFactory factory = new HandleFactory();
final Set<String> searched = new HashSet<>();
@Override
public boolean acceptIndexMatch(String documentPath,
SearchPattern indexRecord, SearchParticipant participant,
AccessRuleSet access) {
// String s = IBuildpathEntry.BUILTIN_EXTERNAL_ENTRY.toString();
final int indexSeparator = documentPath
.indexOf(IDLTKSearchScope.FILE_ENTRY_SEPARATOR);
if (indexSeparator != -1) {
documentPath = documentPath.substring(indexSeparator + 1);
}
ISourceModule module = processed.get(documentPath);
if (module == null) {
if (!searched.add(documentPath)) {
return true;
}
Openable openable = factory.createOpenable(documentPath,
scope);
if (openable == null
|| !(openable instanceof ISourceModule)) {
return true;
}
module = (ISourceModule) openable;
processed.put(documentPath, module);
}
if (keysByModule != null) {
final String val = new String(indexRecord.getIndexKey());
final Set<String> keys;
if (keysByModule.containsKey(module)) {
keys = keysByModule.get(module);
} else {
keys = new HashSet<>();
keysByModule.put(module, keys);
}
keys.add(val);
}
return true;
}
};
IndexManager indexManager = ModelManager.getModelManager()
.getIndexManager();
MixinPattern pattern = new MixinPattern(searchPattern.toCharArray(),
SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE
| SearchPattern.R_PATTERN_MATCH,
toolkit);
SearchParticipant participant = SearchEngine
.getDefaultSearchParticipant();
participant.selectMixinIndexes(pattern, scope);
// add type names from indexes
indexManager.performConcurrentJob(
new PatternSearchJob(pattern, participant, // Script search only
scope, searchRequestor),
IDLTKSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor);
if (DLTKCore.VERBOSE_MIXIN) {
final String msg = "mixin search for \"{0}\": {1} results in {2} ms";//$NON-NLS-1$
System.out.println(NLS.bind(msg, new Object[] { searchPattern,
String.valueOf(processed.size()),
Long.toString(System.currentTimeMillis() - startTime) }));
}
p.done(toolkit.getNatureId(), "Search mixin modules", 0); //$NON-NLS-1$
return processed.values().toArray(new ISourceModule[processed.size()]);
}
/**
* @since 2.0
*/
public static ISourceModule[] searchMixinSources(
final IDLTKSearchScope scope, String key,
IDLTKLanguageToolkit toolkit, IProgressMonitor monitor) {
return searchMixinSources(scope, key, toolkit, null, monitor);
}
public static ISourceModule[] searchMixinSources(
final IDLTKSearchScope scope, String key,
IDLTKLanguageToolkit toolkit) {
return searchMixinSources(scope, key, toolkit, null,
new NullProgressMonitor());
}
public static String[] searchMixinPatterns(final IDLTKSearchScope scope,
String key, IDLTKLanguageToolkit toolkit) {
// Index requestor
final List<String> result = new ArrayList<>();
IndexQueryRequestor searchRequestor = new IndexQueryRequestor() {
@Override
public boolean acceptIndexMatch(String documentPath,
SearchPattern indexRecord, SearchParticipant participant,
AccessRuleSet access) {
String val = new String(indexRecord.getIndexKey());
if (!result.contains(val)) {
result.add(val);
}
return true;
}
};
IndexManager indexManager = ModelManager.getModelManager()
.getIndexManager();
int flags = SearchPattern.R_EXACT_MATCH
| SearchPattern.R_CASE_SENSITIVE;
if (key.indexOf('*') != -1 || key.indexOf('?') != -1)
flags |= SearchPattern.R_PATTERN_MATCH;
MixinPattern pattern = new MixinPattern(key.toCharArray(), flags,
toolkit);
SearchParticipant participant = SearchEngine
.getDefaultSearchParticipant();
participant.selectMixinIndexes(pattern, scope);
// add type names from indexes
indexManager.performConcurrentJob(
new PatternSearchJob(pattern, participant, // Script search only
scope, searchRequestor),
IDLTKSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, null);
return result.toArray(new String[result.size()]);
}
/**
* Create a method name match on a given type with specific modifiers.
*
* @param type
* The java model handle of the type
* @param modifiers
* Modifiers of the method
* @return A non-null match on the given method.
*/
public static MethodNameMatch createMethodNameMatch(IMethod method,
int modifiers) {
return BasicSearchEngine.createMethodNameMatch(method, modifiers);
}
/**
* Searches for all top-level methods (aka functions) in the given scope.
* The search can be selecting specific methods (given a package name using
* specific match mode and/or a method name using another specific match
* mode).
*
* @param packageName
* the full name of the package of the searched methods, or a
* prefix for this package, or a wild-carded string for this
* package.
* @param methodName
* the dot-separated qualified name of the searched method, or a
* prefix for this method, or a wild-carded string for this
* method.
* @param packageMatchRule
* one of
* <ul>
* <li>{@link SearchPattern#R_EXACT_MATCH} if the package name
* and method name are the full names of the searched
* method.</li>
* <li>{@link SearchPattern#R_PREFIX_MATCH} if the package name
* and method name are prefixes of the names of the searched
* methods.</li>
* <li>{@link SearchPattern#R_PATTERN_MATCH} if the package name
* and method name contain wild-cards.</li>
* <li>{@link SearchPattern#R_CAMELCASE_MATCH} if method name are
* camel case of the names of the searched methods.</li>
* </ul>
* combined with {@link SearchPattern#R_CASE_SENSITIVE}, e.g.
* {@link SearchPattern#R_EXACT_MATCH} |
* {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case
* sensitive match is requested, or
* {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case
* sensitive match is requested.
* @param methodMatchRule
* one of
* <ul>
* <li>{@link SearchPattern#R_EXACT_MATCH} if the package name
* and method name are the full names of the searched
* methods.</li>
* <li>{@link SearchPattern#R_PREFIX_MATCH} if the package name
* and method name are prefixes of the names of the searched
* methods.</li>
* <li>{@link SearchPattern#R_PATTERN_MATCH} if the package name
* and method name contain wild-cards.</li>
* <li>{@link SearchPattern#R_CAMELCASE_MATCH} if method name are
* camel case of the names of the searched methods.</li>
* </ul>
* combined with {@link SearchPattern#R_CASE_SENSITIVE}, e.g.
* {@link SearchPattern#R_EXACT_MATCH} |
* {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case
* sensitive match is requested, or
* {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case
* sensitive match is requested.
* @param searchFor
* determines the nature of the searched elements
* <ul>
* <li>{@link IDLTKSearchConstants#METHOD}: only look for methods
* </li>
* </ul>
* @param scope
* the scope to search in
* @param nameRequestor
* the requestor that collects the results of the search
* @param waitingPolicy
* one of
* <ul>
* <li>{@link IDLTKSearchConstants#FORCE_IMMEDIATE_SEARCH} if the
* search should start immediately</li>
* <li>{@link IDLTKSearchConstants#CANCEL_IF_NOT_READY_TO_SEARCH}
* if the search should be cancelled if the underlying indexer
* has not finished indexing the workspace</li>
* <li>{@link IDLTKSearchConstants#WAIT_UNTIL_READY_TO_SEARCH} if
* the search should wait for the underlying indexer to finish
* indexing the workspace</li>
* </ul>
* @param progressMonitor
* the progress monitor to report progress to, or
* <code>null</code> if no progress monitor is provided
* @exception ModelException
* if the search failed. Reasons include:
* <ul>
* <li>the buildpath is incorrectly set</li>
* </ul>
*
*/
public void searchAllMethodNames(final char[] methodName,
final int methodMatchRule, int searchFor, IDLTKSearchScope scope,
final MethodNameMatchRequestor nameRequestor, int waitingPolicy,
IProgressMonitor progressMonitor) throws ModelException {
MethodNameMatchRequestorWrapper requestorWrapper = new MethodNameMatchRequestorWrapper(
nameRequestor, scope);
this.basicEngine.searchAllMethodNames(methodName, methodMatchRule,
searchFor, scope, requestorWrapper, waitingPolicy,
progressMonitor);
}
/**
* Searches for all top-level methods (aka functions) in the given scope.
* The search can be selecting specific methods (given a package name using
* specific match mode and/or a method name using another specific match
* mode).
*
* @param packageName
* the full name of the package of the searched methods, or a
* prefix for this package, or a wild-carded string for this
* package.
* @param methodName
* the dot-separated qualified name of the searched method, or a
* prefix for this method, or a wild-carded string for this
* method.
* @param packageMatchRule
* one of
* <ul>
* <li>{@link SearchPattern#R_EXACT_MATCH} if the package name
* and method name are the full names of the searched
* method.</li>
* <li>{@link SearchPattern#R_PREFIX_MATCH} if the package name
* and method name are prefixes of the names of the searched
* methods.</li>
* <li>{@link SearchPattern#R_PATTERN_MATCH} if the package name
* and method name contain wild-cards.</li>
* <li>{@link SearchPattern#R_CAMELCASE_MATCH} if method name are
* camel case of the names of the searched methods.</li>
* </ul>
* combined with {@link SearchPattern#R_CASE_SENSITIVE}, e.g.
* {@link SearchPattern#R_EXACT_MATCH} |
* {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case
* sensitive match is requested, or
* {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case
* sensitive match is requested.
* @param methodMatchRule
* one of
* <ul>
* <li>{@link SearchPattern#R_EXACT_MATCH} if the package name
* and method name are the full names of the searched
* methods.</li>
* <li>{@link SearchPattern#R_PREFIX_MATCH} if the package name
* and method name are prefixes of the names of the searched
* methods.</li>
* <li>{@link SearchPattern#R_PATTERN_MATCH} if the package name
* and method name contain wild-cards.</li>
* <li>{@link SearchPattern#R_CAMELCASE_MATCH} if method name are
* camel case of the names of the searched methods.</li>
* </ul>
* combined with {@link SearchPattern#R_CASE_SENSITIVE}, e.g.
* {@link SearchPattern#R_EXACT_MATCH} |
* {@link SearchPattern#R_CASE_SENSITIVE} if an exact and case
* sensitive match is requested, or
* {@link SearchPattern#R_PREFIX_MATCH} if a prefix non case
* sensitive match is requested.
* @param searchFor
* determines the nature of the searched elements
* <ul>
* <li>{@link IDLTKSearchConstants#METHOD}: only look for methods
* </li>
* </ul>
* @param scope
* the scope to search in
* @param nameRequestor
* the requestor that collects the results of the search
* @param waitingPolicy
* one of
* <ul>
* <li>{@link IDLTKSearchConstants#FORCE_IMMEDIATE_SEARCH} if the
* search should start immediately</li>
* <li>{@link IDLTKSearchConstants#CANCEL_IF_NOT_READY_TO_SEARCH}
* if the search should be cancelled if the underlying indexer
* has not finished indexing the workspace</li>
* <li>{@link IDLTKSearchConstants#WAIT_UNTIL_READY_TO_SEARCH} if
* the search should wait for the underlying indexer to finish
* indexing the workspace</li>
* </ul>
* @param progressMonitor
* the progress monitor to report progress to, or
* <code>null</code> if no progress monitor is provided
* @exception ModelException
* if the search failed. Reasons include:
* <ul>
* <li>the buildpath is incorrectly set</li>
* </ul>
*
*/
public void searchAllMethodNames(final char[] methodName,
final int methodMatchRule, int searchFor, IDLTKSearchScope scope,
final MethodNameRequestor nameRequestor, int waitingPolicy,
IProgressMonitor progressMonitor) throws ModelException {
MethodNameRequestorWrapper requestorWrapper = new MethodNameRequestorWrapper(
nameRequestor);
this.basicEngine.searchAllMethodNames(methodName, methodMatchRule,
searchFor, scope, requestorWrapper, waitingPolicy,
progressMonitor);
}
}