| /******************************************************************************* |
| * Copyright (c) 2000, 2016 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 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Stephan Herrmann - Contributions for bug 215139 and bug 295894 |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.core.search; |
| |
| import java.util.*; |
| |
| import org.eclipse.core.resources.*; |
| import org.eclipse.core.runtime.*; |
| |
| import org.eclipse.jdt.core.*; |
| import org.eclipse.jdt.core.compiler.CharOperation; |
| import org.eclipse.jdt.core.search.*; |
| import org.eclipse.jdt.internal.compiler.*; |
| import org.eclipse.jdt.internal.compiler.ast.*; |
| import org.eclipse.jdt.internal.compiler.env.AccessRestriction; |
| import org.eclipse.jdt.internal.compiler.env.AccessRuleSet; |
| import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; |
| import org.eclipse.jdt.internal.compiler.lookup.*; |
| import org.eclipse.jdt.internal.compiler.parser.Parser; |
| import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory; |
| import org.eclipse.jdt.internal.compiler.problem.ProblemReporter; |
| import org.eclipse.jdt.internal.core.*; |
| import org.eclipse.jdt.internal.core.search.indexing.*; |
| import org.eclipse.jdt.internal.core.search.matching.*; |
| import org.eclipse.jdt.internal.core.util.Messages; |
| import org.eclipse.jdt.internal.core.util.Util; |
| import org.eclipse.objectteams.otdt.core.IOTJavaElement; |
| import org.eclipse.objectteams.otdt.internal.core.compiler.ast.LiftingTypeReference; |
| |
| /** |
| * Search basic engine. Public search engine (see {@link org.eclipse.jdt.core.search.SearchEngine} |
| * for detailed comment), now uses basic engine functionalities. |
| * Note that search basic engine does not implement deprecated functionalities... |
| */ |
| @SuppressWarnings({ "rawtypes", "unchecked" }) |
| public class BasicSearchEngine { |
| |
| /* |
| * A default parser to parse non-reconciled working copies |
| */ |
| private Parser parser; |
| private CompilerOptions compilerOptions; |
| |
| /* |
| * A list of working copies that take precedence over their original |
| * compilation units. |
| */ |
| private ICompilationUnit[] 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 = false; |
| |
| /* |
| * Creates a new search basic engine. |
| */ |
| public BasicSearchEngine() { |
| // will use working copies of PRIMARY owner |
| } |
| |
| /** |
| * @see SearchEngine#SearchEngine(ICompilationUnit[]) for detailed comment. |
| */ |
| public BasicSearchEngine(ICompilationUnit[] workingCopies) { |
| this.workingCopies = workingCopies; |
| } |
| |
| char convertTypeKind(int typeDeclarationKind) { |
| switch(typeDeclarationKind) { |
| case TypeDeclaration.CLASS_DECL : return IIndexConstants.CLASS_SUFFIX; |
| case TypeDeclaration.INTERFACE_DECL : return IIndexConstants.INTERFACE_SUFFIX; |
| case TypeDeclaration.ENUM_DECL : return IIndexConstants.ENUM_SUFFIX; |
| case TypeDeclaration.ANNOTATION_TYPE_DECL : return IIndexConstants.ANNOTATION_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 IJavaSearchScope createHierarchyScope(IType type) throws JavaModelException { |
| return createHierarchyScope(type, DefaultWorkingCopyOwner.PRIMARY); |
| } |
| |
| /** |
| * @see SearchEngine#createHierarchyScope(IType,WorkingCopyOwner) for detailed comment. |
| */ |
| public static IJavaSearchScope createHierarchyScope(IType type, WorkingCopyOwner owner) throws JavaModelException { |
| return new HierarchyScope(type, owner); |
| } |
| |
| /** |
| * @see SearchEngine#createStrictHierarchyScope(IJavaProject,IType,boolean,boolean,WorkingCopyOwner) for detailed comment. |
| */ |
| public static IJavaSearchScope createStrictHierarchyScope(IJavaProject project, IType type, boolean onlySubtypes, boolean includeFocusType, WorkingCopyOwner owner) throws JavaModelException { |
| return new HierarchyScope(project, type, owner, onlySubtypes, true, includeFocusType); |
| } |
| |
| /** |
| * @see SearchEngine#createJavaSearchScope(IJavaElement[]) for detailed comment. |
| */ |
| public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements) { |
| return createJavaSearchScope(elements, true); |
| } |
| |
| /** |
| * @see SearchEngine#createJavaSearchScope(IJavaElement[], boolean) for detailed comment. |
| */ |
| public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements, boolean includeReferencedProjects) { |
| int includeMask = IJavaSearchScope.SOURCES | IJavaSearchScope.APPLICATION_LIBRARIES | IJavaSearchScope.SYSTEM_LIBRARIES; |
| if (includeReferencedProjects) { |
| includeMask |= IJavaSearchScope.REFERENCED_PROJECTS; |
| } |
| return createJavaSearchScope(elements, includeMask); |
| } |
| |
| /** |
| * @see SearchEngine#createJavaSearchScope(IJavaElement[], int) for detailed comment. |
| */ |
| public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements, int includeMask) { |
| HashSet projectsToBeAdded = new HashSet(2); |
| for (int i = 0, length = elements.length; i < length; i++) { |
| IJavaElement element = elements[i]; |
| if (element instanceof JavaProject) { |
| projectsToBeAdded.add(element); |
| } |
| } |
| JavaSearchScope scope = new JavaSearchScope(); |
| for (int i = 0, length = elements.length; i < length; i++) { |
| IJavaElement element = elements[i]; |
| if (element != null) { |
| try { |
| if (projectsToBeAdded.contains(element)) { |
| scope.add((JavaProject)element, includeMask, projectsToBeAdded); |
| } else { |
| scope.add(element); |
| } |
| } catch (JavaModelException e) { |
| // ignore |
| } |
| } |
| } |
| return scope; |
| } |
| |
| /** |
| * @see SearchEngine#createTypeNameMatch(IType, int) for detailed comment. |
| */ |
| public static TypeNameMatch createTypeNameMatch(IType type, int modifiers) { |
| return new JavaSearchTypeNameMatch(type, modifiers); |
| } |
| |
| /** |
| * @see SearchEngine#createMethodNameMatch(IMethod, int) for detailed comment. |
| */ |
| public static MethodNameMatch createMethodNameMatch(IMethod method, int modifiers) { |
| return new JavaSearchMethodNameMatch(method, modifiers); |
| } |
| |
| /** |
| * @see SearchEngine#createWorkspaceScope() for detailed comment. |
| */ |
| public static IJavaSearchScope createWorkspaceScope() { |
| return JavaModelManager.getJavaModelManager().getWorkspaceScope(); |
| } |
| |
| /** |
| * Searches for matches to a given query. Search queries can be created using helper |
| * methods (from a String pattern or a Java 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, IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException { |
| try { |
| 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; |
| } |
| |
| /* initialize progress monitor */ |
| int length = participants.length; |
| SubMonitor loopMonitor = SubMonitor.convert(monitor, Messages.engine_searching, length); |
| IndexManager indexManager = JavaModelManager.getIndexManager(); |
| requestor.beginReporting(); |
| for (int i = 0; i < length; i++) { |
| SubMonitor iterationMonitor = loopMonitor.split(1).setWorkRemaining(100); |
| |
| SearchParticipant participant = participants[i]; |
| try { |
| iterationMonitor.subTask(Messages.bind(Messages.engine_searching_indexing, new String[] {participant.getDescription()})); |
| participant.beginSearching(); |
| requestor.enterParticipant(participant); |
| PathCollector pathCollector = new PathCollector(); |
| indexManager.performConcurrentJob( |
| new PatternSearchJob(pattern, participant, scope, pathCollector), |
| IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, |
| iterationMonitor.split(50)); |
| |
| // locate index matches if any (note that all search matches could have been issued during index querying) |
| iterationMonitor.subTask(Messages.bind(Messages.engine_searching_matching, new String[] {participant.getDescription()})); |
| String[] indexMatchPaths = pathCollector.getPaths(); |
| if (indexMatchPaths != null) { |
| pathCollector = null; // release |
| int indexMatchLength = indexMatchPaths.length; |
| SearchDocument[] indexMatches = new SearchDocument[indexMatchLength]; |
| for (int j = 0; j < indexMatchLength; j++) { |
| indexMatches[j] = participant.getDocument(indexMatchPaths[j]); |
| } |
| SearchDocument[] matches = MatchLocator.addWorkingCopies(pattern, indexMatches, getWorkingCopies(), participant); |
| participant.locateMatches(matches, pattern, scope, requestor, iterationMonitor.split(50)); |
| } |
| } finally { |
| requestor.exitParticipant(participant); |
| participant.doneSearching(); |
| } |
| } |
| } finally { |
| requestor.endReporting(); |
| } |
| } |
| /** |
| * Returns a new default Java search participant. |
| * |
| * @return a new default Java search participant |
| * @since 3.0 |
| */ |
| public static SearchParticipant getDefaultSearchParticipant() { |
| return new JavaSearchParticipant(); |
| } |
| |
| /** |
| * @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<=16; 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; |
| case SearchPattern.R_CAMELCASE_SAME_PART_COUNT_MATCH: |
| buffer.append("R_CAMELCASE_SAME_PART_COUNT_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 IJavaSearchConstants.TYPE: |
| return ("TYPE"); //$NON-NLS-1$ |
| case IJavaSearchConstants.METHOD: |
| return ("METHOD"); //$NON-NLS-1$ |
| case IJavaSearchConstants.PACKAGE: |
| return ("PACKAGE"); //$NON-NLS-1$ |
| case IJavaSearchConstants.CONSTRUCTOR: |
| return ("CONSTRUCTOR"); //$NON-NLS-1$ |
| case IJavaSearchConstants.FIELD: |
| return ("FIELD"); //$NON-NLS-1$ |
| case IJavaSearchConstants.CLASS: |
| return ("CLASS"); //$NON-NLS-1$ |
| case IJavaSearchConstants.INTERFACE: |
| return ("INTERFACE"); //$NON-NLS-1$ |
| case IJavaSearchConstants.ENUM: |
| return ("ENUM"); //$NON-NLS-1$ |
| case IJavaSearchConstants.ANNOTATION_TYPE: |
| return ("ANNOTATION_TYPE"); //$NON-NLS-1$ |
| case IJavaSearchConstants.CLASS_AND_ENUM: |
| return ("CLASS_AND_ENUM"); //$NON-NLS-1$ |
| case IJavaSearchConstants.CLASS_AND_INTERFACE: |
| return ("CLASS_AND_INTERFACE"); //$NON-NLS-1$ |
| case IJavaSearchConstants.INTERFACE_AND_ANNOTATION: |
| return ("INTERFACE_AND_ANNOTATION"); //$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 ICompilationUnit[] getWorkingCopies() { |
| ICompilationUnit[] copies; |
| if (this.workingCopies != null) { |
| if (this.workingCopyOwner == null) { |
| copies = JavaModelManager.getJavaModelManager().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, length = copies.length; i < length; i++) { |
| ICompilationUnit unit = copies[i]; |
| pathToCUs.put(unit.getPath(), unit); |
| } |
| for (int i = 0, length = this.workingCopies.length; i < length; i++) { |
| ICompilationUnit unit = this.workingCopies[i]; |
| pathToCUs.put(unit.getPath(), unit); |
| } |
| int length = pathToCUs.size(); |
| copies = new ICompilationUnit[length]; |
| pathToCUs.values().toArray(copies); |
| } |
| } else { |
| copies = this.workingCopies; |
| } |
| } else if (this.workingCopyOwner != null) { |
| copies = JavaModelManager.getJavaModelManager().getWorkingCopies(this.workingCopyOwner, true/*add primary WCs*/); |
| } else { |
| copies = JavaModelManager.getJavaModelManager().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 |
| ICompilationUnit[] result = null; |
| int length = copies.length; |
| int index = 0; |
| for (int i = 0; i < length; i++) { |
| CompilationUnit copy = (CompilationUnit)copies[i]; |
| try { |
| if (!copy.isPrimary() |
| || copy.hasUnsavedChanges() |
| || copy.hasResourceChanged()) { |
| if (result == null) { |
| result = new ICompilationUnit[length]; |
| } |
| result[index++] = copy; |
| } |
| } catch (JavaModelException e) { |
| // copy doesn't exist: ignore |
| } |
| } |
| if (index != length && result != null) { |
| System.arraycopy(result, 0, result = new ICompilationUnit[index], 0, index); |
| } |
| return result; |
| } |
| |
| /* |
| * Returns the working copy to use to do the search on the given Java element. |
| */ |
| private ICompilationUnit[] getWorkingCopies(IJavaElement element) { |
| if (element instanceof IMember) { |
| ICompilationUnit cu = ((IMember)element).getCompilationUnit(); |
| if (cu != null && cu.isWorkingCopy()) { |
| return new ICompilationUnit[] { cu }; |
| } |
| } else if (element instanceof ICompilationUnit) { |
| return new ICompilationUnit[] { (ICompilationUnit) element }; |
| } |
| |
| return null; |
| } |
| |
| boolean match(char patternTypeSuffix, int modifiers) { |
| switch(patternTypeSuffix) { |
| case IIndexConstants.CLASS_SUFFIX : |
| return (modifiers & (Flags.AccAnnotation | Flags.AccInterface | Flags.AccEnum)) == 0; |
| case IIndexConstants.CLASS_AND_INTERFACE_SUFFIX: |
| return (modifiers & (Flags.AccAnnotation | Flags.AccEnum)) == 0; |
| case IIndexConstants.CLASS_AND_ENUM_SUFFIX: |
| return (modifiers & (Flags.AccAnnotation | Flags.AccInterface)) == 0; |
| case IIndexConstants.INTERFACE_SUFFIX : |
| return (modifiers & Flags.AccInterface) != 0; |
| case IIndexConstants.INTERFACE_AND_ANNOTATION_SUFFIX: |
| return (modifiers & (Flags.AccInterface | Flags.AccAnnotation)) != 0; |
| case IIndexConstants.ENUM_SUFFIX : |
| return (modifiers & Flags.AccEnum) != 0; |
| case IIndexConstants.ANNOTATION_TYPE_SUFFIX : |
| return (modifiers & Flags.AccAnnotation) != 0; |
| } |
| return true; |
| } |
| |
| boolean match(char patternTypeSuffix, char[] patternPkg, int matchRulePkg, char[] patternTypeName, int matchRuleType, int typeKind, char[] pkg, char[] typeName) { |
| switch(patternTypeSuffix) { |
| case IIndexConstants.CLASS_SUFFIX : |
| if (typeKind != TypeDeclaration.CLASS_DECL) return false; |
| break; |
| case IIndexConstants.CLASS_AND_INTERFACE_SUFFIX: |
| if (typeKind != TypeDeclaration.CLASS_DECL && typeKind != TypeDeclaration.INTERFACE_DECL) return false; |
| break; |
| case IIndexConstants.CLASS_AND_ENUM_SUFFIX: |
| if (typeKind != TypeDeclaration.CLASS_DECL && typeKind != TypeDeclaration.ENUM_DECL) return false; |
| break; |
| case IIndexConstants.INTERFACE_SUFFIX : |
| if (typeKind != TypeDeclaration.INTERFACE_DECL) return false; |
| break; |
| case IIndexConstants.INTERFACE_AND_ANNOTATION_SUFFIX: |
| if (typeKind != TypeDeclaration.INTERFACE_DECL && typeKind != TypeDeclaration.ANNOTATION_TYPE_DECL) return false; |
| break; |
| case IIndexConstants.ENUM_SUFFIX : |
| if (typeKind != TypeDeclaration.ENUM_DECL) return false; |
| break; |
| case IIndexConstants.ANNOTATION_TYPE_SUFFIX : |
| if (typeKind != TypeDeclaration.ANNOTATION_TYPE_DECL) return false; |
| break; |
| case IIndexConstants.TYPE_SUFFIX : // nothing |
| } |
| |
| boolean isPkgCaseSensitive = (matchRulePkg & SearchPattern.R_CASE_SENSITIVE) != 0; |
| if (patternPkg != null && !CharOperation.equals(patternPkg, pkg, isPkgCaseSensitive)) |
| return false; |
| |
| boolean isCaseSensitive = (matchRuleType & SearchPattern.R_CASE_SENSITIVE) != 0; |
| if (patternTypeName != null) { |
| boolean isCamelCase = (matchRuleType & (SearchPattern.R_CAMELCASE_MATCH | SearchPattern.R_CAMELCASE_SAME_PART_COUNT_MATCH)) != 0; |
| int matchMode = matchRuleType & JavaSearchPattern.MATCH_MODE_MASK; |
| if (!isCaseSensitive && !isCamelCase) { |
| patternTypeName = CharOperation.toLowerCase(patternTypeName); |
| } |
| boolean matchFirstChar = !isCaseSensitive || patternTypeName[0] == typeName[0]; |
| switch(matchMode) { |
| case SearchPattern.R_EXACT_MATCH : |
| return matchFirstChar && CharOperation.equals(patternTypeName, typeName, isCaseSensitive); |
| 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; |
| case SearchPattern.R_CAMELCASE_MATCH: |
| if (matchFirstChar && CharOperation.camelCaseMatch(patternTypeName, typeName, false)) { |
| return true; |
| } |
| return !isCaseSensitive && matchFirstChar && CharOperation.prefixEquals(patternTypeName, typeName, false); |
| case SearchPattern.R_CAMELCASE_SAME_PART_COUNT_MATCH: |
| return matchFirstChar && CharOperation.camelCaseMatch(patternTypeName, typeName, true); |
| } |
| } |
| return true; |
| |
| } |
| |
| boolean match(char[] patternName, int matchRule, char[] name) { |
| boolean isCaseSensitive = (matchRule & SearchPattern.R_CASE_SENSITIVE) != 0; |
| if (patternName != null) { |
| boolean isCamelCase = (matchRule & (SearchPattern.R_CAMELCASE_MATCH | SearchPattern.R_CAMELCASE_SAME_PART_COUNT_MATCH)) != 0; |
| int matchMode = matchRule & JavaSearchPattern.MATCH_MODE_MASK; |
| if (!isCaseSensitive && !isCamelCase) { |
| patternName = CharOperation.toLowerCase(patternName); |
| } |
| boolean matchFirstChar = !isCaseSensitive || patternName[0] == name[0]; |
| switch(matchMode) { |
| case SearchPattern.R_EXACT_MATCH : |
| return matchFirstChar && CharOperation.equals(patternName, name, isCaseSensitive); |
| case SearchPattern.R_PREFIX_MATCH : |
| return matchFirstChar && CharOperation.prefixEquals(patternName, name, isCaseSensitive); |
| case SearchPattern.R_PATTERN_MATCH : |
| return CharOperation.match(patternName, name, isCaseSensitive); |
| case SearchPattern.R_REGEXP_MATCH : |
| // TODO implement regular expression match |
| break; |
| case SearchPattern.R_CAMELCASE_MATCH: |
| if (matchFirstChar && CharOperation.camelCaseMatch(patternName, name, false)) { |
| return true; |
| } |
| return !isCaseSensitive && matchFirstChar && CharOperation.prefixEquals(patternName, name, false); |
| case SearchPattern.R_CAMELCASE_SAME_PART_COUNT_MATCH: |
| return matchFirstChar && CharOperation.camelCaseMatch(patternName, name, true); |
| } |
| } |
| return true; |
| } |
| |
| boolean match(char[] patternPkg, int matchRulePkg, |
| char[] patternDeclaringQualifier, int matchRuleDeclaringQualifier, |
| char[] patternDeclaringSimpleName, int matchRuleDeclaringSimpleName, |
| char[] patternMethodName, int methodMatchRule, |
| char[] packageName, char[] declaringQualifier, char[] declaringSimpleName, char[] methodName) { |
| |
| if (patternPkg != null && !CharOperation.equals(patternPkg, packageName, (matchRulePkg & SearchPattern.R_CASE_SENSITIVE) != 0)) |
| return false; |
| |
| return match(patternDeclaringQualifier, matchRuleDeclaringQualifier, declaringQualifier) && |
| match(patternDeclaringSimpleName, matchRuleDeclaringSimpleName, declaringSimpleName) && |
| match(patternMethodName, methodMatchRule, methodName); |
| |
| } |
| |
| boolean match(char[] patternFusedQualifier, int matchRuleFusedQualifier, |
| char[] patternMethodName, int methodMatchRule, |
| char[] packageName, char[] declaringQualifier, char[] declaringSimpleName, char[] methodName) { |
| |
| char[] q = packageName != null ? packageName : CharOperation.NO_CHAR; |
| if (declaringQualifier != null && declaringQualifier.length > 0) { |
| q = q.length > 0 ? CharOperation.concat(q, declaringQualifier, '.') : declaringQualifier; |
| } |
| if (declaringSimpleName != null && declaringSimpleName.length > 0) { |
| q = q.length > 0 ? CharOperation.concat(q, declaringSimpleName, '.') : declaringSimpleName; |
| } |
| |
| return match(patternFusedQualifier, matchRuleFusedQualifier, q) && |
| match(patternMethodName, methodMatchRule, methodName); |
| |
| } |
| /** |
| * Searches for matches of a given search pattern. Search patterns can be created using helper |
| * methods (from a String pattern or a Java 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, IJavaSearchScope 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); |
| } |
| |
| public void searchAllConstructorDeclarations( |
| final char[] packageName, |
| final char[] typeName, |
| final int typeMatchRule, |
| IJavaSearchScope scope, |
| final IRestrictedAccessConstructorRequestor nameRequestor, |
| int waitingPolicy, |
| IProgressMonitor progressMonitor) throws JavaModelException { |
| |
| // Validate match rule first |
| final int validatedTypeMatchRule = SearchPattern.validateMatchRule(typeName == null ? null : new String (typeName), typeMatchRule); |
| |
| final int pkgMatchRule = SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE; |
| final char NoSuffix = IIndexConstants.TYPE_SUFFIX; // Used as TYPE_SUFFIX has no effect in method #match(char, char[] , int, char[], int , int, char[], char[]) |
| |
| // Debug |
| if (VERBOSE) { |
| Util.verbose("BasicSearchEngine.searchAllConstructorDeclarations(char[], char[], int, IJavaSearchScope, IRestrictedAccessConstructorRequestor, int, IProgressMonitor)"); //$NON-NLS-1$ |
| Util.verbose(" - package name: "+(packageName==null?"null":new String(packageName))); //$NON-NLS-1$ //$NON-NLS-2$ |
| Util.verbose(" - type name: "+(typeName==null?"null":new String(typeName))); //$NON-NLS-1$ //$NON-NLS-2$ |
| Util.verbose(" - type match rule: "+getMatchRuleString(typeMatchRule)); //$NON-NLS-1$ |
| if (validatedTypeMatchRule != typeMatchRule) { |
| Util.verbose(" - validated type match rule: "+getMatchRuleString(validatedTypeMatchRule)); //$NON-NLS-1$ |
| } |
| Util.verbose(" - scope: "+scope); //$NON-NLS-1$ |
| } |
| if (validatedTypeMatchRule == -1) return; // invalid match rule => return no results |
| |
| // Create pattern |
| IndexManager indexManager = JavaModelManager.getIndexManager(); |
| final ConstructorDeclarationPattern pattern = new ConstructorDeclarationPattern( |
| packageName, |
| typeName, |
| validatedTypeMatchRule); |
| |
| // 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; |
| ICompilationUnit[] 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++) { |
| ICompilationUnit 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 |
| ConstructorDeclarationPattern record = (ConstructorDeclarationPattern)indexRecord; |
| |
| if ((record.extraFlags & ExtraFlags.IsMemberType) != 0) { |
| return true; // filter out member classes |
| } |
| if ((record.extraFlags & ExtraFlags.IsLocalType) != 0) { |
| return true; // filter out local and anonymous classes |
| } |
| switch (copiesLength) { |
| case 0: |
| break; |
| case 1: |
| if (singleWkcpPath.equals(documentPath)) { |
| return true; // filter 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.declaringPackageName==null || record.declaringPackageName.length==0) ? 0 : record.declaringPackageName.length+1; |
| int nameLength = record.declaringSimpleName==null ? 0 : record.declaringSimpleName.length; |
| char[] path = new char[pkgLength+nameLength]; |
| int pos = 0; |
| if (pkgLength > 0) { |
| System.arraycopy(record.declaringPackageName, 0, path, pos, pkgLength-1); |
| CharOperation.replace(path, '.', '/'); |
| path[pkgLength-1] = '/'; |
| pos += pkgLength; |
| } |
| if (nameLength > 0) { |
| System.arraycopy(record.declaringSimpleName, 0, path, pos, nameLength); |
| pos += nameLength; |
| } |
| // Update access restriction if path is not empty |
| if (pos > 0) { |
| accessRestriction = access.getViolatedRestriction(path); |
| } |
| } |
| nameRequestor.acceptConstructor( |
| record.modifiers, |
| record.declaringSimpleName, |
| record.parameterCount, |
| record.signature, |
| record.parameterTypes, |
| record.parameterNames, |
| record.declaringTypeModifiers, |
| record.declaringPackageName, |
| record.extraFlags, |
| documentPath, |
| accessRestriction); |
| return true; |
| } |
| }; |
| |
| SubMonitor subMonitor = SubMonitor.convert(progressMonitor, Messages.engine_searching, 1000); |
| // add type names from indexes |
| indexManager.performConcurrentJob( |
| new PatternSearchJob( |
| pattern, |
| getDefaultSearchParticipant(), // Java search only |
| scope, |
| searchRequestor), |
| waitingPolicy, |
| subMonitor.split(Math.max(1000-copiesLength, 0))); |
| |
| // add type names from working copies |
| if (copies != null) { |
| for (int i = 0; i < copiesLength; i++) { |
| SubMonitor iterationMonitor = subMonitor.split(1); |
| final ICompilationUnit workingCopy = copies[i]; |
| if (scope instanceof HierarchyScope) { |
| if (!((HierarchyScope)scope).encloses(workingCopy, iterationMonitor)) continue; |
| } else { |
| 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.getAllTypes(); |
| for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) { |
| IType type = allTypes[j]; |
| char[] simpleName = type.getElementName().toCharArray(); |
| if (match(NoSuffix, packageName, pkgMatchRule, typeName, validatedTypeMatchRule, 0/*no kind*/, packageDeclaration, simpleName) && !type.isMember()) { |
| |
| int extraFlags = ExtraFlags.getExtraFlags(type); |
| |
| boolean hasConstructor = false; |
| |
| IMethod[] methods = type.getMethods(); |
| for (int k = 0; k < methods.length; k++) { |
| IMethod method = methods[k]; |
| if (method.isConstructor()) { |
| hasConstructor = true; |
| |
| String[] stringParameterNames = method.getParameterNames(); |
| String[] stringParameterTypes = method.getParameterTypes(); |
| int length = stringParameterNames.length; |
| char[][] parameterNames = new char[length][]; |
| char[][] parameterTypes = new char[length][]; |
| for (int l = 0; l < length; l++) { |
| parameterNames[l] = stringParameterNames[l].toCharArray(); |
| parameterTypes[l] = Signature.toCharArray(Signature.getTypeErasure(stringParameterTypes[l]).toCharArray()); |
| } |
| |
| nameRequestor.acceptConstructor( |
| method.getFlags(), |
| simpleName, |
| parameterNames.length, |
| null,// signature is not used for source type |
| parameterTypes, |
| parameterNames, |
| type.getFlags(), |
| packageDeclaration, |
| extraFlags, |
| path, |
| null); |
| } |
| } |
| |
| if (!hasConstructor) { |
| nameRequestor.acceptConstructor( |
| Flags.AccPublic, |
| simpleName, |
| -1, |
| null, // signature is not used for source type |
| CharOperation.NO_CHAR_CHAR, |
| CharOperation.NO_CHAR_CHAR, |
| type.getFlags(), |
| packageDeclaration, |
| extraFlags, |
| path, |
| null); |
| } |
| } |
| } |
| } else { |
| Parser basicParser = getParser(); |
| org.eclipse.jdt.internal.compiler.env.ICompilationUnit unit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) workingCopy; |
| CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.compilerOptions.maxProblemsPerUnit); |
| CompilationUnitDeclaration parsedUnit = basicParser.dietParse(unit, compilationUnitResult); |
| if (parsedUnit != null) { |
| final char[] packageDeclaration = parsedUnit.currentPackage == null ? CharOperation.NO_CHAR : CharOperation.concatWith(parsedUnit.currentPackage.getImportName(), '.'); |
| class AllConstructorDeclarationsVisitor extends ASTVisitor { |
| private TypeDeclaration[] declaringTypes = new TypeDeclaration[0]; |
| private int declaringTypesPtr = -1; |
| |
| private void endVisit(TypeDeclaration typeDeclaration) { |
| if (!hasConstructor(typeDeclaration) && typeDeclaration.enclosingType == null) { |
| |
| if (match(NoSuffix, packageName, pkgMatchRule, typeName, validatedTypeMatchRule, 0/*no kind*/, packageDeclaration, typeDeclaration.name)) { |
| nameRequestor.acceptConstructor( |
| Flags.AccPublic, |
| typeName, |
| -1, |
| null, // signature is not used for source type |
| CharOperation.NO_CHAR_CHAR, |
| CharOperation.NO_CHAR_CHAR, |
| typeDeclaration.modifiers, |
| packageDeclaration, |
| ExtraFlags.getExtraFlags(typeDeclaration), |
| path, |
| null); |
| } |
| } |
| |
| this.declaringTypes[this.declaringTypesPtr] = null; |
| this.declaringTypesPtr--; |
| } |
| |
| public void endVisit(TypeDeclaration typeDeclaration, CompilationUnitScope s) { |
| endVisit(typeDeclaration); |
| } |
| |
| public void endVisit(TypeDeclaration memberTypeDeclaration, ClassScope s) { |
| endVisit(memberTypeDeclaration); |
| } |
| |
| private boolean hasConstructor(TypeDeclaration typeDeclaration) { |
| AbstractMethodDeclaration[] methods = typeDeclaration.methods; |
| int length = methods == null ? 0 : methods.length; |
| for (int j = 0; j < length; j++) { |
| if (methods[j].isConstructor()) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope classScope) { |
| TypeDeclaration typeDeclaration = this.declaringTypes[this.declaringTypesPtr]; |
| if (match(NoSuffix, packageName, pkgMatchRule, typeName, validatedTypeMatchRule, 0/*no kind*/, packageDeclaration, typeDeclaration.name)) { |
| Argument[] arguments = constructorDeclaration.arguments; |
| int length = arguments == null ? 0 : arguments.length; |
| char[][] parameterNames = new char[length][]; |
| char[][] parameterTypes = new char[length][]; |
| for (int l = 0; l < length; l++) { |
| Argument argument = arguments[l]; |
| parameterNames[l] = argument.name; |
| if (argument.type instanceof SingleTypeReference) { |
| parameterTypes[l] = ((SingleTypeReference)argument.type).token; |
| //{ObjectTeams: one more kind of type reference: (note that TypeAnchorReference cannot occur as an argument type) |
| } else if (argument.type instanceof LiftingTypeReference) { |
| parameterTypes[l] = CharOperation.concatWith(((LiftingTypeReference)argument.type).baseTokens, '.'); |
| //SH} |
| } else { |
| parameterTypes[l] = CharOperation.concatWith(((QualifiedTypeReference)argument.type).tokens, '.'); |
| } |
| } |
| |
| TypeDeclaration enclosing = typeDeclaration.enclosingType; |
| char[][] enclosingTypeNames = CharOperation.NO_CHAR_CHAR; |
| while (enclosing != null) { |
| enclosingTypeNames = CharOperation.arrayConcat(new char[][] {enclosing.name}, enclosingTypeNames); |
| if ((enclosing.bits & ASTNode.IsMemberType) != 0) { |
| enclosing = enclosing.enclosingType; |
| } else { |
| enclosing = null; |
| } |
| } |
| |
| nameRequestor.acceptConstructor( |
| constructorDeclaration.modifiers, |
| typeName, |
| parameterNames.length, |
| null, // signature is not used for source type |
| parameterTypes, |
| parameterNames, |
| typeDeclaration.modifiers, |
| packageDeclaration, |
| ExtraFlags.getExtraFlags(typeDeclaration), |
| path, |
| null); |
| } |
| return false; // no need to find constructors from local/anonymous type |
| } |
| public boolean visit(TypeDeclaration typeDeclaration, BlockScope blockScope) { |
| return false; |
| } |
| |
| private boolean visit(TypeDeclaration typeDeclaration) { |
| if(this.declaringTypes.length <= ++this.declaringTypesPtr) { |
| int length = this.declaringTypesPtr; |
| System.arraycopy(this.declaringTypes, 0, this.declaringTypes = new TypeDeclaration[length * 2 + 1], 0, length); |
| } |
| this.declaringTypes[this.declaringTypesPtr] = typeDeclaration; |
| return true; |
| } |
| |
| public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope s) { |
| return visit(typeDeclaration); |
| } |
| |
| public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope s) { |
| return visit(memberTypeDeclaration); |
| } |
| } |
| parsedUnit.traverse(new AllConstructorDeclarationsVisitor(), parsedUnit.scope); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Searches for all method declarations in the given scope. |
| * * <p> |
| * Warning: This API is in experimental phase and may be modified/removed. Do not use this until this |
| * comment is removed. |
| * </p> |
| * |
| * @see SearchEngine#searchAllMethodNames(char[], int, char[], int, IJavaSearchScope, MethodNameMatchRequestor, int, IProgressMonitor) |
| * for detailed comments |
| */ |
| public void searchAllMethodNames( |
| final char[] qualifier, |
| final int qualifierMatchRule, |
| final char[] methodName, |
| final int methodMatchRule, |
| IJavaSearchScope scope, |
| final IRestrictedAccessMethodRequestor nameRequestor, |
| int waitingPolicy, |
| IProgressMonitor progressMonitor) throws JavaModelException { |
| |
| // Validate match rule first |
| final int validatedMethodMatchRule = SearchPattern.validateMatchRule(methodName == null ? null : new String (methodName), methodMatchRule); |
| // Debug |
| if (VERBOSE) { |
| Util.verbose("BasicSearchEngine.searchAllMethodDeclarations(char[] qualifier, "//$NON-NLS-1$ |
| + "char[] methodName, int methodMatchRule, IJavaSearchScope, IRestrictedAccessConstructorRequestor, int waitingPolicy, IProgressMonitor)"); //$NON-NLS-1$ |
| Util.verbose(" - qualifier name: "+(qualifier==null?"null":new String(qualifier))); //$NON-NLS-1$ //$NON-NLS-2$ |
| Util.verbose(" - method name: "+(methodName==null?"null":new String(methodName))); //$NON-NLS-1$ //$NON-NLS-2$ |
| Util.verbose(" - method match rule: "+getMatchRuleString(methodMatchRule)); //$NON-NLS-1$ |
| if (validatedMethodMatchRule != methodMatchRule) { |
| Util.verbose(" - validated method match rule: "+getMatchRuleString(validatedMethodMatchRule)); //$NON-NLS-1$ |
| } |
| Util.verbose(" - scope: "+scope); //$NON-NLS-1$ |
| } |
| if (validatedMethodMatchRule == -1) return; // invalid match rule => return no results |
| |
| // Create pattern |
| IndexManager indexManager = JavaModelManager.getIndexManager(); |
| final MethodDeclarationPattern pattern = new MethodDeclarationPattern(qualifier, methodName, methodMatchRule); |
| |
| // 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; |
| ICompilationUnit[] 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++) { |
| ICompilationUnit 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) { |
| MethodDeclarationPattern record = (MethodDeclarationPattern)indexRecord; |
| |
| if ((record.extraFlags & ExtraFlags.IsLocalType) != 0) { |
| return true; // filter out local and anonymous classes |
| } |
| switch (copiesLength) { |
| case 0: |
| break; |
| case 1: |
| if (singleWkcpPath.equals(documentPath)) { |
| return true; // filter 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.declaringPackageName==null || record.declaringPackageName.length==0) ? 0 : record.declaringPackageName.length+1; |
| int qualificationLength = (record.declaringQualification == null || record.declaringQualification.length == 0) ? 0 : record.declaringQualification.length; |
| int nameLength = record.declaringSimpleName==null ? 0 : record.declaringSimpleName.length; |
| char[] path = new char[pkgLength + qualificationLength + nameLength]; |
| int pos = 0; |
| if (pkgLength > 0) { |
| System.arraycopy(record.declaringPackageName, 0, path, pos, pkgLength-1); |
| CharOperation.replace(path, '.', '/'); |
| path[pkgLength-1] = '/'; |
| pos += pkgLength; |
| } |
| if (qualificationLength > 0) { |
| System.arraycopy(record.declaringQualification, 0, path, pos, qualificationLength); |
| } |
| if (nameLength > 0) { |
| System.arraycopy(record.declaringSimpleName, 0, path, pos, nameLength); |
| pos += nameLength; |
| } |
| // Update access restriction if path is not empty |
| if (pos > 0) { |
| accessRestriction = access.getViolatedRestriction(path); |
| } |
| } |
| if (match(qualifier, qualifierMatchRule, methodName, methodMatchRule, |
| record.declaringPackageName, record.declaringQualification, record.declaringSimpleName, record.selector)) { |
| nameRequestor.acceptMethod( |
| record.selector, |
| record.parameterCount, |
| record.declaringQualification, |
| record.declaringSimpleName, |
| record.declaringTypeModifiers, |
| record.declaringPackageName, |
| record.signature, |
| record.parameterTypes, |
| record.parameterNames, |
| record.returnSimpleName, |
| record.modifiers, |
| documentPath, |
| accessRestriction, |
| -1 /* method index not applicable as there is no IType here */); |
| } |
| return true; |
| } |
| }; |
| |
| SubMonitor subMonitor = SubMonitor.convert(progressMonitor, Messages.engine_searching, 1000); |
| // add type names from indexes |
| indexManager.performConcurrentJob( |
| new PatternSearchJob( |
| pattern, |
| getDefaultSearchParticipant(), // Java search only |
| scope, |
| searchRequestor), |
| waitingPolicy, |
| subMonitor.split(Math.max(1000-copiesLength, 0))); |
| |
| // add type names from working copies |
| if (copies != null) { |
| for (int i = 0; i < copiesLength; i++) { |
| SubMonitor iterationMonitor = subMonitor.split(1); |
| final ICompilationUnit workingCopy = copies[i]; |
| if (scope instanceof HierarchyScope) { |
| if (!((HierarchyScope)scope).encloses(workingCopy, iterationMonitor)) continue; |
| } else { |
| 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.getAllTypes(); |
| for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) { |
| IType type = allTypes[j]; |
| IJavaElement parent = type.getParent(); |
| char[] rDeclaringQualification = parent instanceof IType ? ((IType) parent).getTypeQualifiedName('.').toCharArray() : CharOperation.NO_CHAR; |
| char[] rSimpleName = type.getElementName().toCharArray(); |
| char[] q = CharOperation.concatNonEmpty(packageDeclaration, '.', rDeclaringQualification, '.', rSimpleName); |
| if (!match(qualifier, qualifierMatchRule, q)) |
| continue; |
| reportMatchingMethods(methodName, methodMatchRule, nameRequestor, path, |
| packageDeclaration, type, rDeclaringQualification, rSimpleName); |
| } |
| } else { |
| Parser basicParser = getParser(); |
| org.eclipse.jdt.internal.compiler.env.ICompilationUnit unit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) workingCopy; |
| CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.compilerOptions.maxProblemsPerUnit); |
| CompilationUnitDeclaration parsedUnit = basicParser.dietParse(unit, compilationUnitResult); |
| if (parsedUnit != null) { |
| final char[] packageDeclaration = parsedUnit.currentPackage == null ? CharOperation.NO_CHAR : CharOperation.concatWith(parsedUnit.currentPackage.getImportName(), '.'); |
| class AllMethodDeclarationVisitor extends ASTVisitor { |
| |
| class TypeInfo { |
| public TypeDeclaration typeDecl; |
| public IType type; |
| public boolean visitMethods; |
| public char[] enclosingTypeName; |
| |
| TypeInfo(TypeDeclaration typeDecl, boolean visitMethods, char[] enclosingTypeName) { |
| this.typeDecl = typeDecl; |
| this.type = workingCopy.getType(new String(typeDecl.name)); |
| this.visitMethods = visitMethods; |
| this.enclosingTypeName = enclosingTypeName; |
| } |
| } |
| Stack<TypeInfo> typeInfoStack = new Stack<>(); |
| IType getCurrentType() { |
| int l = this.typeInfoStack.size(); |
| if (l <= 0) return null; |
| TypeInfo typeInfo = this.typeInfoStack.get(0); |
| IType type = typeInfo.type; |
| if (type == null) { |
| TypeInfo ti = this.typeInfoStack.get(0); |
| ti.type = ti.type == null ? workingCopy.getType(new String(ti.typeDecl.name)) : ti.type; |
| type = ti.type; |
| for (int j = 1; j < l && type != null; ++j) { |
| ti = this.typeInfoStack.get(j); |
| if (ti.type == null) { |
| ti.type = type.getType(new String(ti.typeDecl.name)); |
| } |
| type = ti.type; |
| } |
| } |
| return type; |
| } |
| |
| private void addStackEntry(TypeDeclaration typeDeclaration, char[] enclosingTypeName) { |
| char[] q = CharOperation.concatNonEmpty(packageDeclaration, '.', enclosingTypeName, '.', typeDeclaration.name); |
| boolean visitMethods = match(qualifier, qualifierMatchRule, q); |
| this.typeInfoStack.push(new TypeInfo(typeDeclaration, visitMethods, enclosingTypeName)); |
| } |
| public void endVisit(TypeDeclaration typeDeclaration, CompilationUnitScope s) { |
| this.typeInfoStack.pop(); |
| } |
| public void endVisit(TypeDeclaration memberTypeDeclaration, ClassScope s) { |
| this.typeInfoStack.pop(); |
| } |
| public boolean visit(MethodDeclaration methodDeclaration, ClassScope classScope) { |
| TypeInfo typeInfo = this.typeInfoStack.peek(); |
| if (typeInfo.visitMethods && |
| match(methodName, methodMatchRule, methodDeclaration.selector)) { |
| reportMatchingMethod(path, packageDeclaration, |
| typeInfo.enclosingTypeName, |
| typeInfo.typeDecl, |
| methodDeclaration, |
| getCurrentType(), |
| nameRequestor); |
| } |
| |
| return false; // no need to find methods from local/anonymous type |
| } |
| public boolean visit(TypeDeclaration typeDeclaration, BlockScope blockScope) { |
| return false; // do not visit local/anonymous types |
| } |
| public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope s) { |
| addStackEntry(typeDeclaration, CharOperation.NO_CHAR); |
| return true; |
| } |
| public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope s) { |
| TypeInfo typeInfo = this.typeInfoStack.peek(); |
| addStackEntry(memberTypeDeclaration, typeInfo.enclosingTypeName == CharOperation.NO_CHAR ? typeInfo.typeDecl.name : |
| CharOperation.concat(typeInfo.enclosingTypeName, typeInfo.typeDecl.name, '.')); |
| return true; |
| } |
| } |
| parsedUnit.traverse(new AllMethodDeclarationVisitor(), parsedUnit.scope); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Searches for all method declarations in the given scope. |
| * * <p> |
| * Warning: This API is in experimental phase and may be modified/removed. Do not use this until this |
| * comment is removed. |
| * </p> |
| * |
| * @see SearchEngine#searchAllMethodNames(char[], int, char[], int, char[], int, char[], int, IJavaSearchScope, MethodNameMatchRequestor, int, IProgressMonitor) |
| * for detailed comments |
| */ |
| public void searchAllMethodNames( |
| final char[] packageName, |
| final int pkgMatchRule, |
| final char[] declaringQualification, |
| final int declQualificationMatchRule, |
| final char[] declaringSimpleName, |
| final int declSimpleNameMatchRule, |
| final char[] methodName, |
| final int methodMatchRule, |
| IJavaSearchScope scope, |
| final IRestrictedAccessMethodRequestor nameRequestor, |
| int waitingPolicy, |
| IProgressMonitor progressMonitor) throws JavaModelException { |
| |
| // Validate match rule first |
| final int validatedMethodMatchRule = SearchPattern.validateMatchRule(methodName == null ? null : new String (methodName), methodMatchRule); |
| // Debug |
| if (VERBOSE) { |
| Util.verbose("BasicSearchEngine.searchAllMethodDeclarations(char[] packageName, char[] declaringQualification, char[] declaringSimpleName, "//$NON-NLS-1$ |
| + "char[] methodName, int methodMatchRule, IJavaSearchScope, IRestrictedAccessConstructorRequestor, int waitingPolicy, IProgressMonitor)"); //$NON-NLS-1$ |
| Util.verbose(" - package name: "+(packageName==null?"null":new String(packageName))); //$NON-NLS-1$ //$NON-NLS-2$ |
| Util.verbose(" - declaringQualification name: "+(declaringQualification==null?"null":new String(declaringQualification))); //$NON-NLS-1$ //$NON-NLS-2$ |
| Util.verbose(" - declaringSimple name: "+(declaringSimpleName==null?"null":new String(declaringSimpleName))); //$NON-NLS-1$ //$NON-NLS-2$ |
| Util.verbose(" - method name: "+(methodName==null?"null":new String(methodName))); //$NON-NLS-1$ //$NON-NLS-2$ |
| Util.verbose(" - method match rule: "+getMatchRuleString(methodMatchRule)); //$NON-NLS-1$ |
| if (validatedMethodMatchRule != methodMatchRule) { |
| Util.verbose(" - validated method match rule: "+getMatchRuleString(validatedMethodMatchRule)); //$NON-NLS-1$ |
| } |
| Util.verbose(" - scope: "+scope); //$NON-NLS-1$ |
| } |
| if (validatedMethodMatchRule == -1) return; // invalid match rule => return no results |
| |
| // Create pattern |
| IndexManager indexManager = JavaModelManager.getIndexManager(); |
| final MethodDeclarationPattern pattern = new MethodDeclarationPattern(packageName, declaringQualification, declaringSimpleName, methodName, methodMatchRule); |
| |
| // 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; |
| ICompilationUnit[] 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++) { |
| ICompilationUnit 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) { |
| MethodDeclarationPattern record = (MethodDeclarationPattern)indexRecord; |
| |
| if ((record.extraFlags & ExtraFlags.IsLocalType) != 0) { |
| return true; // filter out local and anonymous classes |
| } |
| switch (copiesLength) { |
| case 0: |
| break; |
| case 1: |
| if (singleWkcpPath.equals(documentPath)) { |
| return true; // filter 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.declaringPackageName==null || record.declaringPackageName.length==0) ? 0 : record.declaringPackageName.length+1; |
| int qualificationLength = (record.declaringQualification == null || record.declaringQualification.length == 0) ? 0 : record.declaringQualification.length; |
| int nameLength = record.declaringSimpleName==null ? 0 : record.declaringSimpleName.length; |
| char[] path = new char[pkgLength + qualificationLength + nameLength]; |
| int pos = 0; |
| if (pkgLength > 0) { |
| System.arraycopy(record.declaringPackageName, 0, path, pos, pkgLength-1); |
| CharOperation.replace(path, '.', '/'); |
| path[pkgLength-1] = '/'; |
| pos += pkgLength; |
| } |
| if (qualificationLength > 0) { |
| System.arraycopy(record.declaringQualification, 0, path, pos, qualificationLength); |
| } |
| if (nameLength > 0) { |
| System.arraycopy(record.declaringSimpleName, 0, path, pos, nameLength); |
| pos += nameLength; |
| } |
| // Update access restriction if path is not empty |
| if (pos > 0) { |
| accessRestriction = access.getViolatedRestriction(path); |
| } |
| } |
| if (match(packageName, pkgMatchRule, declaringQualification, declQualificationMatchRule, declaringSimpleName, declSimpleNameMatchRule, methodName, methodMatchRule, |
| record.declaringPackageName, record.declaringQualification, record.declaringSimpleName, record.selector)) { |
| nameRequestor.acceptMethod( |
| record.selector, |
| record.parameterCount, |
| record.declaringQualification, |
| record.declaringSimpleName, |
| record.declaringTypeModifiers, |
| record.declaringPackageName, |
| record.signature, |
| record.parameterTypes, |
| record.parameterNames, |
| record.returnSimpleName, |
| record.modifiers, |
| documentPath, |
| accessRestriction, |
| -1 /* method index not applicable as there is no IType here */); |
| } |
| return true; |
| } |
| }; |
| |
| SubMonitor subMonitor = SubMonitor.convert(progressMonitor, Messages.engine_searching, 1000); |
| // add type names from indexes |
| indexManager.performConcurrentJob( |
| new PatternSearchJob( |
| pattern, |
| getDefaultSearchParticipant(), // Java search only |
| scope, |
| searchRequestor), |
| waitingPolicy, |
| subMonitor.split(Math.max(1000-copiesLength, 0))); |
| |
| // add type names from working copies |
| if (copies != null) { |
| boolean isPkgCaseSensitive = (pkgMatchRule & SearchPattern.R_CASE_SENSITIVE) != 0; |
| for (int i = 0; i < copiesLength; i++) { |
| SubMonitor iterationMonitor = subMonitor.split(1); |
| final ICompilationUnit workingCopy = copies[i]; |
| if (scope instanceof HierarchyScope) { |
| if (!((HierarchyScope)scope).encloses(workingCopy, iterationMonitor)) continue; |
| } else { |
| 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(); |
| if (packageName != null && !CharOperation.equals(packageName, packageDeclaration, isPkgCaseSensitive)) |
| continue; |
| |
| IType[] allTypes = workingCopy.getAllTypes(); |
| for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) { |
| IType type = allTypes[j]; |
| IJavaElement parent = type.getParent(); |
| char[] rDeclaringQualification = parent instanceof IType ? ((IType) parent).getTypeQualifiedName('.').toCharArray() : CharOperation.NO_CHAR; |
| char[] rSimpleName = type.getElementName().toCharArray(); |
| if (!match(declaringQualification, declQualificationMatchRule, rDeclaringQualification) || |
| !match(declaringSimpleName, declSimpleNameMatchRule, rSimpleName)) |
| continue; |
| reportMatchingMethods(methodName, methodMatchRule, nameRequestor, path, |
| packageDeclaration, type, rDeclaringQualification, rSimpleName); |
| } |
| } else { |
| Parser basicParser = getParser(); |
| org.eclipse.jdt.internal.compiler.env.ICompilationUnit unit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) workingCopy; |
| CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.compilerOptions.maxProblemsPerUnit); |
| CompilationUnitDeclaration parsedUnit = basicParser.dietParse(unit, compilationUnitResult); |
| if (parsedUnit != null) { |
| final char[] packageDeclaration = parsedUnit.currentPackage == null ? CharOperation.NO_CHAR : CharOperation.concatWith(parsedUnit.currentPackage.getImportName(), '.'); |
| class AllMethodDeclarationVisitor extends ASTVisitor { |
| |
| class TypeInfo { |
| public TypeDeclaration typeDecl; |
| public IType type; |
| public boolean visitMethods; |
| public char[] enclosingTypeName; |
| |
| TypeInfo(TypeDeclaration typeDecl, boolean visitMethods, char[] enclosingTypeName) { |
| this.typeDecl = typeDecl; |
| this.type = workingCopy.getType(new String(typeDecl.name)); |
| this.visitMethods = visitMethods; |
| this.enclosingTypeName = enclosingTypeName; |
| } |
| } |
| Stack<TypeInfo> typeInfoStack = new Stack<>(); |
| IType getCurrentType() { |
| int l = this.typeInfoStack.size(); |
| if (l <= 0) return null; |
| TypeInfo typeInfo = this.typeInfoStack.get(0); |
| IType type = typeInfo.type; |
| if (type == null) { |
| TypeInfo ti = this.typeInfoStack.get(0); |
| ti.type = ti.type == null ? workingCopy.getType(new String(ti.typeDecl.name)) : ti.type; |
| type = ti.type; |
| for (int j = 1; j < l && type != null; ++j) { |
| ti = this.typeInfoStack.get(j); |
| if (ti.type == null) { |
| ti.type = type.getType(new String(ti.typeDecl.name)); |
| } |
| type = ti.type; |
| } |
| } |
| return type; |
| } |
| |
| private void addStackEntry(TypeDeclaration typeDeclaration, char[] enclosingTypeName) { |
| boolean visitMethods = match(declaringQualification, declQualificationMatchRule, enclosingTypeName) && |
| match(declaringSimpleName, declSimpleNameMatchRule, typeDeclaration.name); |
| this.typeInfoStack.push(new TypeInfo(typeDeclaration, visitMethods, enclosingTypeName)); |
| } |
| public void endVisit(TypeDeclaration typeDeclaration, CompilationUnitScope s) { |
| this.typeInfoStack.pop(); |
| } |
| public void endVisit(TypeDeclaration memberTypeDeclaration, ClassScope s) { |
| this.typeInfoStack.pop(); |
| } |
| public boolean visit(MethodDeclaration methodDeclaration, ClassScope classScope) { |
| TypeInfo typeInfo = this.typeInfoStack.peek(); |
| if (typeInfo.visitMethods && |
| match(methodName, methodMatchRule, methodDeclaration.selector)) { |
| reportMatchingMethod(path, packageDeclaration, |
| typeInfo.enclosingTypeName, |
| typeInfo.typeDecl, |
| methodDeclaration, |
| getCurrentType(), |
| nameRequestor); |
| } |
| |
| return false; // no need to find methods from local/anonymous type |
| } |
| public boolean visit(TypeDeclaration typeDeclaration, BlockScope blockScope) { |
| return false; // do not visit local/anonymous types |
| } |
| public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope s) { |
| addStackEntry(typeDeclaration, CharOperation.NO_CHAR); |
| return true; |
| } |
| public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope s) { |
| TypeInfo typeInfo = this.typeInfoStack.peek(); |
| addStackEntry(memberTypeDeclaration, typeInfo.enclosingTypeName == CharOperation.NO_CHAR ? typeInfo.typeDecl.name : |
| CharOperation.concat(typeInfo.enclosingTypeName, typeInfo.typeDecl.name, '.')); |
| return true; |
| } |
| } |
| if (match(packageName, pkgMatchRule, packageDeclaration)) |
| parsedUnit.traverse(new AllMethodDeclarationVisitor(), parsedUnit.scope); |
| } |
| } |
| } |
| } |
| } |
| |
| void reportMatchingMethod( |
| final String path, |
| final char[] packageDeclaration, |
| final char[] declaringQualifier, |
| final TypeDeclaration typeDeclaration, |
| final MethodDeclaration methodDeclaration, |
| final IType type, |
| final IRestrictedAccessMethodRequestor nameRequestor) { |
| |
| Argument[] arguments = methodDeclaration.arguments; |
| int argsLength = 0; |
| char[][] parameterTypes = CharOperation.NO_CHAR_CHAR; |
| char[][] parameterNames = CharOperation.NO_CHAR_CHAR; |
| if (arguments != null) { |
| argsLength = arguments.length; |
| parameterTypes = new char[argsLength][]; |
| parameterNames = new char[argsLength][]; |
| } |
| for (int i = 0; i < argsLength; ++i) { |
| Argument argument = arguments[i]; |
| parameterNames[i] = argument.name; |
| parameterTypes[i] = CharOperation.concatWith(argument.type.getTypeName(), '.'); |
| } |
| if (nameRequestor instanceof MethodNameMatchRequestorWrapper) { |
| IMethod method = type.getMethod(new String(methodDeclaration.selector), CharOperation.toStrings(parameterTypes)); |
| ((MethodNameMatchRequestorWrapper)nameRequestor).requestor.acceptMethodNameMatch(new JavaSearchMethodNameMatch(method, methodDeclaration.modifiers)); |
| } else { |
| char[] returnType = CharOperation.toString(methodDeclaration.returnType.getTypeName()).toCharArray(); |
| nameRequestor.acceptMethod( |
| methodDeclaration.selector, |
| argsLength, |
| declaringQualifier, |
| typeDeclaration.name, |
| typeDeclaration.modifiers, |
| packageDeclaration, |
| null, |
| parameterTypes, |
| parameterNames, |
| returnType, |
| methodDeclaration.modifiers, |
| path, |
| null, |
| -1 /* method index */); |
| } |
| } |
| void reportMatchingMethods(final char[] methodName, final int methodMatchRule, |
| final IRestrictedAccessMethodRequestor nameRequestor, final String path, char[] packageDeclaration, |
| IType type, char[] rDeclaringQualification, char[] rSimpleName) |
| throws JavaModelException { |
| IMethod[] methods = type.getMethods(); |
| |
| for (int k = 0; k < methods.length; k++) { |
| IMethod method = methods[k]; |
| if (method.isConstructor()) continue; |
| |
| char[] rMethodName = method.getElementName().toCharArray(); |
| if (match(methodName, methodMatchRule, rMethodName)) { |
| if (nameRequestor instanceof MethodNameMatchRequestorWrapper) { |
| ((MethodNameMatchRequestorWrapper) nameRequestor).requestor.acceptMethodNameMatch(new JavaSearchMethodNameMatch(method, method.getFlags())); |
| } else { |
| |
| String[] stringParameterNames = method.getParameterNames(); |
| String[] stringParameterTypes = method.getParameterTypes(); |
| int length = stringParameterNames.length; |
| char[][] parameterNames = new char[length][]; |
| char[][] parameterTypes = new char[length][]; |
| for (int l = 0; l < length; l++) { |
| parameterNames[l] = stringParameterNames[l].toCharArray(); |
| parameterTypes[l] = Signature.toCharArray(Signature.getTypeErasure(stringParameterTypes[l]).toCharArray()); |
| } |
| String returnSignature = method.getReturnType(); |
| char[] signature = returnSignature.toCharArray(); |
| char[] returnErasure = Signature.toCharArray(Signature.getTypeErasure(signature)); |
| CharOperation.replace(returnErasure, '$', '.'); |
| char[] returnTypeName = returnErasure; |
| |
| nameRequestor.acceptMethod( |
| rMethodName, |
| parameterNames.length, |
| rDeclaringQualification, |
| rSimpleName, |
| type.getFlags(), |
| packageDeclaration, |
| null, // signature not used for source |
| parameterTypes, |
| parameterNames, |
| returnTypeName, |
| method.getFlags(), |
| path, |
| null, |
| k); |
| } |
| } |
| } |
| } |
| |
| /** |
| * 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( |
| IPackageFragmentRoot[] sourceFolders, |
| final IRestrictedAccessTypeRequestor nameRequestor, |
| boolean waitForIndexes, |
| IProgressMonitor progressMonitor) throws JavaModelException { |
| |
| if (VERBOSE) { |
| Util.verbose("BasicSearchEngine.searchAllSecondaryTypeNames(IPackageFragmentRoot[], 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 = JavaModelManager.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; |
| ICompilationUnit[] 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++) { |
| ICompilationUnit 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 |
| try { |
| SubMonitor subMonitor = SubMonitor.convert(progressMonitor, Messages.engine_searching, 100); |
| indexManager.performConcurrentJob( |
| new PatternSearchJob( |
| pattern, |
| getDefaultSearchParticipant(), // Java search only |
| createJavaSearchScope(sourceFolders), |
| searchRequestor), |
| waitForIndexes |
| ? IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH |
| : IJavaSearchConstants.FORCE_IMMEDIATE_SEARCH, |
| subMonitor.split(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[], int, char[], int, int, IJavaSearchScope, TypeNameRequestor, int, IProgressMonitor) |
| * for detailed comment |
| */ |
| public void searchAllTypeNames( |
| final char[] packageName, |
| final int packageMatchRule, |
| final char[] typeName, |
| final int typeMatchRule, |
| int searchFor, |
| IJavaSearchScope scope, |
| final IRestrictedAccessTypeRequestor nameRequestor, |
| int waitingPolicy, |
| IProgressMonitor progressMonitor) throws JavaModelException { |
| |
| // Validate match rule first |
| final int validatedTypeMatchRule = SearchPattern.validateMatchRule(typeName == null ? null : new String (typeName), typeMatchRule); |
| |
| // Debug |
| if (VERBOSE) { |
| Util.verbose("BasicSearchEngine.searchAllTypeNames(char[], char[], int, int, IJavaSearchScope, IRestrictedAccessTypeRequestor, int, IProgressMonitor)"); //$NON-NLS-1$ |
| Util.verbose(" - package name: "+(packageName==null?"null":new String(packageName))); //$NON-NLS-1$ //$NON-NLS-2$ |
| Util.verbose(" - package match rule: "+getMatchRuleString(packageMatchRule)); //$NON-NLS-1$ |
| Util.verbose(" - type name: "+(typeName==null?"null":new String(typeName))); //$NON-NLS-1$ //$NON-NLS-2$ |
| Util.verbose(" - type match rule: "+getMatchRuleString(typeMatchRule)); //$NON-NLS-1$ |
| if (validatedTypeMatchRule != typeMatchRule) { |
| Util.verbose(" - validated type match rule: "+getMatchRuleString(validatedTypeMatchRule)); //$NON-NLS-1$ |
| } |
| Util.verbose(" - search for: "+searchFor); //$NON-NLS-1$ |
| Util.verbose(" - scope: "+scope); //$NON-NLS-1$ |
| } |
| if (validatedTypeMatchRule == -1) return; // invalid match rule => return no results |
| |
| // Create pattern |
| IndexManager indexManager = JavaModelManager.getIndexManager(); |
| final char typeSuffix; |
| switch(searchFor){ |
| case IJavaSearchConstants.CLASS : |
| typeSuffix = IIndexConstants.CLASS_SUFFIX; |
| break; |
| case IJavaSearchConstants.CLASS_AND_INTERFACE : |
| typeSuffix = IIndexConstants.CLASS_AND_INTERFACE_SUFFIX; |
| break; |
| case IJavaSearchConstants.CLASS_AND_ENUM : |
| typeSuffix = IIndexConstants.CLASS_AND_ENUM_SUFFIX; |
| break; |
| case IJavaSearchConstants.INTERFACE : |
| typeSuffix = IIndexConstants.INTERFACE_SUFFIX; |
| break; |
| case IJavaSearchConstants.INTERFACE_AND_ANNOTATION : |
| typeSuffix = IIndexConstants.INTERFACE_AND_ANNOTATION_SUFFIX; |
| break; |
| case IJavaSearchConstants.ENUM : |
| typeSuffix = IIndexConstants.ENUM_SUFFIX; |
| break; |
| case IJavaSearchConstants.ANNOTATION_TYPE : |
| typeSuffix = IIndexConstants.ANNOTATION_TYPE_SUFFIX; |
| break; |
| default : |
| typeSuffix = IIndexConstants.TYPE_SUFFIX; |
| break; |
| } |
| final TypeDeclarationPattern pattern = packageMatchRule == SearchPattern.R_EXACT_MATCH |
| ? new TypeDeclarationPattern( |
| packageName, |
| null, |
| typeName, |
| typeSuffix, |
| validatedTypeMatchRule) |
| : new QualifiedTypeDeclarationPattern( |
| packageName, |
| packageMatchRule, |
| typeName, |
| typeSuffix, |
| validatedTypeMatchRule); |
| |
| // 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; |
| ICompilationUnit[] 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++) { |
| ICompilationUnit 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.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; // filter 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, documentPath, accessRestriction); |
| } |
| return true; |
| } |
| }; |
| |
| SubMonitor subMonitor = SubMonitor.convert(progressMonitor, Messages.engine_searching, 1000); |
| // add type names from indexes |
| indexManager.performConcurrentJob( |
| new PatternSearchJob( |
| pattern, |
| getDefaultSearchParticipant(), // Java search only |
| scope, |
| searchRequestor), |
| waitingPolicy, |
| subMonitor.split(Math.max(1000-copiesLength, 0))); |
| |
| // add type names from working copies |
| if (copies != null) { |
| for (int i = 0; i < copiesLength; i++) { |
| SubMonitor iterationMonitor = subMonitor.split(i); |
| final ICompilationUnit workingCopy = copies[i]; |
| if (scope instanceof HierarchyScope) { |
| if (!((HierarchyScope)scope).encloses(workingCopy, iterationMonitor)) continue; |
| } else { |
| 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.getAllTypes(); |
| for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) { |
| IType type = allTypes[j]; |
| IJavaElement 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; |
| if (type.isEnum()) { |
| kind = TypeDeclaration.ENUM_DECL; |
| } else if (type.isAnnotation()) { |
| kind = TypeDeclaration.ANNOTATION_TYPE_DECL; |
| } else if (type.isClass()) { |
| kind = TypeDeclaration.CLASS_DECL; |
| } else /*if (type.isInterface())*/ { |
| kind = TypeDeclaration.INTERFACE_DECL; |
| } |
| if (match(typeSuffix, packageName, packageMatchRule, typeName, validatedTypeMatchRule, kind, packageDeclaration, simpleName)) { |
| if (nameRequestor instanceof TypeNameMatchRequestorWrapper) { |
| ((TypeNameMatchRequestorWrapper)nameRequestor).requestor.acceptTypeNameMatch(new JavaSearchTypeNameMatch(type, type.getFlags())); |
| } else { |
| nameRequestor.acceptType(type.getFlags(), packageDeclaration, simpleName, enclosingTypeNames, path, null); |
| } |
| } |
| } |
| } else { |
| Parser basicParser = getParser(); |
| org.eclipse.jdt.internal.compiler.env.ICompilationUnit unit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) workingCopy; |
| CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.compilerOptions.maxProblemsPerUnit); |
| CompilationUnitDeclaration 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, CompilationUnitScope compilationUnitScope) { |
| if (match(typeSuffix, packageName, packageMatchRule, typeName, validatedTypeMatchRule, TypeDeclaration.kind(typeDeclaration.modifiers), packageDeclaration, typeDeclaration.name)) { |
| if (nameRequestor instanceof TypeNameMatchRequestorWrapper) { |
| IType type = workingCopy.getType(new String(typeName)); |
| ((TypeNameMatchRequestorWrapper)nameRequestor).requestor.acceptTypeNameMatch(new JavaSearchTypeNameMatch(type, typeDeclaration.modifiers)); |
| } else { |
| nameRequestor.acceptType(typeDeclaration.modifiers, packageDeclaration, typeDeclaration.name, CharOperation.NO_CHAR_CHAR, path, null); |
| } |
| } |
| return true; |
| } |
| public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope classScope) { |
| if (match(typeSuffix, packageName, packageMatchRule, typeName, validatedTypeMatchRule, TypeDeclaration.kind(memberTypeDeclaration.modifiers), packageDeclaration, memberTypeDeclaration.name)) { |
| // compute enclosing type names |
| TypeDeclaration enclosing = memberTypeDeclaration.enclosingType; |
| char[][] enclosingTypeNames = CharOperation.NO_CHAR_CHAR; |
| while (enclosing != null) { |
| enclosingTypeNames = CharOperation.arrayConcat(new char[][] {enclosing.name}, enclosingTypeNames); |
| if ((enclosing.bits & ASTNode.IsMemberType) != 0) { |
| enclosing = enclosing.enclosingType; |
| } else { |
| enclosing = null; |
| } |
| } |
| // report |
| if (nameRequestor instanceof TypeNameMatchRequestorWrapper) { |
| IType type = workingCopy.getType(new String(enclosingTypeNames[0])); |
| for (int j=1, l=enclosingTypeNames.length; j<l; j++) { |
| type = type.getType(new String(enclosingTypeNames[j])); |
| } |
| ((TypeNameMatchRequestorWrapper)nameRequestor).requestor.acceptTypeNameMatch(new JavaSearchTypeNameMatch(type, 0)); |
| } else { |
| nameRequestor.acceptType(memberTypeDeclaration.modifiers, packageDeclaration, memberTypeDeclaration.name, enclosingTypeNames, path, null); |
| } |
| } |
| return true; |
| } |
| } |
| parsedUnit.traverse(new AllTypeDeclarationsVisitor(), parsedUnit.scope); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * 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, |
| IJavaSearchScope scope, |
| final IRestrictedAccessTypeRequestor nameRequestor, |
| int waitingPolicy, |
| IProgressMonitor progressMonitor) throws JavaModelException { |
| |
| // Debug |
| if (VERBOSE) { |
| Util.verbose("BasicSearchEngine.searchAllTypeNames(char[][], char[][], int, int, IJavaSearchScope, IRestrictedAccessTypeRequestor, int, IProgressMonitor)"); //$NON-NLS-1$ |
| Util.verbose(" - package name: "+(qualifications==null?"null":new String(CharOperation.concatWith(qualifications, ',')))); //$NON-NLS-1$ //$NON-NLS-2$ |
| Util.verbose(" - type name: "+(typeNames==null?"null":new String(CharOperation.concatWith(typeNames, ',')))); //$NON-NLS-1$ //$NON-NLS-2$ |
| Util.verbose(" - match rule: "+getMatchRuleString(matchRule)); //$NON-NLS-1$ |
| Util.verbose(" - search for: "+searchFor); //$NON-NLS-1$ |
| Util.verbose(" - scope: "+scope); //$NON-NLS-1$ |
| } |
| IndexManager indexManager = JavaModelManager.getIndexManager(); |
| |
| // Create pattern |
| final char typeSuffix; |
| switch(searchFor){ |
| case IJavaSearchConstants.CLASS : |
| typeSuffix = IIndexConstants.CLASS_SUFFIX; |
| break; |
| case IJavaSearchConstants.CLASS_AND_INTERFACE : |
| typeSuffix = IIndexConstants.CLASS_AND_INTERFACE_SUFFIX; |
| break; |
| case IJavaSearchConstants.CLASS_AND_ENUM : |
| typeSuffix = IIndexConstants.CLASS_AND_ENUM_SUFFIX; |
| break; |
| case IJavaSearchConstants.INTERFACE : |
| typeSuffix = IIndexConstants.INTERFACE_SUFFIX; |
| break; |
| case IJavaSearchConstants.INTERFACE_AND_ANNOTATION : |
| typeSuffix = IIndexConstants.INTERFACE_AND_ANNOTATION_SUFFIX; |
| break; |
| case IJavaSearchConstants.ENUM : |
| typeSuffix = IIndexConstants.ENUM_SUFFIX; |
| break; |
| case IJavaSearchConstants.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; |
| ICompilationUnit[] 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++) { |
| ICompilationUnit 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 |
| QualifiedTypeDeclarationPattern record = (QualifiedTypeDeclarationPattern) indexRecord; |
| 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; // filter 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 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, '.', '/'); |
| |
| // Access rules work on package level and should not discriminate on enclosing types. |
| boolean isNestedType = record.enclosingTypeNames != null && record.enclosingTypeNames.length > 0; |
| path[qualificationLength-1] = isNestedType ? '$' : '/'; |
| 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; |
| } |
| }; |
| |
| SubMonitor subMonitor = SubMonitor.convert(progressMonitor, Messages.engine_searching, 100); |
| // add type names from indexes |
| indexManager.performConcurrentJob( |
| new PatternSearchJob( |
| pattern, |
| getDefaultSearchParticipant(), // Java search only |
| scope, |
| searchRequestor), |
| waitingPolicy, |
| subMonitor.split(100)); |
| |
| // add type names from working copies |
| if (copies != null) { |
| for (int i = 0, length = copies.length; i < length; i++) { |
| ICompilationUnit 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]; |
| IJavaElement 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.jdt.internal.compiler.env.ICompilationUnit unit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) workingCopy; |
| CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.compilerOptions.maxProblemsPerUnit); |
| CompilationUnitDeclaration 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, CompilationUnitScope 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 enclosing 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); |
| } |
| } |
| } |
| } |
| } |
| |
| public void searchDeclarations(IJavaElement enclosingElement, SearchRequestor requestor, SearchPattern pattern, IProgressMonitor monitor) throws JavaModelException { |
| if (VERBOSE) { |
| Util.verbose(" - java element: "+enclosingElement); //$NON-NLS-1$ |
| } |
| IJavaSearchScope scope = createJavaSearchScope(new IJavaElement[] {enclosingElement}); |
| IResource resource = ((JavaElement) enclosingElement).resource(); |
| if (enclosingElement instanceof IMember) { |
| IMember member = (IMember) enclosingElement; |
| ICompilationUnit cu = member.getCompilationUnit(); |
| if (cu != null) { |
| resource = cu.getResource(); |
| } else if (member.isBinary()) { |
| // 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 " + resource.getFullPath()); //$NON-NLS-1$//$NON-NLS-2$ |
| } |
| SearchParticipant participant = getDefaultSearchParticipant(); |
| SearchDocument[] documents = MatchLocator.addWorkingCopies( |
| pattern, |
| new SearchDocument[] {new JavaSearchDocument(enclosingElement.getPath().toString(), participant)}, |
| 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 JavaModelException) |
| throw (JavaModelException) e; |
| throw new JavaModelException(e); |
| } |
| } |
| |
| /** |
| * Searches for all declarations of the fields accessed in the given element. |
| * The element can be a compilation unit or a source type/method/field. |
| * Reports the field declarations using the given requestor. |
| * |
| * @see SearchEngine#searchDeclarationsOfAccessedFields(IJavaElement, SearchRequestor, IProgressMonitor) |
| * for detailed comment |
| */ |
| public void searchDeclarationsOfAccessedFields(IJavaElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaModelException { |
| if (VERBOSE) { |
| Util.verbose("BasicSearchEngine.searchDeclarationsOfAccessedFields(IJavaElement, SearchRequestor, SearchPattern, IProgressMonitor)"); //$NON-NLS-1$ |
| } |
| // Do not accept other kind of element type than those specified in the spec |
| switch (enclosingElement.getElementType()) { |
| case IJavaElement.FIELD: |
| case IJavaElement.METHOD: |
| case IJavaElement.TYPE: |
| case IJavaElement.COMPILATION_UNIT: |
| //{ObjectTeams: callouts are valid, too: |
| case IOTJavaElement.CALLOUT_MAPPING: |
| case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING: |
| // SH} |
| // valid element type |
| break; |
| default: |
| throw new IllegalArgumentException(); |
| } |
| 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 or a source type/method/field. |
| * Reports the type declarations using the given requestor. |
| * |
| * @see SearchEngine#searchDeclarationsOfReferencedTypes(IJavaElement, SearchRequestor, IProgressMonitor) |
| * for detailed comment |
| */ |
| public void searchDeclarationsOfReferencedTypes(IJavaElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaModelException { |
| if (VERBOSE) { |
| Util.verbose("BasicSearchEngine.searchDeclarationsOfReferencedTypes(IJavaElement, SearchRequestor, SearchPattern, IProgressMonitor)"); //$NON-NLS-1$ |
| } |
| // Do not accept other kind of element type than those specified in the spec |
| switch (enclosingElement.getElementType()) { |
| case IJavaElement.FIELD: |
| case IJavaElement.METHOD: |
| case IJavaElement.TYPE: |
| case IJavaElement.COMPILATION_UNIT: |
| //{ObjectTeams: callouts are valid, too: |
| case IOTJavaElement.CALLOUT_MAPPING: |
| case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING: |
| // SH} |
| // valid element type |
| break; |
| default: |
| throw new IllegalArgumentException(); |
| } |
| 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 or a source type/method/field. |
| * Reports the method declarations using the given requestor. |
| * |
| * @see SearchEngine#searchDeclarationsOfSentMessages(IJavaElement, SearchRequestor, IProgressMonitor) |
| * for detailed comment |
| */ |
| public void searchDeclarationsOfSentMessages(IJavaElement enclosingElement, SearchRequestor requestor, IProgressMonitor monitor) throws JavaModelException { |
| if (VERBOSE) { |
| Util.verbose("BasicSearchEngine.searchDeclarationsOfSentMessages(IJavaElement, SearchRequestor, SearchPattern, IProgressMonitor)"); //$NON-NLS-1$ |
| } |
| // Do not accept other kind of element type than those specified in the spec |
| switch (enclosingElement.getElementType()) { |
| case IJavaElement.FIELD: |
| case IJavaElement.METHOD: |
| case IJavaElement.TYPE: |
| case IJavaElement.COMPILATION_UNIT: |
| //{ObjectTeams: callouts are valid, too: |
| case IOTJavaElement.CALLOUT_MAPPING: |
| case IOTJavaElement.CALLOUT_TO_FIELD_MAPPING: |
| // SH} |
| // valid element type |
| break; |
| default: |
| throw new IllegalArgumentException(); |
| } |
| SearchPattern pattern = new DeclarationOfReferencedMethodsPattern(enclosingElement); |
| searchDeclarations(enclosingElement, requestor, pattern, monitor); |
| } |
| } |