blob: 41ebc138bb156ddced6be7bd2d7db96f641b940b [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.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.dltk.ast.declarations.TypeDeclaration;
import org.eclipse.dltk.compiler.CharOperation;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.IMember;
import org.eclipse.dltk.core.IMethod;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IProjectFragment;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.WorkingCopyOwner;
import org.eclipse.dltk.core.search.indexing.IIndexConstants;
import org.eclipse.dltk.core.search.indexing.IndexManager;
import org.eclipse.dltk.core.search.matching.ModuleFactory;
import org.eclipse.dltk.internal.compiler.env.AccessRestriction;
import org.eclipse.dltk.internal.compiler.env.AccessRuleSet;
import org.eclipse.dltk.internal.core.DefaultWorkingCopyOwner;
import org.eclipse.dltk.internal.core.ModelManager;
import org.eclipse.dltk.internal.core.ScriptProject;
import org.eclipse.dltk.internal.core.SourceModule;
import org.eclipse.dltk.internal.core.search.DLTKSearchDocument;
import org.eclipse.dltk.internal.core.search.DLTKSearchMethodNameMatch;
import org.eclipse.dltk.internal.core.search.DLTKSearchScope;
import org.eclipse.dltk.internal.core.search.DLTKSearchTypeNameMatch;
import org.eclipse.dltk.internal.core.search.HierarchyScope;
import org.eclipse.dltk.internal.core.search.IRestrictedAccessMethodRequestor;
import org.eclipse.dltk.internal.core.search.IRestrictedAccessTypeRequestor;
import org.eclipse.dltk.internal.core.search.IndexQueryRequestor;
import org.eclipse.dltk.internal.core.search.PathCollector;
import org.eclipse.dltk.internal.core.search.PatternSearchJob;
import org.eclipse.dltk.internal.core.search.SuperHierarchyScope;
import org.eclipse.dltk.internal.core.search.matching.DLTKSearchPattern;
import org.eclipse.dltk.internal.core.search.matching.MethodDeclarationPattern;
import org.eclipse.dltk.internal.core.search.matching.QualifiedTypeDeclarationPattern;
import org.eclipse.dltk.internal.core.search.matching.TypeDeclarationPattern;
import org.eclipse.dltk.internal.core.util.Messages;
import org.eclipse.dltk.internal.core.util.Util;
import org.eclipse.osgi.util.NLS;
/**
* Search basic engine. Public search engine now uses basic engine
* functionalities. Note that serch basic engine does not implement deprecated
* functionalities...
*/
public class BasicSearchEngine {
/*
* A default parseor to parse non-reconciled working copies
*/
/*
* A list of working copies that take precedence over their original
* compilation units.
*/
private ISourceModule[] workingCopies;
/*
* A working copy owner whose working copies will take precedent over their
* original compilation units.
*/
private WorkingCopyOwner workingCopyOwner;
/**
* For tracing purpose.
*/
public static boolean VERBOSE = DLTKCore.VERBOSE_SEARCH;
/*
* Creates a new search basic engine.
*/
public BasicSearchEngine() {
// will use working copies of PRIMARY owner
}
/**
* @see SearchEngine#SearchEngine(ISourceModule[]) for detailed comment.
*/
public BasicSearchEngine(ISourceModule[] workingCopies) {
this.workingCopies = workingCopies;
}
char convertTypeKind(int typeDeclarationKind) {
switch (typeDeclarationKind) {
case TypeDeclaration.D_CLASS:
return IIndexConstants.TYPE_SUFFIX;
default:
return IIndexConstants.TYPE_SUFFIX;
}
}
/**
* @see SearchEngine#SearchEngine(WorkingCopyOwner) for detailed comment.
*/
public BasicSearchEngine(WorkingCopyOwner workingCopyOwner) {
this.workingCopyOwner = workingCopyOwner;
}
/**
* @see SearchEngine#createHierarchyScope(IType) for detailed comment.
*/
public static IDLTKSearchScope createHierarchyScope(IType type)
throws ModelException {
return createHierarchyScope(type, DefaultWorkingCopyOwner.PRIMARY);
}
/**
* @see SearchEngine#createHierarchyScope(IType,WorkingCopyOwner) for
* detailed comment.
*/
public static IDLTKSearchScope createHierarchyScope(IType type,
WorkingCopyOwner owner) throws ModelException {
IDLTKLanguageToolkit toolkit;
toolkit = DLTKLanguageManager.getLanguageToolkit(type);
return new HierarchyScope(toolkit, type, owner);
}
/**
* @see SearchEngine#createSuperHierarchyScope(IType) for detailed comment.
*/
public static IDLTKSearchScope createSuperHierarchyScope(IType type)
throws ModelException {
return createSuperHierarchyScope(type, DefaultWorkingCopyOwner.PRIMARY);
}
/**
* @see SearchEngine#createSuperHierarchyScope(IType,WorkingCopyOwner) for
* detailed comment.
*/
public static IDLTKSearchScope createSuperHierarchyScope(IType type,
WorkingCopyOwner owner) throws ModelException {
IDLTKLanguageToolkit toolkit;
toolkit = DLTKLanguageManager.getLanguageToolkit(type);
return new SuperHierarchyScope(toolkit, type, owner);
}
/**
* @see SearchEngine#createSearchScope(IModelElement[]) for detailed
* comment.
*/
public static IDLTKSearchScope createSearchScope(IModelElement[] elements,
IDLTKLanguageToolkit toolkit) {
return createSearchScope(elements, true, toolkit);
}
public static IDLTKSearchScope createSearchScope(IModelElement element) {
return createSearchScope(new IModelElement[] { element }, true,
DLTKLanguageManager.getLanguageToolkit(element));
}
/**
* @see SearchEngine#createSearchScope(IModelElement[], boolean) for
* detailed comment.
*/
public static IDLTKSearchScope createSearchScope(IModelElement[] elements,
boolean includeReferencedProjects, IDLTKLanguageToolkit toolkit) {
int includeMask = IDLTKSearchScope.SOURCES
| IDLTKSearchScope.APPLICATION_LIBRARIES
| IDLTKSearchScope.SYSTEM_LIBRARIES;
if (includeReferencedProjects) {
includeMask |= IDLTKSearchScope.REFERENCED_PROJECTS;
}
return createSearchScope(elements, includeMask, toolkit);
}
/**
* @see SearchEngine#createSearchScope(IModelElement[], int) for detailed
* comment.
*/
public static IDLTKSearchScope createSearchScope(IModelElement[] elements,
int includeMask, IDLTKLanguageToolkit toolkit) {
DLTKSearchScope scope = new DLTKSearchScope(toolkit);
// For EMPTY CASE
if (toolkit != null) {
HashSet<IProject> visitedProjects = new HashSet<>(2);
for (int i = 0; i < elements.length; i++) {
IModelElement element = elements[i];
if (element != null) {
try {
if (element instanceof ScriptProject) {
scope.add((ScriptProject) element, includeMask,
visitedProjects);
} else {
scope.add(element);
}
} catch (ModelException e) {
// ignore
}
}
}
}
return scope;
}
/**
* @see SearchEngine#createTypeNameMatch(IType, int) for detailed comment.
*/
public static TypeNameMatch createTypeNameMatch(IType type, int modifiers) {
return new DLTKSearchTypeNameMatch(type, modifiers);
}
/**
* @see SearchEngine#createWorkspaceScope() for detailed comment.
*/
public static IDLTKSearchScope createWorkspaceScope(
IDLTKLanguageToolkit toolkit) {
return ModelManager.getModelManager().getWorkspaceScope(toolkit);
}
/**
* Searches for matches to a given query. Search queries 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 scope
* the search result has to be limited to the given scope
* @param requestor
* a callback object to which each match is reported
*/
void findMatches(SearchPattern pattern, SearchParticipant[] participants,
IDLTKSearchScope scope, SearchRequestor requestor,
IProgressMonitor monitor) throws CoreException {
if (monitor != null && monitor.isCanceled()) {
throw new OperationCanceledException();
}
if (VERBOSE) {
Util.verbose("Searching for pattern: " + pattern.toString()); //$NON-NLS-1$
Util.verbose(scope.toString());
}
if (participants == null) {
if (VERBOSE) {
Util.verbose("No participants => do nothing!"); //$NON-NLS-1$
}
return;
}
int length = participants.length;
if (monitor != null)
monitor.beginTask(Messages.engine_searching, 100 * length);
IndexManager indexManager = ModelManager.getModelManager()
.getIndexManager();
try {
requestor.beginReporting();
for (int i = 0; i < participants.length; i++) {
SearchParticipant participant = participants[i];
if (monitor != null && monitor.isCanceled()) {
throw new OperationCanceledException();
}
try {
if (monitor != null)
monitor.subTask(
NLS.bind(Messages.engine_searching_indexing,
participant.getDescription()));
participant.beginSearching();
requestor.enterParticipant(participant);
final String[] indexMatchPaths = collectMatchingPaths(
indexManager, pattern, participant, scope,
monitor == null ? null
: new SubProgressMonitor(monitor, 50));
// locate index matches if any (note that all search matches
// could have been issued during index querying)
if (monitor != null)
monitor.subTask(
NLS.bind(Messages.engine_searching_matching,
participant.getDescription()));
if (indexMatchPaths != null) {
int indexMatchLength = indexMatchPaths.length;
SearchDocument[] indexMatches = new SearchDocument[indexMatchLength];
for (int j = 0; j < indexMatchLength; j++) {
indexMatches[j] = participant
.getDocument(indexMatchPaths[j], null);
}
SearchDocument[] matches = ModuleFactory
.addWorkingCopies(pattern, indexMatches,
getWorkingCopies(), participant);
final Set<IPath> paths = new HashSet<>();
List<SearchDocument> filteredMatches = new ArrayList<>();
for (int q = 0; q < matches.length; ++q) {
IPath path = new Path(matches[q].getPath());
if (paths.add(path)) {
filteredMatches.add(matches[q]);
}
}
SearchDocument[] fmatches = filteredMatches.toArray(
new SearchDocument[filteredMatches.size()]);
participant.locateMatches(fmatches, pattern, scope,
requestor, monitor == null ? null
: new SubProgressMonitor(monitor, 50));
}
} catch (Exception e) {
DLTKCore.error("Error in findMatches()", e); //$NON-NLS-1$
} finally {
requestor.exitParticipant(participant);
participant.doneSearching();
}
}
} catch (Exception e) {
DLTKCore.error("Error in findMatches()", e); //$NON-NLS-1$
} finally {
requestor.endReporting();
if (monitor != null) {
monitor.done();
}
}
}
private String[] collectMatchingPaths(IndexManager indexManager,
SearchPattern pattern, SearchParticipant participant,
IDLTKSearchScope scope, IProgressMonitor monitor) {
final PathCollector pathCollector = new PathCollector();
indexManager.performConcurrentJob(
new PatternSearchJob(pattern, participant, scope,
pathCollector),
IDLTKSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor);
if (monitor != null && monitor.isCanceled())
throw new OperationCanceledException();
return pathCollector.getPaths();
}
List findMatchesSourceOnly(SearchPattern pattern,
SearchParticipant[] participants, IDLTKSearchScope scope,
IProgressMonitor monitor) throws CoreException {
if (monitor != null && monitor.isCanceled()) {
throw new OperationCanceledException();
}
/* initialize progress monitor */
if (monitor != null) {
monitor.beginTask(Messages.engine_searching, 100);
}
if (VERBOSE) {
Util.verbose("Searching for pattern: " + pattern.toString()); //$NON-NLS-1$
Util.verbose(scope.toString());
}
if (participants == null) {
if (VERBOSE) {
Util.verbose("No participants => do nothing!"); //$NON-NLS-1$
}
return null;
}
IndexManager indexManager = ModelManager.getModelManager()
.getIndexManager();
try {
List documents = new ArrayList();
for (int i = 0; i < participants.length; i++) {
SearchParticipant participant = participants[i];
if (monitor != null && monitor.isCanceled()) {
throw new OperationCanceledException();
}
SubProgressMonitor subMonitor = monitor == null ? null
: new SubProgressMonitor(monitor, 1000);
if (subMonitor != null) {
subMonitor.beginTask("", 1000); //$NON-NLS-1$
}
try {
if (subMonitor != null) {
subMonitor.subTask(
NLS.bind(Messages.engine_searching_indexing,
participant.getDescription()));
}
participant.beginSearching();
final String[] indexMatchPaths = collectMatchingPaths(
indexManager, pattern, participant, scope,
subMonitor);
if (indexMatchPaths != null) {
// locate index matches if any (note that all search
// matches
// could have been issued during index querying)
if (subMonitor != null) {
subMonitor.subTask(
NLS.bind(Messages.engine_searching_matching,
participant.getDescription()));
}
int indexMatchLength = indexMatchPaths.length;
SearchDocument[] indexMatches = new SearchDocument[indexMatchLength];
for (int j = 0; j < indexMatchLength; j++) {
indexMatches[j] = participant
.getDocument(indexMatchPaths[j], null);
}
SearchDocument[] matches = ModuleFactory
.addWorkingCopies(pattern, indexMatches,
getWorkingCopies(), participant);
ISourceModule[] modules = participant
.locateModules(matches, scope, subMonitor);
for (int k = 0; k < modules.length; ++k) {
if (!documents.contains(modules[k])) {
documents.add(modules[k]);
}
}
}
} catch (Exception e) {
DLTKCore.error("Error in findMatchesSourceOnly()", e); //$NON-NLS-1$
} finally {
participant.doneSearching();
}
return documents;
}
} catch (Exception e) {
DLTKCore.error("Error in findMatchesSourceOnly()", e); //$NON-NLS-1$
} finally {
if (monitor != null) {
monitor.done();
}
}
return null;
}
/**
* Returns a new default Script search participant.
*
* @return a new default Script search participant
*
*/
public static SearchParticipant getDefaultSearchParticipant() {
return new DLTKSearchParticipant();
}
/**
* @param matchRule
*/
public static String getMatchRuleString(final int matchRule) {
if (matchRule == 0) {
return "R_EXACT_MATCH"; //$NON-NLS-1$
}
StringBuffer buffer = new StringBuffer();
for (int i = 1; i <= 8; i++) {
int bit = matchRule & (1 << (i - 1));
if (bit != 0 && buffer.length() > 0) {
buffer.append(" | "); //$NON-NLS-1$
}
switch (bit) {
case SearchPattern.R_PREFIX_MATCH:
buffer.append("R_PREFIX_MATCH"); //$NON-NLS-1$
break;
case SearchPattern.R_CASE_SENSITIVE:
buffer.append("R_CASE_SENSITIVE"); //$NON-NLS-1$
break;
case SearchPattern.R_EQUIVALENT_MATCH:
buffer.append("R_EQUIVALENT_MATCH"); //$NON-NLS-1$
break;
case SearchPattern.R_ERASURE_MATCH:
buffer.append("R_ERASURE_MATCH"); //$NON-NLS-1$
break;
case SearchPattern.R_FULL_MATCH:
buffer.append("R_FULL_MATCH"); //$NON-NLS-1$
break;
case SearchPattern.R_PATTERN_MATCH:
buffer.append("R_PATTERN_MATCH"); //$NON-NLS-1$
break;
case SearchPattern.R_REGEXP_MATCH:
buffer.append("R_REGEXP_MATCH"); //$NON-NLS-1$
break;
case SearchPattern.R_CAMELCASE_MATCH:
buffer.append("R_CAMELCASE_MATCH"); //$NON-NLS-1$
break;
}
}
return buffer.toString();
}
/**
* Return kind of search corresponding to given value.
*
* @param searchFor
*/
public static String getSearchForString(final int searchFor) {
switch (searchFor) {
case IDLTKSearchConstants.TYPE:
return ("TYPE"); //$NON-NLS-1$
case IDLTKSearchConstants.METHOD:
return ("METHOD"); //$NON-NLS-1$
// case IDLTKSearchConstants.PACKAGE:
// return ("PACKAGE"); //$NON-NLS-1$
// case IDLTKSearchConstants.CONSTRUCTOR:
// return ("CONSTRUCTOR"); //$NON-NLS-1$
case IDLTKSearchConstants.FIELD:
return ("FIELD"); //$NON-NLS-1$
case IDLTKSearchConstants.ANNOTATION_TYPE:
return ("ANNOTATION_TYPE"); //$NON-NLS-1$
}
return "UNKNOWN"; //$NON-NLS-1$
}
// private Parser getParser() {
// if (this.parser == null) {
// this.compilerOptions = new CompilerOptions(JavaCore.getOptions());
// ProblemReporter problemReporter =
// new ProblemReporter(
// DefaultErrorHandlingPolicies.proceedWithAllProblems(),
// this.compilerOptions,
// new DefaultProblemFactory());
// this.parser = new Parser(problemReporter, true);
// }
// return this.parser;
// }
/*
* Returns the list of working copies used by this search engine. Returns
* null if none.
*/
private ISourceModule[] getWorkingCopies() {
ISourceModule[] copies;
if (this.workingCopies != null) {
if (this.workingCopyOwner == null) {
copies = ModelManager.getModelManager().getWorkingCopies(
DefaultWorkingCopyOwner.PRIMARY,
false/*
* don't add primary WCs a second time
*/);
if (copies == null) {
copies = this.workingCopies;
} else {
HashMap pathToCUs = new HashMap();
for (int i = 0; i < copies.length; i++) {
ISourceModule unit = copies[i];
pathToCUs.put(unit.getPath(), unit);
}
for (int i = 0; i < this.workingCopies.length; i++) {
ISourceModule unit = this.workingCopies[i];
pathToCUs.put(unit.getPath(), unit);
}
int length = pathToCUs.size();
copies = new ISourceModule[length];
pathToCUs.values().toArray(copies);
}
} else {
copies = this.workingCopies;
}
} else if (this.workingCopyOwner != null) {
copies = ModelManager.getModelManager().getWorkingCopies(
this.workingCopyOwner, true/* add primary WCs */);
} else {
copies = ModelManager.getModelManager().getWorkingCopies(
DefaultWorkingCopyOwner.PRIMARY,
false/*
* don't add primary WCs a second time
*/);
}
if (copies == null) {
return null;
}
// filter out primary working copies that are saved
ISourceModule[] result = null;
int length = copies.length;
int index = 0;
for (int i = 0; i < length; i++) {
SourceModule copy = (SourceModule) copies[i];
try {
if (!copy.isPrimary() || copy.hasUnsavedChanges()
|| copy.hasResourceChanged()) {
if (result == null) {
result = new ISourceModule[length];
}
result[index++] = copy;
}
} catch (ModelException e) {
// copy doesn't exist: ignore
}
}
if (index != length && result != null) {
System.arraycopy(result, 0, result = new ISourceModule[index], 0,
index);
}
return result;
}
/*
* Returns the list of working copies used to do the search on the given
* Script element.
*/
private ISourceModule[] getWorkingCopies(IModelElement element) {
if (element instanceof IMember) {
ISourceModule cu = ((IMember) element).getSourceModule();
if (cu != null && cu.isWorkingCopy()) {
ISourceModule[] copies = getWorkingCopies();
int length = copies == null ? 0 : copies.length;
if (length > 0) {
ISourceModule[] newWorkingCopies = new ISourceModule[length
+ 1];
System.arraycopy(copies, 0, newWorkingCopies, 0, length);
newWorkingCopies[length] = cu;
return newWorkingCopies;
}
return new ISourceModule[] { cu };
}
}
return getWorkingCopies();
}
boolean match(char patternTypeSuffix, int modifiers) {
switch (patternTypeSuffix) {
case IIndexConstants.TYPE_SUFFIX:
return true; // TODO: add conditions here when needed
// case IIndexConstants.ANNOTATION_TYPE_SUFFIX :
// return (modifiers & Flags.AccAnnotation) != 0;
}
return true;
}
boolean match(char patternTypeSuffix, char[] patternPkg,
char[] patternTypeName, int matchRule, int typeKind, char[] pkg,
char[] typeName) {
boolean isCaseSensitive = (matchRule
& SearchPattern.R_CASE_SENSITIVE) != 0;
// if (patternPkg != null && !CharOperation.equals(patternPkg, pkg,
// isCaseSensitive))
// return false;
if (patternTypeName != null) {
boolean isCamelCase = (matchRule
& SearchPattern.R_CAMELCASE_MATCH) != 0;
int matchMode = matchRule & DLTKSearchPattern.MATCH_MODE_MASK;
if (!isCaseSensitive && !isCamelCase) {
patternTypeName = CharOperation.toLowerCase(patternTypeName);
}
boolean matchFirstChar = !isCaseSensitive
|| patternTypeName[0] == typeName[0];
if (isCamelCase && matchFirstChar && CharOperation
.camelCaseMatch(patternTypeName, typeName)) {
return true;
}
switch (matchMode) {
case SearchPattern.R_EXACT_MATCH:
if (!isCamelCase) {
return matchFirstChar && CharOperation
.equals(patternTypeName, typeName, isCaseSensitive);
}
// fall through next case to match as prefix if camel case
// failed
case SearchPattern.R_PREFIX_MATCH:
return matchFirstChar && CharOperation.prefixEquals(
patternTypeName, typeName, isCaseSensitive);
case SearchPattern.R_PATTERN_MATCH:
return CharOperation.match(patternTypeName, typeName,
isCaseSensitive);
case SearchPattern.R_REGEXP_MATCH:
// TODO (frederic) implement regular expression match
break;
}
}
return true;
}
/**
* 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).
*
* @see SearchEngine#search(SearchPattern, SearchParticipant[],
* IJavaSearchScope, SearchRequestor, IProgressMonitor) for detailed
* comment
*/
public void search(SearchPattern pattern, SearchParticipant[] participants,
IDLTKSearchScope scope, SearchRequestor requestor,
IProgressMonitor monitor) throws CoreException {
if (VERBOSE) {
Util.verbose(
"BasicSearchEngine.search(SearchPattern, SearchParticipant[], IJavaSearchScope, SearchRequestor, IProgressMonitor)"); //$NON-NLS-1$
}
findMatches(pattern, participants, scope, requestor, monitor);
}
/**
* 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).
*
* @see SearchEngine#search(SearchPattern, SearchParticipant[],
* IJavaSearchScope, SearchRequestor, IProgressMonitor) for detailed
* comment
*/
public List searchSourceOnly(SearchPattern pattern,
SearchParticipant[] participants, IDLTKSearchScope scope,
IProgressMonitor monitor) throws CoreException {
if (VERBOSE) {
Util.verbose(
"BasicSearchEngine.search(SearchPattern, SearchParticipant[], IJavaSearchScope, SearchRequestor, IProgressMonitor)"); //$NON-NLS-1$
}
return findMatchesSourceOnly(pattern, participants, scope, monitor);
}
/**
* Searches for all secondary types in the given scope. The search can be
* selecting specific types (given a package or a type name prefix and match
* modes).
*/
public void searchAllSecondaryTypeNames(IProjectFragment[] sourceFolders,
final IRestrictedAccessTypeRequestor nameRequestor,
boolean waitForIndexes, IProgressMonitor progressMonitor)
throws ModelException {
//
// if (VERBOSE) {
// Util.verbose(
// "BasicSearchEngine.searchAllSecondaryTypeNames(IProjectFragment[],
// IRestrictedAccessTypeRequestor, boolean, IProgressMonitor)");
// //$NON-NLS-1$
// StringBuffer buffer = new StringBuffer(" - source folders: ");
// //$NON-NLS-1$
// int length = sourceFolders.length;
// for (int i=0; i<length; i++) {
// if (i==0) {
// buffer.append('[');
// } else {
// buffer.append(',');
// }
// buffer.append(sourceFolders[i].getElementName());
// }
// buffer.append("]\n - waitForIndexes: "); //$NON-NLS-1$
// buffer.append(waitForIndexes);
// Util.verbose(buffer.toString());
// }
//
// IndexManager indexManager =
// ModelManager.getModelManager().getIndexManager();
// final TypeDeclarationPattern pattern = new
// SecondaryTypeDeclarationPattern();
//
// // Get working copy path(s). Store in a single string in case of only
// one to optimize comparison in requestor
// final HashSet workingCopyPaths = new HashSet();
// String workingCopyPath = null;
// ISourceModule[] copies = getWorkingCopies();
// final int copiesLength = copies == null ? 0 : copies.length;
// if (copies != null) {
// if (copiesLength == 1) {
// workingCopyPath = copies[0].getPath().toString();
// } else {
// for (int i = 0; i < copiesLength; i++) {
// ISourceModule workingCopy = copies[i];
// workingCopyPaths.add(workingCopy.getPath().toString());
// }
// }
// }
// final String singleWkcpPath = workingCopyPath;
//
// // Index requestor
// IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){
// public boolean acceptIndexMatch(String documentPath, SearchPattern
// indexRecord, SearchParticipant participant, AccessRuleSet access) {
// // Filter unexpected types
// TypeDeclarationPattern record = (TypeDeclarationPattern)indexRecord;
// if (!record.secondary) {
// return true; // filter maint types
// }
// if (record.enclosingTypeNames == IIndexConstants.ONE_ZERO_CHAR) {
// return true; // filter out local and anonymous classes
// }
// switch (copiesLength) {
// case 0:
// break;
// case 1:
// if (singleWkcpPath.equals(documentPath)) {
// return true; // fliter out *the* working copy
// }
// break;
// default:
// if (workingCopyPaths.contains(documentPath)) {
// return true; // filter out working copies
// }
// break;
// }
//
// // Accept document path
// AccessRestriction accessRestriction = null;
// if (access != null) {
// // Compute document relative path
// int pkgLength = (record.pkg==null || record.pkg.length==0) ? 0 :
// record.pkg.length+1;
// int nameLength = record.simpleName==null ? 0 :
// record.simpleName.length;
// char[] path = new char[pkgLength+nameLength];
// int pos = 0;
// if (pkgLength > 0) {
// System.arraycopy(record.pkg, 0, path, pos, pkgLength-1);
// CharOperation.replace(path, '.', '/');
// path[pkgLength-1] = '/';
// pos += pkgLength;
// }
// if (nameLength > 0) {
// System.arraycopy(record.simpleName, 0, path, pos, nameLength);
// pos += nameLength;
// }
// // Update access restriction if path is not empty
// if (pos > 0) {
// accessRestriction = access.getViolatedRestriction(path);
// }
// }
// nameRequestor.acceptType(record.modifiers, record.pkg,
// record.simpleName, record.enclosingTypeNames, documentPath,
// accessRestriction);
// return true;
// }
// };
//
// // add type names from indexes
// if (progressMonitor != null) {
// progressMonitor.beginTask(Messages.engine_searching, 100);
// }
// try {
// indexManager.performConcurrentJob(
// new PatternSearchJob(
// pattern,
// getDefaultSearchParticipant(), // Script search only
// createJavaSearchScope(sourceFolders),
// searchRequestor),
// waitForIndexes
// ? IDLTKSearchConstants.WAIT_UNTIL_READY_TO_SEARCH
// : IDLTKSearchConstants.FORCE_IMMEDIATE_SEARCH,
// progressMonitor == null ? null : new
// SubProgressMonitor(progressMonitor, 100));
// }
// catch (OperationCanceledException oce) {
// // do nothing
// }
}
/**
* Searches for all top-level types and member types in the given scope. The
* search can be selecting specific types (given a package or a type name
* prefix and match modes).
*
* @see SearchEngine#searchAllTypeNames(char[], char[], int, int,
* IJavaSearchScope, TypeNameRequestor, int, IProgressMonitor) for
* detailed comment
*/
public void searchAllTypeNames(final char[] packageName,
final int packageMatchRule, char[] typeName,
final int typeMatchRule, int searchFor, IDLTKSearchScope scope,
final IRestrictedAccessTypeRequestor nameRequestor,
int waitingPolicy, IProgressMonitor progressMonitor)
throws ModelException {
if (VERBOSE) {
Util.verbose(
"BasicSearchEngine.searchAllTypeNames(char[], char[], int, int, IJavaSearchScope, IRestrictedAccessTypeRequestor, int, IProgressMonitor)"); //$NON-NLS-1$
Util.verbose(" - package name: " //$NON-NLS-1$
+ (packageName == null ? "null" : new String(packageName))); //$NON-NLS-1$
Util.verbose(
" - match rule: " + getMatchRuleString(packageMatchRule)); //$NON-NLS-1$
Util.verbose(" - type name: " //$NON-NLS-1$
+ (typeName == null ? "null" : new String(typeName))); //$NON-NLS-1$
Util.verbose(
" - match rule: " + getMatchRuleString(typeMatchRule)); //$NON-NLS-1$
Util.verbose(" - search for: " + searchFor); //$NON-NLS-1$
Util.verbose(" - scope: " + scope); //$NON-NLS-1$
}
// Return on invalid combination of package and type names
if (packageName == null || packageName.length == 0) {
if (typeName != null && typeName.length == 0) {
// TODO (frederic) Throw a JME instead?
if (VERBOSE) {
Util.verbose(
" => return no result due to invalid empty values for package and type names!"); //$NON-NLS-1$
}
return;
}
}
// Create pattern
IndexManager indexManager = ModelManager.getModelManager()
.getIndexManager();
final char typeSuffix;
switch (searchFor) {
case IDLTKSearchConstants.TYPE:
typeSuffix = IIndexConstants.TYPE_SUFFIX;
break;
case IDLTKSearchConstants.ANNOTATION_TYPE:
typeSuffix = IIndexConstants.ANNOTATION_TYPE_SUFFIX;
break;
default:
typeSuffix = IIndexConstants.TYPE_SUFFIX;
break;
}
final boolean simple = packageName == null || packageName.length == 0;
// packageMatchRule == SearchPattern.R_EXACT_MATCH
final TypeDeclarationPattern pattern = simple
? new TypeDeclarationPattern(packageName, null, null, typeName,
typeSuffix, typeMatchRule, scope.getLanguageToolkit())
: new QualifiedTypeDeclarationPattern(packageName,
packageMatchRule, typeName, typeSuffix, typeMatchRule,
scope.getLanguageToolkit());
// Get working copy path(s). Store in a single string in case of only
// one to optimize comparison in requestor
final HashSet<String> workingCopyPaths = new HashSet<>();
String workingCopyPath = null;
ISourceModule[] copies = getWorkingCopies();
final int copiesLength = copies == null ? 0 : copies.length;
if (copies != null) {
if (copiesLength == 1) {
workingCopyPath = copies[0].getPath().toString();
} else {
for (int i = 0; i < copiesLength; i++) {
ISourceModule workingCopy = copies[i];
workingCopyPaths.add(workingCopy.getPath().toString());
}
}
}
final String singleWkcpPath = workingCopyPath;
// final List documentPathFilter = new ArrayList();
// Index requestor
IndexQueryRequestor searchRequestor = new IndexQueryRequestor() {
@Override
public boolean acceptIndexMatch(String documentPath,
SearchPattern indexRecord, SearchParticipant participant,
AccessRuleSet access) {
// IPath fullPath = new Path(documentPath);
// if( documentPathFilter.contains(fullPath)) {
// return true;
// }
// documentPathFilter.add(fullPath);
// Filter unexpected types
TypeDeclarationPattern record = (TypeDeclarationPattern) indexRecord;
// FIXME (alex) filter out local and anonymous classes
// if (record.enclosingTypeNames ==
// IIndexConstants.ONE_ZERO_CHAR) {
// return true; // filter out local and anonymous classes
// }
switch (copiesLength) {
case 0:
break;
case 1:
if (singleWkcpPath.equals(documentPath)) {
return true; // fliter out *the* working copy
}
break;
default:
if (workingCopyPaths.contains(documentPath)) {
return true; // filter out working copies
}
break;
}
// Accept document path
AccessRestriction accessRestriction = null;
if (access != null) {
// Compute document relative path
int pkgLength = (record.pkg == null
|| record.pkg.length == 0) ? 0
: record.pkg.length + 1;
int nameLength = record.simpleName == null ? 0
: record.simpleName.length;
char[] path = new char[pkgLength + nameLength];
int pos = 0;
if (pkgLength > 0) {
System.arraycopy(record.pkg, 0, path, pos,
pkgLength - 1);
CharOperation.replace(path, '.', '/');
path[pkgLength - 1] = '/';
pos += pkgLength;
}
if (nameLength > 0) {
System.arraycopy(record.simpleName, 0, path, pos,
nameLength);
pos += nameLength;
}
// Update access restriction if path is not empty
if (pos > 0) {
accessRestriction = access.getViolatedRestriction(path);
}
}
if (match(record.typeSuffix, record.modifiers)) {
nameRequestor.acceptType(record.modifiers, record.pkg,
record.simpleName, record.enclosingTypeNames,
record.superTypes, documentPath, accessRestriction);
}
return true;
}
};
try {
if (progressMonitor != null) {
progressMonitor.beginTask(Messages.engine_searching, 100);
}
// add type names from indexes
indexManager.performConcurrentJob(
new PatternSearchJob(pattern, getDefaultSearchParticipant(), // Script
// search
// only
scope, searchRequestor),
waitingPolicy, progressMonitor == null ? null
: new SubProgressMonitor(progressMonitor, 100));
// add type names from working copies
if (copies != null) {
for (int i = 0; i < copiesLength; i++) {
ISourceModule workingCopy = copies[i];
if (!scope.encloses(workingCopy)) {
continue;
}
final String path = workingCopy.getPath().toString();
// if (workingCopy.isConsistent()) {
// IPackageDeclaration[] packageDeclarations =
// workingCopy.getPackageDeclarations();
// char[] packageDeclaration = packageDeclarations.length ==
// 0 ? CharOperation.NO_CHAR :
// packageDeclarations[0].getElementName().toCharArray();
IType[] allTypes = workingCopy.getTypes();
for (int j = 0; j < allTypes.length; j++) {
IType type = allTypes[i];
IModelElement parent = type.getParent();
final char[][] enclosingTypeNames;
if (parent instanceof IType) {
char[] parentQualifiedName = ((IType) parent)
.getTypeQualifiedName().toCharArray();
enclosingTypeNames = CharOperation.splitOn('.',
parentQualifiedName);
} else {
enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
}
char[] simpleName = type.getElementName().toCharArray();
char[] packageDeclaration = SearchPattern
.createPackagePattern(type.getNamespace());
int kind = 0;
if (match(typeSuffix, packageName, typeName,
typeMatchRule, kind, packageDeclaration,
simpleName)) {
nameRequestor.acceptType(type.getFlags(),
packageDeclaration, simpleName,
enclosingTypeNames,
CharOperation.stringArrayToCharCharArray(
type.getSuperClasses()),
path, null);
}
}
// }
}
}
} finally {
if (progressMonitor != null) {
progressMonitor.done();
}
}
}
/**
* Searches for all top-level types and member types in the given scope
* using a case sensitive exact match with the given qualified names and
* type names.
*
* @see SearchEngine#searchAllTypeNames(char[][], char[][],
* IJavaSearchScope, TypeNameRequestor, int, IProgressMonitor) for
* detailed comment
*/
public void searchAllTypeNames(final char[][] qualifications,
final char[][] typeNames, final int matchRule, int searchFor,
IDLTKSearchScope scope,
final IRestrictedAccessTypeRequestor nameRequestor,
int waitingPolicy, IProgressMonitor progressMonitor)
throws ModelException {
if (VERBOSE) {
Util.verbose(
"BasicSearchEngine.searchAllTypeNames(char[][], char[][], int, int, IJavaSearchScope, IRestrictedAccessTypeRequestor, int, IProgressMonitor)"); //$NON-NLS-1$
Util.verbose(" - package name: " + (qualifications == null ? "null" //$NON-NLS-1$ //$NON-NLS-2$
: new String(
CharOperation.concatWith(qualifications, ','))));
Util.verbose(" - type name: " + (typeNames == null ? "null" //$NON-NLS-1$ //$NON-NLS-2$
: new String(CharOperation.concatWith(typeNames, ','))));
Util.verbose(" - match rule: " + matchRule); //$NON-NLS-1$
Util.verbose(" - search for: " + searchFor); //$NON-NLS-1$
Util.verbose(" - scope: " + scope); //$NON-NLS-1$
}
// IndexManager indexManager =
// ModelManager.getModelManager().getIndexManager();
//
// final char typeSuffix;
// switch(searchFor){
// case IDLTKSearchConstants.CLASS :
// typeSuffix = IIndexConstants.CLASS_SUFFIX;
// break;
// case IDLTKSearchConstants.CLASS_AND_INTERFACE :
// typeSuffix = IIndexConstants.CLASS_AND_INTERFACE_SUFFIX;
// break;
// case IDLTKSearchConstants.CLASS_AND_ENUM :
// typeSuffix = IIndexConstants.CLASS_AND_ENUM_SUFFIX;
// break;
// case IDLTKSearchConstants.INTERFACE :
// typeSuffix = IIndexConstants.INTERFACE_SUFFIX;
// break;
// case IDLTKSearchConstants.ENUM :
// typeSuffix = IIndexConstants.ENUM_SUFFIX;
// break;
// case IDLTKSearchConstants.ANNOTATION_TYPE :
// typeSuffix = IIndexConstants.ANNOTATION_TYPE_SUFFIX;
// break;
// default :
// typeSuffix = IIndexConstants.TYPE_SUFFIX;
// break;
// }
// final MultiTypeDeclarationPattern pattern = new
// MultiTypeDeclarationPattern(qualifications, typeNames, typeSuffix,
// matchRule);
//
// // Get working copy path(s). Store in a single string in case of only
// one to optimize comparison in requestor
// final HashSet workingCopyPaths = new HashSet();
// String workingCopyPath = null;
// ISourceModule[] copies = getWorkingCopies();
// final int copiesLength = copies == null ? 0 : copies.length;
// if (copies != null) {
// if (copiesLength == 1) {
// workingCopyPath = copies[0].getPath().toString();
// } else {
// for (int i = 0; i < copiesLength; i++) {
// ISourceModule workingCopy = copies[i];
// workingCopyPaths.add(workingCopy.getPath().toString());
// }
// }
// }
// final String singleWkcpPath = workingCopyPath;
//
// // Index requestor
// IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){
// public boolean acceptIndexMatch(String documentPath, SearchPattern
// indexRecord, SearchParticipant participant, AccessRuleSet access) {
// // Filter unexpected types
// switch (copiesLength) {
// case 0:
// break;
// case 1:
// if (singleWkcpPath.equals(documentPath)) {
// return true; // fliter out *the* working copy
// }
// break;
// default:
// if (workingCopyPaths.contains(documentPath)) {
// return true; // filter out working copies
// }
// break;
// }
//
// // Accept document path
// QualifiedTypeDeclarationPattern record =
// (QualifiedTypeDeclarationPattern) indexRecord;
// AccessRestriction accessRestriction = null;
// if (access != null) {
// // Compute document relative path
// int qualificationLength = (record.qualification == null ||
// record.qualification.length == 0) ? 0 : record.qualification.length +
// 1;
// int nameLength = record.simpleName == null ? 0 :
// record.simpleName.length;
// char[] path = new char[qualificationLength + nameLength];
// int pos = 0;
// if (qualificationLength > 0) {
// System.arraycopy(record.qualification, 0, path, pos,
// qualificationLength - 1);
// CharOperation.replace(path, '.', '/');
// path[qualificationLength-1] = '/';
// pos += qualificationLength;
// }
// if (nameLength > 0) {
// System.arraycopy(record.simpleName, 0, path, pos, nameLength);
// pos += nameLength;
// }
// // Update access restriction if path is not empty
// if (pos > 0) {
// accessRestriction = access.getViolatedRestriction(path);
// }
// }
// nameRequestor.acceptType(record.modifiers, record.pkg,
// record.simpleName, record.enclosingTypeNames, documentPath,
// accessRestriction);
// return true;
// }
// };
//
// try {
// if (progressMonitor != null) {
// progressMonitor.beginTask(Messages.engine_searching, 100);
// }
// // add type names from indexes
// indexManager.performConcurrentJob(
// new PatternSearchJob(
// pattern,
// getDefaultSearchParticipant(), // Script search only
// scope,
// searchRequestor),
// waitingPolicy,
// progressMonitor == null ? null : new
// SubProgressMonitor(progressMonitor, 100));
//
// // add type names from working copies
// if (copies != null) {
// for (int i = 0, length = copies.length; i < length; i++) {
// ISourceModule workingCopy = copies[i];
// final String path = workingCopy.getPath().toString();
// if (workingCopy.isConsistent()) {
// IPackageDeclaration[] packageDeclarations =
// workingCopy.getPackageDeclarations();
// char[] packageDeclaration = packageDeclarations.length == 0 ?
// CharOperation.NO_CHAR :
// packageDeclarations[0].getElementName().toCharArray();
// IType[] allTypes = workingCopy.getAllTypes();
// for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength;
// j++) {
// IType type = allTypes[j];
// IModelElement parent = type.getParent();
// char[][] enclosingTypeNames;
// char[] qualification = packageDeclaration;
// if (parent instanceof IType) {
// char[] parentQualifiedName =
// ((IType)parent).getTypeQualifiedName('.').toCharArray();
// enclosingTypeNames = CharOperation.splitOn('.', parentQualifiedName);
// qualification = CharOperation.concat(qualification,
// parentQualifiedName);
// } else {
// enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
// }
// char[] simpleName = type.getElementName().toCharArray();
// char suffix = IIndexConstants.TYPE_SUFFIX;
// if (type.isClass()) {
// suffix = IIndexConstants.CLASS_SUFFIX;
// } else if (type.isInterface()) {
// suffix = IIndexConstants.INTERFACE_SUFFIX;
// } else if (type.isEnum()) {
// suffix = IIndexConstants.ENUM_SUFFIX;
// } else if (type.isAnnotation()) {
// suffix = IIndexConstants.ANNOTATION_TYPE_SUFFIX;
// }
// if (pattern.matchesDecodedKey(new
// QualifiedTypeDeclarationPattern(qualification, simpleName, suffix,
// matchRule))) {
// nameRequestor.acceptType(type.getFlags(), packageDeclaration,
// simpleName, enclosingTypeNames, path, null);
// }
// }
// } else {
// Parser basicParser = getParser();
// org.eclipse.dltk.internal.compiler.env.ISourceModule unit =
// (org.eclipse.dltk.internal.compiler.env.ISourceModule) workingCopy;
// CompilationResult compilationUnitResult = new CompilationResult(unit,
// 0, 0, this.compilerOptions.maxProblemsPerUnit);
// SourceModuleDeclaration parsedUnit = basicParser.dietParse(unit,
// compilationUnitResult);
// if (parsedUnit != null) {
// final char[] packageDeclaration = parsedUnit.currentPackage == null
// ? CharOperation.NO_CHAR
// : CharOperation.concatWith(parsedUnit.currentPackage.getImportName(),
// '.');
// class AllTypeDeclarationsVisitor extends ASTVisitor {
// public boolean visit(TypeDeclaration typeDeclaration, BlockScope
// blockScope) {
// return false; // no local/anonymous type
// }
// public boolean visit(TypeDeclaration typeDeclaration,
// SourceModuleScope compilationUnitScope) {
// SearchPattern decodedPattern =
// new QualifiedTypeDeclarationPattern(packageDeclaration,
// typeDeclaration.name,
// convertTypeKind(TypeDeclaration.kind(typeDeclaration.modifiers)),
// matchRule);
// if (pattern.matchesDecodedKey(decodedPattern)) {
// nameRequestor.acceptType(typeDeclaration.modifiers,
// packageDeclaration, typeDeclaration.name, CharOperation.NO_CHAR_CHAR,
// path, null);
// Parser basicParser = getParser();
// org.eclipse.dltk.internal.compiler.env.ISourceModule unit =
// (org.eclipse.dltk.internal.compiler.env.ISourceModule) workingCopy;
// CompilationResult compilationUnitResult = new CompilationResult(unit,
// 0, 0, this.compilerOptions.maxProblemsPerUnit);
// SourceModuleDeclaration parsedUnit = basicParser.dietParse(unit,
// compilationUnitResult);
// if (parsedUnit != null) {
// final char[] packageDeclaration = parsedUnit.currentPackage == null
// ? CharOperation.NO_CHAR
// : CharOperation.concatWith(parsedUnit.currentPackage.getImportName(),
// '.');
// class AllTypeDeclarationsVisitor extends ASTVisitor {
// public boolean visit(TypeDeclaration typeDeclaration, BlockScope
// blockScope) {
// return false; // no local/anonymous type
// }
// public boolean visit(TypeDeclaration typeDeclaration,
// SourceModuleScope compilationUnitScope) {
// SearchPattern decodedPattern =
// new QualifiedTypeDeclarationPattern(packageDeclaration,
// typeDeclaration.name,
// convertTypeKind(TypeDeclaration.kind(typeDeclaration.modifiers)),
// matchRule);
// if (pattern.matchesDecodedKey(decodedPattern)) {
// nameRequestor.acceptType(typeDeclaration.modifiers,
// packageDeclaration, typeDeclaration.name, CharOperation.NO_CHAR_CHAR,
// path, null);
// }
// return true;
// }
// public boolean visit(TypeDeclaration memberTypeDeclaration,
// ClassScope classScope) {
// // compute encloising type names
// char[] qualification = packageDeclaration;
// TypeDeclaration enclosing = memberTypeDeclaration.enclosingType;
// char[][] enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
// while (enclosing != null) {
// qualification = CharOperation.concat(qualification, enclosing.name,
// '.');
// enclosingTypeNames = CharOperation.arrayConcat(new char[][]
// {enclosing.name}, enclosingTypeNames);
// if ((enclosing.bits & ASTNode.IsMemberType) != 0) {
// enclosing = enclosing.enclosingType;
// } else {
// enclosing = null;
// }
// }
// SearchPattern decodedPattern =
// new QualifiedTypeDeclarationPattern(qualification,
// memberTypeDeclaration.name,
// convertTypeKind(TypeDeclaration.kind(memberTypeDeclaration.modifiers))
// ,
// matchRule);
// if (pattern.matchesDecodedKey(decodedPattern)) {
// nameRequestor.acceptType(memberTypeDeclaration.modifiers,
// packageDeclaration, memberTypeDeclaration.name, enclosingTypeNames,
// path, null);
// }
// return true;
// }
// }
// parsedUnit.traverse(new AllTypeDeclarationsVisitor(),
// parsedUnit.scope);}
// return true;
// }
// public boolean visit(TypeDeclaration memberTypeDeclaration,
// ClassScope classScope) {
// // compute encloising type names
// char[] qualification = packageDeclaration;
// TypeDeclaration enclosing = memberTypeDeclaration.enclosingType;
// char[][] enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
// while (enclosing != null) {
// qualification = CharOperation.concat(qualification, enclosing.name,
// '.');
// enclosingTypeNames = CharOperation.arrayConcat(new char[][]
// {enclosing.name}, enclosingTypeNames);
// if ((enclosing.bits & ASTNode.IsMemberType) != 0) {
// enclosing = enclosing.enclosingType;
// } else {
// enclosing = null;
// }
// }
// SearchPattern decodedPattern =
// new QualifiedTypeDeclarationPattern(qualification,
// memberTypeDeclaration.name,
// convertTypeKind(TypeDeclaration.kind(memberTypeDeclaration.modifiers))
// ,
// matchRule);
// if (pattern.matchesDecodedKey(decodedPattern)) {
// nameRequestor.acceptType(memberTypeDeclaration.modifiers,
// packageDeclaration, memberTypeDeclaration.name, enclosingTypeNames,
// path, null);
// }
// return true;
// }
// }
// parsedUnit.traverse(new AllTypeDeclarationsVisitor(),
// parsedUnit.scope);
// }
// }
// }
// }
// } finally {
// if (progressMonitor != null) {
// progressMonitor.done();
// }
// }
}
public DLTKSearchParticipant getSearchParticipant(IModelElement element) {
IDLTKLanguageToolkit toolkit = null;
toolkit = DLTKLanguageManager.getLanguageToolkit(element);
if (toolkit != null) {
DLTKSearchParticipant par = DLTKLanguageManager
.createSearchParticipant(toolkit.getNatureId());
if (par != null) {
return par;
}
}
return new DLTKSearchParticipant();
}
public void searchDeclarations(IModelElement enclosingElement,
SearchRequestor requestor, SearchPattern pattern,
IProgressMonitor monitor) throws ModelException {
if (VERBOSE) {
Util.verbose(" - script element: " + enclosingElement); //$NON-NLS-1$
}
IDLTKSearchScope scope = createSearchScope(
new IModelElement[] { enclosingElement },
DLTKLanguageManager.getLanguageToolkit(enclosingElement));
IResource resource = enclosingElement.getResource();
if (enclosingElement instanceof IMember) {
IMember member = (IMember) enclosingElement;
ISourceModule cu = member.getSourceModule();
if (cu != null) {
resource = cu.getResource();
} else if (((IProjectFragment) member
.getAncestor(IModelElement.PROJECT_FRAGMENT))
.isExternal()) {
// binary member resource cannot be used as this
// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=148215
resource = null;
}
}
try {
if (resource instanceof IFile) {
try {
requestor.beginReporting();
if (VERBOSE) {
Util.verbose("Searching for " + pattern + " in " //$NON-NLS-1$//$NON-NLS-2$
+ resource.getFullPath());
}
SearchParticipant participant = getSearchParticipant(
enclosingElement);
boolean external = false;
IProjectFragment fragment = (IProjectFragment) enclosingElement
.getAncestor(IModelElement.PROJECT_FRAGMENT);
if (fragment != null) {
external = fragment.isExternal();
}
char[] contents = Util
.getResourceContentsAsCharArray((IFile) resource);
SearchDocument[] documents = ModuleFactory.addWorkingCopies(
pattern,
new SearchDocument[] { new DLTKSearchDocument(
enclosingElement.getPath().toString(),
contents, participant, external,
enclosingElement.getScriptProject()
.getProject()) },
getWorkingCopies(enclosingElement), participant);
participant.locateMatches(documents, pattern, scope,
requestor, monitor);
} finally {
requestor.endReporting();
}
} else {
search(pattern,
new SearchParticipant[] {
getDefaultSearchParticipant() },
scope, requestor, monitor);
}
} catch (CoreException e) {
if (e instanceof ModelException) {
throw (ModelException) e;
}
throw new ModelException(e);
}
}
/**
* 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.
*
* @see SearchEngine#searchDeclarationsOfAccessedFields(IModelElement,
* SearchRequestor, IProgressMonitor) for detailed comment
*/
public void searchDeclarationsOfAccessedFields(
IModelElement enclosingElement, SearchRequestor requestor,
IProgressMonitor monitor) throws ModelException {
// if (VERBOSE) {
// Util.verbose(
// "BasicSearchEngine.searchDeclarationsOfAccessedFields(IModelElement,
// SearchRequestor, SearchPattern, IProgressMonitor)"); //$NON-NLS-1$
// }
// SearchPattern pattern = new
// DeclarationOfAccessedFieldsPattern(enclosingElement);
// searchDeclarations(enclosingElement, requestor, pattern, 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.
*
* @see SearchEngine#searchDeclarationsOfReferencedTypes(IModelElement,
* SearchRequestor, IProgressMonitor) for detailed comment
*/
public void searchDeclarationsOfReferencedTypes(
IModelElement enclosingElement, SearchRequestor requestor,
IProgressMonitor monitor) throws ModelException {
// if (VERBOSE) {
// Util.verbose(
// "BasicSearchEngine.searchDeclarationsOfReferencedTypes(IModelElement,
// SearchRequestor, SearchPattern, IProgressMonitor)"); //$NON-NLS-1$
// }
// SearchPattern pattern = new
// DeclarationOfReferencedTypesPattern(enclosingElement);
// searchDeclarations(enclosingElement, requestor, pattern, 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.
*
* @see SearchEngine#searchDeclarationsOfSentMessages(IModelElement,
* SearchRequestor, IProgressMonitor) for detailed comment
*/
public void searchDeclarationsOfSentMessages(IModelElement enclosingElement,
SearchRequestor requestor, IProgressMonitor monitor)
throws ModelException {
// if (VERBOSE) {
// Util.verbose(
// "BasicSearchEngine.searchDeclarationsOfSentMessages(IModelElement,
// SearchRequestor, SearchPattern, IProgressMonitor)"); //$NON-NLS-1$
// }
// SearchPattern pattern = new
// DeclarationOfReferencedMethodsPattern(enclosingElement);
// searchDeclarations(enclosingElement, requestor, pattern, monitor);
}
/**
* @see SearchEngine#createTypeNameMatch(IType, int) for detailed comment.
*/
public static MethodNameMatch createMethodNameMatch(IMethod method,
int modifiers) {
return new DLTKSearchMethodNameMatch(method, modifiers);
}
/**
* Searches for all top-level types and member types in the given scope. The
* search can be selecting specific types (given a package or a type name
* prefix and match modes).
*
* @throws ModelException
*
* @see SearchEngine#searchAllTypeNames(char[], char[], int, int,
* IJavaSearchScope, TypeNameRequestor, int, IProgressMonitor) for
* detailed comment
*/
public void searchAllMethodNames(char[] methodName, int methodMatchRule,
int searchFor, IDLTKSearchScope scope,
final IRestrictedAccessMethodRequestor nameRequestor,
int waitingPolicy, IProgressMonitor progressMonitor)
throws ModelException {
if (VERBOSE) {
Util.verbose(
"BasicSearchEngine.searchAllTypeNames(char[], char[], int, int, IJavaSearchScope, IRestrictedAccessTypeRequestor, int, IProgressMonitor)"); //$NON-NLS-1$
Util.verbose(" - method name: " //$NON-NLS-1$
+ (methodName == null ? "null" : new String(methodName))); //$NON-NLS-1$
Util.verbose(
" - match rule: " + getMatchRuleString(methodMatchRule)); //$NON-NLS-1$
Util.verbose(" - search for: " + searchFor); //$NON-NLS-1$
Util.verbose(" - scope: " + scope); //$NON-NLS-1$
}
// Return on invalid combination of package and type names
if (methodName != null && methodName.length == 0) {
// TODO (frederic) Throw a JME instead?
if (VERBOSE) {
Util.verbose(
" => return no result due to invalid empty values for package and type names!"); //$NON-NLS-1$
}
return;
}
// Create pattern
IndexManager indexManager = ModelManager.getModelManager()
.getIndexManager();
final MethodDeclarationPattern pattern = new MethodDeclarationPattern(
methodName, methodMatchRule, scope.getLanguageToolkit());
// Get working copy path(s). Store in a single string in case of only
// one to optimize comparison in requestor
final HashSet workingCopyPaths = new HashSet();
String workingCopyPath = null;
ISourceModule[] copies = getWorkingCopies();
final int copiesLength = copies == null ? 0 : copies.length;
if (copies != null) {
if (copiesLength == 1) {
workingCopyPath = copies[0].getPath().toString();
} else {
for (int i = 0; i < copiesLength; i++) {
ISourceModule workingCopy = copies[i];
workingCopyPaths.add(workingCopy.getPath().toString());
}
}
}
final String singleWkcpPath = workingCopyPath;
// final List documentPathFilter = new ArrayList();
// Index requestor
IndexQueryRequestor searchRequestor = new IndexQueryRequestor() {
@Override
public boolean acceptIndexMatch(String documentPath,
SearchPattern indexRecord, SearchParticipant participant,
AccessRuleSet access) {
// IPath fullPath = new Path(documentPath);
// if( documentPathFilter.contains(fullPath)) {
// return true;
// }
// documentPathFilter.add(fullPath);
// Filter unexpected types
MethodDeclarationPattern record = (MethodDeclarationPattern) indexRecord;
switch (copiesLength) {
case 0:
break;
case 1:
if (singleWkcpPath.equals(documentPath)) {
return true; // fliter out *the* working copy
}
break;
default:
if (workingCopyPaths.contains(documentPath)) {
return true; // filter out working copies
}
break;
}
nameRequestor.acceptMethod(record.modifiers, record.pkg,
record.simpleName, record.enclosingTypeNames,
record.parameterNames, documentPath);
return true;
}
};
try {
if (progressMonitor != null) {
progressMonitor.beginTask(Messages.engine_searching, 100);
}
// add type names from indexes
indexManager.performConcurrentJob(
new PatternSearchJob(pattern, getDefaultSearchParticipant(), // Script
// search
// only
scope, searchRequestor),
waitingPolicy, progressMonitor == null ? null
: new SubProgressMonitor(progressMonitor, 100));
// add type names from working copies
if (copies != null) {
for (int i = 0; i < copiesLength; i++) {
ISourceModule workingCopy = copies[i];
if (!scope.encloses(workingCopy)) {
continue;
}
final String path = workingCopy.getPath().toString();
// if (workingCopy.isConsistent()) {
// IPackageDeclaration[] packageDeclarations =
// workingCopy.getPackageDeclarations();
// char[] packageDeclaration = packageDeclarations.length ==
// 0 ? CharOperation.NO_CHAR :
// packageDeclarations[0].getElementName().toCharArray();
IType[] allTypes = workingCopy.getTypes();
for (int j = 0; j < allTypes.length; j++) {
IType type = allTypes[i];
IModelElement parent = type.getParent();
char[][] enclosingTypeNames;
if (parent instanceof IType) {
char[] parentQualifiedName = ((IType) parent)
.getTypeQualifiedName().toCharArray();
enclosingTypeNames = CharOperation.splitOn('.',
parentQualifiedName);
} else {
enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
}
char[] simpleName = type.getElementName().toCharArray();
int kind = 0;
// FIXME search working copies
// if (match(typeSuffix, packageName, methodName,
// methodMatchRule, kind, /* packageDeclaration, */
// simpleName)) {
// nameRequestor.acceptMethod(simpleName, path, null);
// }
}
// }
}
}
} finally {
if (progressMonitor != null) {
progressMonitor.done();
}
}
}
}