| /******************************************************************************* |
| * 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(); |
| } |
| } |
| |
| } |
| } |