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