diff options
Diffstat (limited to 'bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/BasicSearchEngine.java')
-rw-r--r-- | bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/BasicSearchEngine.java | 1316 |
1 files changed, 820 insertions, 496 deletions
diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/BasicSearchEngine.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/BasicSearchEngine.java index baa3bc4b..b6baa27f 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/BasicSearchEngine.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/core/search/BasicSearchEngine.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2013 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 @@ -10,8 +10,11 @@ *******************************************************************************/ package org.eclipse.wst.jsdt.internal.core.search; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; @@ -29,6 +32,7 @@ import org.eclipse.wst.jsdt.core.IPackageFragmentRoot; import org.eclipse.wst.jsdt.core.IType; import org.eclipse.wst.jsdt.core.JavaScriptCore; import org.eclipse.wst.jsdt.core.JavaScriptModelException; +import org.eclipse.wst.jsdt.core.Signature; import org.eclipse.wst.jsdt.core.WorkingCopyOwner; import org.eclipse.wst.jsdt.core.compiler.CharOperation; import org.eclipse.wst.jsdt.core.infer.InferredAttribute; @@ -44,7 +48,6 @@ import org.eclipse.wst.jsdt.core.search.TypeNameMatch; import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor; import org.eclipse.wst.jsdt.internal.compiler.CompilationResult; import org.eclipse.wst.jsdt.internal.compiler.DefaultErrorHandlingPolicies; -import org.eclipse.wst.jsdt.internal.compiler.ast.ASTNode; import org.eclipse.wst.jsdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.wst.jsdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration; @@ -55,7 +58,6 @@ import org.eclipse.wst.jsdt.internal.compiler.env.AccessRuleSet; import org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions; import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding; import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope; -import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope; import org.eclipse.wst.jsdt.internal.compiler.lookup.CompilationUnitScope; import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope; import org.eclipse.wst.jsdt.internal.compiler.parser.Parser; @@ -65,22 +67,25 @@ import org.eclipse.wst.jsdt.internal.core.CompilationUnit; import org.eclipse.wst.jsdt.internal.core.DefaultWorkingCopyOwner; import org.eclipse.wst.jsdt.internal.core.JavaModelManager; import org.eclipse.wst.jsdt.internal.core.JavaProject; +import org.eclipse.wst.jsdt.internal.core.Logger; import org.eclipse.wst.jsdt.internal.core.search.indexing.IIndexConstants; import org.eclipse.wst.jsdt.internal.core.search.indexing.IndexManager; -import org.eclipse.wst.jsdt.internal.core.search.matching.ConstructorDeclarationPattern; +import org.eclipse.wst.jsdt.internal.core.search.matching.ConstructorPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.DeclarationOfAccessedFieldsPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.DeclarationOfReferencedMethodsPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.DeclarationOfReferencedTypesPattern; +import org.eclipse.wst.jsdt.internal.core.search.matching.FieldPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.JavaSearchPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.LocalVariablePattern; import org.eclipse.wst.jsdt.internal.core.search.matching.MatchLocator; import org.eclipse.wst.jsdt.internal.core.search.matching.MethodPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.MultiTypeDeclarationPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.OrPattern; -import org.eclipse.wst.jsdt.internal.core.search.matching.QualifiedTypeDeclarationPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.SecondaryTypeDeclarationPattern; import org.eclipse.wst.jsdt.internal.core.search.matching.TypeDeclarationPattern; +import org.eclipse.wst.jsdt.internal.core.search.processing.IJob; import org.eclipse.wst.jsdt.internal.core.util.Messages; +import org.eclipse.wst.jsdt.internal.core.util.QualificationHelpers; import org.eclipse.wst.jsdt.internal.core.util.Util; /** @@ -89,6 +94,7 @@ import org.eclipse.wst.jsdt.internal.core.util.Util; * Note that search basic engine does not implement depreciated functionalities... */ public class BasicSearchEngine { + private static final String GLOBAL_TYPE_SYMBOL = new String(IIndexConstants.GLOBAL_SYMBOL); /* * A default parser to parse non-reconciled working copies @@ -101,6 +107,11 @@ public class BasicSearchEngine { * compilation units. */ private IJavaScriptUnit[] workingCopies; + + /** + * <p>Set of all of the working copies paths</p> + */ + private HashSet fWorkingCopiesPaths; /* * A working copy owner whose working copies will take precedent over @@ -366,9 +377,9 @@ public class BasicSearchEngine { return this.parser; } - /* - * Returns the list of working copies used by this search engine. - * Returns null if none. + /** + * @return list of working copies used by this search engine, + * or <code>null</code> if none. */ private IJavaScriptUnit[] getWorkingCopies() { IJavaScriptUnit[] copies; @@ -425,6 +436,22 @@ public class BasicSearchEngine { } return result; } + + /** + * @return {@link HashSet} of all of the working copy paths + */ + private HashSet getWorkingCopiesPaths() { + if(this.fWorkingCopiesPaths == null) { + this.fWorkingCopiesPaths = new HashSet(); + + IJavaScriptUnit[] workingCopies = this.getWorkingCopies(); + for(int i = 0; workingCopies != null && i < workingCopies.length; ++i) { + this.fWorkingCopiesPaths.add(workingCopies[i].getPath().toString()); + } + } + + return this.fWorkingCopiesPaths; + } /* * Returns the list of working copies used to do the search on the given Java element. @@ -512,8 +539,7 @@ public class BasicSearchEngine { } findMatches(pattern, participants, scope, requestor, monitor); } - - + public void searchAllBindingNames( final char[] packageName, final char[] bindingName, @@ -546,9 +572,7 @@ public class BasicSearchEngine { suffix = IIndexConstants.CLASS_SUFFIX; searchPattern = new TypeDeclarationPattern( packageName, - null, // do find member types bindingName, - suffix, matchRule); break; @@ -557,7 +581,8 @@ public class BasicSearchEngine { case Binding.LOCAL : case Binding.FIELD : { - searchPattern = new LocalVariablePattern(true, false, false,bindingName, matchRule); + //searchPattern = new LocalVariablePattern(true, false, false,bindingName, matchRule); + searchPattern = new FieldPattern(true, false, false, true, bindingName, null, IIndexConstants.GLOBAL_SYMBOL, null, null, matchRule, null); } break; case Binding.METHOD: @@ -566,7 +591,7 @@ public class BasicSearchEngine { true,false,true, bindingName, null,null,null,null, - null,null,null, + null,IIndexConstants.GLOBAL_SYMBOL, matchRule); } @@ -578,27 +603,24 @@ public class BasicSearchEngine { searchPattern = new MethodPattern( true,false,true, bindingName, - null,null,null,null, - null,null,null, matchRule); } if ((bindingType & (Binding.VARIABLE |Binding.LOCAL |Binding.FIELD )) >0) { - LocalVariablePattern localVariablePattern = new LocalVariablePattern(true, false, false,bindingName, matchRule); + //LocalVariablePattern localVariablePattern = new LocalVariablePattern(true, false, false,bindingName, matchRule); + FieldPattern fieldPattern = new FieldPattern(true, false, false, true, bindingName, null, IIndexConstants.GLOBAL_SYMBOL, null, null, matchRule, null); if (searchPattern==null) - searchPattern=localVariablePattern; + searchPattern=fieldPattern; else - searchPattern=new OrPattern(searchPattern,localVariablePattern); + searchPattern=new OrPattern(searchPattern,fieldPattern); } if ((bindingType & Binding.TYPE) >0) { suffix = IIndexConstants.CLASS_SUFFIX; TypeDeclarationPattern typeDeclarationPattern = new TypeDeclarationPattern( packageName, - null, // do find member types bindingName, - suffix, matchRule); if (searchPattern==null) searchPattern=typeDeclarationPattern; @@ -610,24 +632,7 @@ public class BasicSearchEngine { final SearchPattern pattern =searchPattern; final char typeSuffix=suffix; - // 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; - IJavaScriptUnit[] 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++) { - IJavaScriptUnit workingCopy = copies[i]; - workingCopyPaths.add(workingCopy.getPath().toString()); - } - } - } - final String singleWkcpPath = workingCopyPath; - - // Index requestor + // Index requester IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){ public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRuleSet access) { // Filter unexpected types @@ -691,6 +696,8 @@ public class BasicSearchEngine { progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100)); // add type names from working copies + IJavaScriptUnit[] copies = getWorkingCopies(); + final int copiesLength = copies == null ? 0 : copies.length; if (copies != null && doParse) { for (int i = 0; i < copiesLength; i++) { IJavaScriptUnit workingCopy = copies[i]; @@ -705,14 +712,6 @@ public class BasicSearchEngine { IType[] allTypes = workingCopy.getAllTypes(); for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) { IType type = allTypes[j]; - IJavaScriptElement 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 = TypeDeclaration.CLASS_DECL; @@ -726,16 +725,7 @@ public class BasicSearchEngine { IFunction[] allMethods = workingCopy.getFunctions(); for (int j = 0, allMethodsLength = allMethods.length; j < allMethodsLength; j++) { IFunction method = allMethods[j]; - IJavaScriptElement parent = method.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 = method.getElementName().toCharArray(); -// int kind; if (match(typeSuffix, packageName, bindingName, matchRule, 0, packageDeclaration, simpleName)) { nameRequestor.acceptBinding(bindingType,method.getFlags(), packageDeclaration, simpleName, path, null); } @@ -749,16 +739,7 @@ public class BasicSearchEngine { IField[] allFields = workingCopy.getFields (); for (int j = 0, allFieldsLength = allFields.length; j < allFieldsLength; j++) { IField field = allFields[j]; - IJavaScriptElement parent = field.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 = field.getElementName().toCharArray(); - int kind; if (match(typeSuffix, packageName, bindingName, matchRule, 0, packageDeclaration, simpleName)) { nameRequestor.acceptBinding(bindingType,field.getFlags(), packageDeclaration, simpleName, path, null); } @@ -793,30 +774,13 @@ public class BasicSearchEngine { return true; } public boolean visit(MethodDeclaration methodDeclaration, Scope scope) { - if (bindingType==Binding.METHOD && methodDeclaration.selector!=null && - match(typeSuffix, packageName, bindingName, matchRule,0, packageDeclaration, methodDeclaration.selector)) { - nameRequestor.acceptBinding(bindingType,methodDeclaration.modifiers, packageDeclaration, methodDeclaration.selector, path, null); + char[] methName = methodDeclaration.getName(); + if (bindingType==Binding.METHOD && methName!=null && + match(typeSuffix, packageName, bindingName, matchRule,0, packageDeclaration, methName)) { + nameRequestor.acceptBinding(bindingType,methodDeclaration.modifiers, packageDeclaration, methName, path, null); } return true; } -// public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope classScope) { -// if (match(typeSuffix, packageName, bindingName, matchRule, TypeDeclaration.kind(memberTypeDeclaration.modifiers), packageDeclaration, memberTypeDeclaration.name)) { -// // compute encloising 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 -// nameRequestor.acceptType(memberTypeDeclaration.modifiers, packageDeclaration, memberTypeDeclaration.name, enclosingTypeNames, path, null); -// } -// return true; -// } public boolean visit(InferredType inferredType, BlockScope scope) { if (bindingType==Binding.TYPE && match(typeSuffix, packageName, bindingName, matchRule, TypeDeclaration.kind(0), packageDeclaration, inferredType.getName())) { @@ -885,59 +849,33 @@ public class BasicSearchEngine { IndexManager indexManager = JavaModelManager.getJavaModelManager().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; - IJavaScriptUnit[] 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++) { - IJavaScriptUnit workingCopy = copies[i]; - workingCopyPaths.add(workingCopy.getPath().toString()); - } - } - } - final String singleWkcpPath = workingCopyPath; + // Get working copy path(s). Store in a single string in case of only one to optimize comparison in requester + final HashSet workingCopyPaths = this.getWorkingCopiesPaths(); - // Index requestor + // Index requester 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; + + if (workingCopyPaths.contains(documentPath)) { + return true; // filter out working copies } // 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 pkgLength = (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[pkgLength+nameLength]; int pos = 0; if (pkgLength > 0) { - System.arraycopy(record.pkg, 0, path, pos, pkgLength-1); + System.arraycopy(record.qualification, 0, path, pos, pkgLength-1); CharOperation.replace(path, '.', '/'); path[pkgLength-1] = '/'; pos += pkgLength; @@ -951,7 +889,7 @@ public class BasicSearchEngine { accessRestriction = access.getViolatedRestriction(path); } } - nameRequestor.acceptType(record.modifiers, record.pkg, record.simpleName, record.enclosingTypeNames, documentPath, accessRestriction); + nameRequestor.acceptType(record.modifiers, record.qualification, record.simpleName, record.superTypes, record.enclosingTypeNames, documentPath, accessRestriction); return true; } }; @@ -979,21 +917,51 @@ public class BasicSearchEngine { } } } + + /** + * <p>Search for types using the given prefix. The prefix could be part of the + * qualification or simple name for a type, or it could be a camel case + * statement for a simple name of a type.</p> + * + * @param prefix + * @param matchRule + * @param scope + * @param nameRequestor + * @param waitingPolicy + * @param progressMonitor + * @throws JavaScriptModelException + */ + public void searchAllTypeNames( + final char[] prefix, + final int matchRule, + IJavaScriptSearchScope scope, + final IRestrictedAccessTypeRequestor nameRequestor, + int waitingPolicy, + IProgressMonitor progressMonitor) throws JavaScriptModelException { + + // Create pattern + TypeDeclarationPattern pattern = new TypeDeclarationPattern(prefix, matchRule); + + this.searchAllTypeNames(pattern, scope, nameRequestor, waitingPolicy, progressMonitor); + } /** - * Searches for all top-level types and member types in the given scope. - * The search can be selecting specific types (given a package or a type name - * prefix and match modes). - * - * @see org.eclipse.wst.jsdt.core.search.SearchEngine#searchAllTypeNames(char[], int, char[], int, int, IJavaScriptSearchScope, org.eclipse.wst.jsdt.core.search.TypeNameRequestor, int, IProgressMonitor) - * for detailed comment + * <p>Search for a type with a specific qualification and simple name</p> + * + * @param qualification + * @param qualificationMatchRule + * @param simpleTypeName + * @param matchRule + * @param scope + * @param nameRequestor + * @param waitingPolicy + * @param progressMonitor + * @throws JavaScriptModelException */ public void searchAllTypeNames( - final char[] packageName, - final int packageMatchRule, - final char[] typeName, - final int typeMatchRule, - int searchFor, + final char[] qualification, + final char[] simpleTypeName, + final int matchRule, IJavaScriptSearchScope scope, final IRestrictedAccessTypeRequestor nameRequestor, int waitingPolicy, @@ -1001,92 +969,101 @@ public class BasicSearchEngine { if (VERBOSE) { Util.verbose("BasicSearchEngine.searchAllTypeNames(char[], char[], int, int, IJavaScriptSearchScope, IRestrictedAccessTypeRequestor, int, IProgressMonitor)"); //$NON-NLS-1$ - Util.verbose(" - package name: "+(packageName==null?"null":new String(packageName))); //$NON-NLS-1$ //$NON-NLS-2$ - Util.verbose(" - 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(" - match rule: "+getMatchRuleString(typeMatchRule)); //$NON-NLS-1$ - Util.verbose(" - search for: "+searchFor); //$NON-NLS-1$ + Util.verbose(" - package name: "+(qualification==null?"null":new String(qualification))); //$NON-NLS-1$ //$NON-NLS-2$ + Util.verbose(" - type name: "+(simpleTypeName==null?"null":new String(simpleTypeName))); //$NON-NLS-1$ //$NON-NLS-2$ + Util.verbose(" - match rule: "+getMatchRuleString(matchRule)); //$NON-NLS-1$ Util.verbose(" - scope: "+scope); //$NON-NLS-1$ } // Create pattern - IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager(); - final char typeSuffix; - switch(searchFor){ - case IJavaScriptSearchConstants.CLASS : - typeSuffix = IIndexConstants.CLASS_SUFFIX; - break; - default : - typeSuffix = IIndexConstants.TYPE_SUFFIX; - break; + TypeDeclarationPattern pattern = new TypeDeclarationPattern( + qualification, + simpleTypeName, + matchRule); + + this.searchAllTypeNames(pattern, scope, nameRequestor, waitingPolicy, progressMonitor); + } + + /** + * <p>Search for multiple types with specific qualifications and simple type names.</p> + * + * @param qualifications + * @param simpleTypeNames + * @param matchRule + * @param scope + * @param nameRequestor + * @param waitingPolicy + * @param progressMonitor + * @throws JavaScriptModelException + */ + public void searchAllTypeNames( + final char[][] qualifications, + final char[][] simpleTypeNames, + final int matchRule, + IJavaScriptSearchScope scope, + final IRestrictedAccessTypeRequestor nameRequestor, + int waitingPolicy, + IProgressMonitor progressMonitor) throws JavaScriptModelException { + + if (VERBOSE) { + Util.verbose("BasicSearchEngine.searchAllTypeNames(char[][], char[][], int, int, IJavaScriptSearchScope, 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: "+(simpleTypeNames==null?"null":new String(CharOperation.concatWith(simpleTypeNames, ',')))); //$NON-NLS-1$ //$NON-NLS-2$ + Util.verbose(" - match rule: "+matchRule); //$NON-NLS-1$ + Util.verbose(" - scope: "+scope); //$NON-NLS-1$ } - final TypeDeclarationPattern pattern = packageMatchRule == SearchPattern.R_EXACT_MATCH - ? new TypeDeclarationPattern( - packageName, - null, - typeName, - typeSuffix, - typeMatchRule) - : new QualifiedTypeDeclarationPattern( - packageName, - packageMatchRule, - typeName, - typeSuffix, - typeMatchRule); + + MultiTypeDeclarationPattern pattern = new MultiTypeDeclarationPattern( + qualifications, simpleTypeNames, matchRule); + this.searchAllTypeNames(pattern, scope, nameRequestor, waitingPolicy, progressMonitor); + } + + /** + * <p>Used to search for types using a given pattern.</p> + * + * @param pattern + * @param scope + * @param nameRequestor + * @param waitingPolicy + * @param progressMonitor + * @throws JavaScriptModelException + */ + private void searchAllTypeNames( + final TypeDeclarationPattern pattern, + IJavaScriptSearchScope scope, + final IRestrictedAccessTypeRequestor nameRequestor, + int waitingPolicy, + IProgressMonitor progressMonitor) throws JavaScriptModelException { // 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; - IJavaScriptUnit[] 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++) { - IJavaScriptUnit workingCopy = copies[i]; - workingCopyPaths.add(workingCopy.getPath().toString()); - } - } - } - final String singleWkcpPath = workingCopyPath; + final HashSet workingCopyPaths = this.getWorkingCopiesPaths(); // Index requestor IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){ public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRuleSet access) { // Filter unexpected types - TypeDeclarationPattern record = (TypeDeclarationPattern)indexRecord; + 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; // fliter out *the* working copy - } - break; - default: - if (workingCopyPaths.contains(documentPath)) { - return true; // filter out working copies - } - break; + + if (workingCopyPaths.contains(documentPath)) { + return true; // filter out working copies } // 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 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 (pkgLength > 0) { - System.arraycopy(record.pkg, 0, path, pos, pkgLength-1); + if (qualificationLength > 0) { + System.arraycopy(record.qualification, 0, path, pos, qualificationLength - 1); CharOperation.replace(path, '.', '/'); - path[pkgLength-1] = '/'; - pos += pkgLength; + path[qualificationLength-1] = '/'; + pos += qualificationLength; } if (nameLength > 0) { System.arraycopy(record.simpleName, 0, path, pos, nameLength); @@ -1097,9 +1074,7 @@ public class BasicSearchEngine { accessRestriction = access.getViolatedRestriction(path); } } - if (match(record.typeSuffix, record.modifiers)) { - nameRequestor.acceptType(record.modifiers, record.pkg, record.simpleName, record.enclosingTypeNames, documentPath, accessRestriction); - } + nameRequestor.acceptType(record.modifiers, record.qualification, record.simpleName, record.superTypes, record.enclosingTypeNames, documentPath, accessRestriction); return true; } }; @@ -1109,6 +1084,7 @@ public class BasicSearchEngine { progressMonitor.beginTask(Messages.engine_searching, 100); } // add type names from indexes + IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager(); indexManager.performConcurrentJob( new PatternSearchJob( pattern, @@ -1119,97 +1095,47 @@ public class BasicSearchEngine { progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100)); // add type names from working copies + IJavaScriptUnit[] copies = this.getWorkingCopies(); if (copies != null) { - for (int i = 0; i < copiesLength; i++) { + final int matchRule = pattern.getMatchRule(); + for (int i = 0; i < copies.length; i++) { final IJavaScriptUnit workingCopy = copies[i]; if (!scope.encloses(workingCopy)) continue; final String path = workingCopy.getPath().toString(); - if (workingCopy.isConsistent()) { - char[] packageDeclaration = CharOperation.NO_CHAR; - IType[] allTypes = workingCopy.getAllTypes(); - for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) { - IType type = allTypes[j]; - IJavaScriptElement 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 = TypeDeclaration.CLASS_DECL; - - if (match(typeSuffix, packageName, typeName, typeMatchRule, 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); - } - } + + //make the working copy consistent if it is not + if(!workingCopy.isConsistent()) { + workingCopy.makeConsistent(progressMonitor); + } + + //search all types in the working copy + IType[] allTypes = workingCopy.getAllTypes(); + for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) { + IType type = allTypes[j]; + + //get type name + char[] wcTypeQualification = null; + char[] wcTypeSimpleName = null; + char[] wcTypeFullName = type.getTypeQualifiedName().toCharArray(); + if(type.getTypeQualifiedName() != null) { + char[][] wcSeperatedDeclaringType = QualificationHelpers.seperateFullyQualifedName(wcTypeFullName); + wcTypeQualification = wcSeperatedDeclaringType[QualificationHelpers.QULIFIERS_INDEX]; + wcTypeSimpleName = wcSeperatedDeclaringType[QualificationHelpers.SIMPLE_NAMES_INDEX]; } - } else { - Parser basicParser = getParser(); - org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit unit = (org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit) workingCopy; - CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.compilerOptions.maxProblemsPerUnit); - CompilationUnitDeclaration parsedUnit = basicParser.dietParse(unit, compilationUnitResult); - if (parsedUnit != null) { - basicParser.inferTypes(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 + + if(wcTypeSimpleName != null) { + TypeDeclarationPattern wcPattern = new TypeDeclarationPattern(wcTypeQualification, wcTypeSimpleName, matchRule); + if (pattern.matchesDecodedKey(wcPattern)) { + char[][] superTypes = CharOperation.NO_CHAR_CHAR; + try { + String superType = type.getSuperclassName(); + superTypes = new char[][]{superType.toCharArray()}; } - public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope compilationUnitScope) { - if (match(typeSuffix, packageName, typeName, typeMatchRule, 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, typeName, typeMatchRule, TypeDeclaration.kind(memberTypeDeclaration.modifiers), packageDeclaration, memberTypeDeclaration.name)) { - // compute encloising 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; - } - public boolean visit(InferredType inferredType, BlockScope scope) { - if (match(typeSuffix, packageName, typeName, typeMatchRule, TypeDeclaration.kind(0), packageDeclaration, inferredType.getName())) { - if (nameRequestor instanceof TypeNameMatchRequestorWrapper) { - IType type = workingCopy.getType(new String(typeName)); - ((TypeNameMatchRequestorWrapper)nameRequestor).requestor.acceptTypeNameMatch(new JavaSearchTypeNameMatch(type, 0)); - } else { - nameRequestor.acceptType(0, packageDeclaration, inferredType.getName(), CharOperation.NO_CHAR_CHAR, path, null); - } - } - return true; + catch (JavaScriptModelException e) { + // stay empty } + nameRequestor.acceptType(type.getFlags(), wcTypeQualification, wcTypeSimpleName, superTypes, null, path, null); } - parsedUnit.traverse(new AllTypeDeclarationsVisitor(), parsedUnit.scope); } } } @@ -1221,219 +1147,173 @@ public class BasicSearchEngine { } } - /** - * 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 org.eclipse.wst.jsdt.core.search.SearchEngine#searchAllTypeNames(char[][], char[][], IJavaScriptSearchScope, org.eclipse.wst.jsdt.core.search.TypeNameRequestor, int, IProgressMonitor) - * for detailed comment - */ - public void searchAllTypeNames( - final char[][] qualifications, - final char[][] typeNames, - final int matchRule, - int searchFor, - IJavaScriptSearchScope scope, - final IRestrictedAccessTypeRequestor nameRequestor, - int waitingPolicy, - IProgressMonitor progressMonitor) throws JavaScriptModelException { - - if (VERBOSE) { - Util.verbose("BasicSearchEngine.searchAllTypeNames(char[][], char[][], int, int, IJavaScriptSearchScope, 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: "+matchRule); //$NON-NLS-1$ - Util.verbose(" - search for: "+searchFor); //$NON-NLS-1$ - Util.verbose(" - scope: "+scope); //$NON-NLS-1$ - } - IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager(); - - final char typeSuffix; - switch(searchFor){ - case IJavaScriptSearchConstants.CLASS : - typeSuffix = IIndexConstants.CLASS_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; - IJavaScriptUnit[] 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++) { - IJavaScriptUnit workingCopy = copies[i]; - workingCopyPaths.add(workingCopy.getPath().toString()); - } - } - } - final String singleWkcpPath = workingCopyPath; - + public void searchAllModuleDeclarations(SearchPattern pattern, IJavaScriptSearchScope scope, final IModuleRequestor requestor, IProgressMonitor monitor) { + final HashSet workingCopiesPaths = this.getWorkingCopiesPaths(); + // Index requestor - IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){ + IndexQueryRequestor queryRequestor = 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; // 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 qualificationLength = (record.qualification == null || record.qualification.length == 0) ? 0 : record.qualification.length + 1; - int nameLength = record.simpleName == null ? 0 : record.simpleName.length; - char[] path = new char[qualificationLength + nameLength]; - int pos = 0; - if (qualificationLength > 0) { - System.arraycopy(record.qualification, 0, path, pos, qualificationLength - 1); - CharOperation.replace(path, '.', '/'); - path[qualificationLength-1] = '/'; - pos += qualificationLength; + if(!workingCopiesPaths.contains(documentPath)) { + if (indexRecord instanceof MethodPattern) { + MethodPattern record = (MethodPattern) indexRecord; + requestor.acceptFunction(record.selector, + record.getDeclaringQualification(), + record.getDeclaringSimpleName(), + documentPath); } - if (nameLength > 0) { - System.arraycopy(record.simpleName, 0, path, pos, nameLength); - pos += nameLength; + else if (indexRecord instanceof FieldPattern) { + FieldPattern record = (FieldPattern) indexRecord; + requestor.acceptField(record.name, + record.getDeclaringQualification(), + record.getDeclaringSimpleName(), + documentPath); } - // Update access restriction if path is not empty - if (pos > 0) { - accessRestriction = access.getViolatedRestriction(path); + else if (indexRecord instanceof TypeDeclarationPattern) { + TypeDeclarationPattern record = (TypeDeclarationPattern) indexRecord; + requestor.acceptType(record.qualification, + record.simpleName, + documentPath); } } - nameRequestor.acceptType(record.modifiers, record.pkg, record.simpleName, record.enclosingTypeNames, documentPath, accessRestriction); return true; } }; + // Find matches from index + IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager(); try { - if (progressMonitor != null) { - progressMonitor.beginTask(Messages.engine_searching, 100); + if (monitor != null) { + monitor.beginTask(Messages.engine_searching, 1000); } - // add type names from indexes - indexManager.performConcurrentJob( - new PatternSearchJob( - pattern, - getDefaultSearchParticipant(), // Java search only - scope, - searchRequestor), - waitingPolicy, - progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100)); - // add type names from working copies - if (copies != null) { - for (int i = 0, length = copies.length; i < length; i++) { - IJavaScriptUnit workingCopy = copies[i]; - final String path = workingCopy.getPath().toString(); - if (workingCopy.isConsistent()) { - char[] packageDeclaration = CharOperation.NO_CHAR; - IType[] allTypes = workingCopy.getAllTypes(); - for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) { - IType type = allTypes[j]; - IJavaScriptElement 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; + indexManager.performConcurrentJob(new PatternSearchJob( + pattern, + getDefaultSearchParticipant(), // JavaScript search only + scope, + queryRequestor), + IJavaScriptSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, + monitor == null ? null : new SubProgressMonitor(monitor, 1000)); + + SearchPattern typePattern = null; + SearchPattern fieldPattern = null; + SearchPattern methodPattern = null; + + if (pattern instanceof OrPattern) { + typePattern = ((OrPattern) pattern).findPatternKind(IIndexConstants.TYPE_DECL_PATTERN); + methodPattern = ((OrPattern) pattern).findPatternKind(IIndexConstants.METHOD_PATTERN); + fieldPattern = ((OrPattern) pattern).findPatternKind(IIndexConstants.FIELD_PATTERN); + } else if (pattern instanceof TypeDeclarationPattern) { + typePattern = pattern; + } else if (pattern instanceof FieldPattern) { + fieldPattern = pattern; + } else if (pattern instanceof MethodPattern) { + methodPattern = pattern; + } + + // find matches from working copies + IJavaScriptUnit[] workingCopies = this.getWorkingCopies(); + for (int w = 0; workingCopies != null && w < workingCopies.length; w++) { + final IJavaScriptUnit workingCopy = workingCopies[w]; + + //skip this working copy if not in the scope + if (!scope.encloses(workingCopy)) { + continue; + } + + try { + //make the working copy consistent if it is not + if (!workingCopy.isConsistent()) { + workingCopy.makeConsistent(monitor); + } + + //check each each type in the working copy for a match + IType[] types = workingCopy.getAllTypes(); + for (int t = 0; t < types.length; t++) { + IType type = types[t]; + if (typePattern != null && !type.isAnonymous()) { + //get type name + char[] wcTypeSimpleName = null; + char[] wcTypeQualification = null; + if (type.getTypeQualifiedName() != null) { + char[][] wcSeperatedDeclaringType = QualificationHelpers.seperateFullyQualifedName(type.getTypeQualifiedName().toCharArray()); + wcTypeQualification = wcSeperatedDeclaringType[QualificationHelpers.QULIFIERS_INDEX]; + wcTypeSimpleName = wcSeperatedDeclaringType[QualificationHelpers.SIMPLE_NAMES_INDEX]; } - if (pattern.matchesDecodedKey(new QualifiedTypeDeclarationPattern(qualification, simpleName, suffix, matchRule))) { - nameRequestor.acceptType(type.getFlags(), packageDeclaration, simpleName, enclosingTypeNames, path, null); + + if (wcTypeSimpleName != null) { + TypeDeclarationPattern wcPattern = new TypeDeclarationPattern(wcTypeQualification, wcTypeSimpleName, pattern.getMatchRule()); + if (typePattern.matchesDecodedKey(wcPattern)) { + requestor.acceptType(type); + } } } - } else { - Parser basicParser = getParser(); - org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit unit = (org.eclipse.wst.jsdt.internal.compiler.env.ICompilationUnit) workingCopy; - CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.compilerOptions.maxProblemsPerUnit); - CompilationUnitDeclaration parsedUnit = basicParser.dietParse(unit, compilationUnitResult); - if (parsedUnit != null) { - basicParser.inferTypes(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 + if (methodPattern != null) { + IFunction[] allFunctions = type.getFunctions(); + for (int f = 0; f < allFunctions.length; f++) { + IFunction function = allFunctions[f]; + //selector must not be null for it to be a match + char[] wcSelector = null; + if (function.getElementName() != null) { + wcSelector = function.getElementName().toCharArray(); } - 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; + char[] wcDeclaringTypeSimpleName = null; + char[] wcDeclaringTypeQualification = null; + if (function.getDeclaringType() != null && function.getDeclaringType().getTypeQualifiedName() != null) { + char[] wcDeclaringType = function.getDeclaringType().getTypeQualifiedName().toCharArray(); + char[][] wcSeperatedDeclaringType = QualificationHelpers.seperateFullyQualifedName(wcDeclaringType); + wcDeclaringTypeQualification = wcSeperatedDeclaringType[QualificationHelpers.QULIFIERS_INDEX]; + wcDeclaringTypeSimpleName = wcSeperatedDeclaringType[QualificationHelpers.SIMPLE_NAMES_INDEX]; } - public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope classScope) { - // compute encloising type names - char[] qualification = packageDeclaration; - TypeDeclaration enclosing = memberTypeDeclaration.enclosingType; - char[][] enclosingTypeNames = CharOperation.NO_CHAR_CHAR; - while (enclosing != null) { - qualification = CharOperation.concat(qualification, enclosing.name, '.'); - enclosingTypeNames = CharOperation.arrayConcat(new char[][] {enclosing.name}, enclosingTypeNames); - if ((enclosing.bits & ASTNode.IsMemberType) != 0) { - enclosing = enclosing.enclosingType; - } else { - enclosing = null; - } + if (wcSelector != null) { + MethodPattern wcPattern = new MethodPattern(true, false, false, wcSelector, null, null, null, null, + wcDeclaringTypeQualification, wcDeclaringTypeSimpleName, pattern.getMatchRule()); + //if working copy function matches the search pattern then accept the function + if (methodPattern.matchesDecodedKey(wcPattern)) { + requestor.acceptFunction(function); } - 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; } - public boolean visit(InferredType inferredType, BlockScope scope) { - SearchPattern decodedPattern = - new QualifiedTypeDeclarationPattern(packageDeclaration, inferredType.getName(), convertTypeKind(TypeDeclaration.kind(0)), matchRule); - if (pattern.matchesDecodedKey(decodedPattern)) { - nameRequestor.acceptType(0, packageDeclaration, inferredType.getName(), CharOperation.NO_CHAR_CHAR, path, null); + } + } + if (fieldPattern != null) { + IField[] allFields = type.getFields(); + for (int i = 0; i < allFields.length; i++) { + IField field = allFields[i]; + //selector must not be null for it to be a match + char[] wcName = null; + if (field.getElementName() != null) { + wcName = field.getElementName().toCharArray(); + } + char[] wcDeclaringTypeSimpleName = null; + char[] wcDeclaringTypeQualification = null; + if (field.getDeclaringType() != null && field.getDeclaringType().getTypeQualifiedName() != null) { + char[] wcDeclaringType = field.getDeclaringType().getTypeQualifiedName().toCharArray(); + char[][] wcSeperatedDeclaringType = QualificationHelpers.seperateFullyQualifedName(wcDeclaringType); + wcDeclaringTypeQualification = wcSeperatedDeclaringType[QualificationHelpers.QULIFIERS_INDEX]; + wcDeclaringTypeSimpleName = wcSeperatedDeclaringType[QualificationHelpers.SIMPLE_NAMES_INDEX]; + } + if (wcName != null) { + //create a pattern from the working copy field + FieldPattern wcPattern = new FieldPattern(true, false, false, + wcName, wcDeclaringTypeQualification, wcDeclaringTypeSimpleName, pattern.getMatchRule()); + if (fieldPattern.matchesDecodedKey(wcPattern)) { + requestor.acceptField(field); } - return true; } - } - parsedUnit.traverse(new AllTypeDeclarationsVisitor(), parsedUnit.scope); + } } } + } catch(JavaScriptModelException e) { + Logger.logException("Error while processing working copy", e); } } } finally { - if (progressMonitor != null) { - progressMonitor.done(); + if (monitor != null) { + monitor.done(); } } } + public void searchDeclarations(IJavaScriptElement enclosingElement, SearchRequestor requestor, SearchPattern pattern, IProgressMonitor monitor) throws JavaScriptModelException { if (VERBOSE) { Util.verbose(" - java element: "+enclosingElement); //$NON-NLS-1$ @@ -1540,10 +1420,10 @@ public class BasicSearchEngine { * <p>Used to search all constructor declarations for ones that match the given type name using the given role, * in the given scope, reporting to the given requester.</p> * - * @param typeNamePattern type name pattern to search for + * @param prefix constructor prefix to search for * @param typeMatchRule Search pattern matching rule to use with the given <code>typeNamePattern</code> * @param scope scope of the search - * @param nameRequester requester to report findings to + * @param requestor requester to report findings to * @param waitingPolicy Policy to use when waiting for the index * @param progressMonitor monitor to report index search progress to * @@ -1561,63 +1441,68 @@ public class BasicSearchEngine { * @see IJavaScriptSearchConstants#WAIT_UNTIL_READY_TO_SEARCH */ public void searchAllConstructorDeclarations( - final char[] typeNamePattern, + final char[] prefix, final int typeMatchRule, IJavaScriptSearchScope scope, - final IConstructorRequestor nameRequester, + final IConstructorRequestor requestor, int waitingPolicy, IProgressMonitor progressMonitor) { // Debug if (VERBOSE) { Util.verbose("BasicSearchEngine.searchAllConstructorDeclarations(char[], char[], int, IJavaSearchScope, IRestrictedAccessConstructorRequestor, int, IProgressMonitor)"); //$NON-NLS-1$ - Util.verbose(" - type name: "+(typeNamePattern==null?"null":new String(typeNamePattern))); //$NON-NLS-1$ //$NON-NLS-2$ + Util.verbose(" - type name: "+(prefix==null?"null":new String(prefix))); //$NON-NLS-1$ //$NON-NLS-2$ Util.verbose(" - type match rule: "+getMatchRuleString(typeMatchRule)); //$NON-NLS-1$ Util.verbose(" - scope: "+scope); //$NON-NLS-1$ } // Create pattern IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager(); - final ConstructorDeclarationPattern pattern = new ConstructorDeclarationPattern( - typeNamePattern, + final ConstructorPattern pattern = new ConstructorPattern( + prefix, typeMatchRule); // Index requester + final HashSet workingCopiesPaths = this.getWorkingCopiesPaths(); IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){ public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant, AccessRuleSet access) { // Filter unexpected types - ConstructorDeclarationPattern record = (ConstructorDeclarationPattern)indexRecord; + ConstructorPattern record = (ConstructorPattern)indexRecord; - - // Accept document path - AccessRestriction accessRestriction = null; - if (access != null) { - // Compute document relative path - int nameLength = record.declaringSimpleName==null ? 0 : record.declaringSimpleName.length; - char[] path = new char[nameLength]; - int pos = 0; - - 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); + //do not accept matches from files that have working copies open + if(!workingCopiesPaths.contains(documentPath)) { + // Accept document path + AccessRestriction accessRestriction = null; + if (access != null) { + // Compute document relative path + int nameLength = record.declaringSimpleName==null ? 0 : record.declaringSimpleName.length; + char[] path = new char[nameLength]; + int pos = 0; + + 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); + } } + requestor.acceptConstructor( + record.modifiers, + QualificationHelpers.createFullyQualifiedName( + record.declaringQualification, record.declaringSimpleName), + record.parameterNames == null ? 0 : record.parameterNames.length, + record.getFullyQualifiedParameterTypeNames(), + record.parameterNames, + documentPath, + accessRestriction); } - nameRequester.acceptConstructor( - record.modifiers, - record.declaringSimpleName, - record.parameterCount, - record.parameterTypes, - record.parameterNames, - documentPath, - accessRestriction); return true; } }; + //find constructor matches from index try { if (progressMonitor != null) { progressMonitor.beginTask(Messages.engine_searching, 1000); @@ -1636,5 +1521,444 @@ public class BasicSearchEngine { progressMonitor.done(); } } + + // find constructor matches from working copies + IJavaScriptUnit[] workingCopies = this.getWorkingCopies(); + for (int w = 0; workingCopies != null && w < workingCopies.length; w++) { + final IJavaScriptUnit workingCopy = workingCopies[w]; + + //skip this working copy if not in the scope + if(!scope.encloses(workingCopy)) { + continue; + } + + try { + //make the working copy consistent if it is not + if(!workingCopy.isConsistent()) { + workingCopy.makeConsistent(progressMonitor); + } + + //check each constructor in each type in the working copy for a match + IType[] types = workingCopy.getAllTypes(); + for(int t = 0; t < types.length; ++t) { + IType type = types[t]; + + //get type name + char[] wcTypeQualification = null; + char[] wcTypeSimpleName = null; + char[] wcTypeFullName = type.getTypeQualifiedName().toCharArray(); + if(type.getTypeQualifiedName() != null) { + char[][] wcSeperatedDeclaringType = QualificationHelpers.seperateFullyQualifedName(wcTypeFullName); + wcTypeQualification = wcSeperatedDeclaringType[QualificationHelpers.QULIFIERS_INDEX]; + wcTypeSimpleName = wcSeperatedDeclaringType[QualificationHelpers.SIMPLE_NAMES_INDEX]; + } + + if(wcTypeSimpleName != null) { + //if working type matches the pattern then propose its constructor + ConstructorPattern wcPattern = new ConstructorPattern( + wcTypeQualification, wcTypeSimpleName, typeMatchRule); + if(pattern.matchesDecodedKey(wcPattern)) { + IFunction[] allFunctions = type.getFunctions(); + for (int f = 0; f < allFunctions.length; ++f) { + IFunction function = allFunctions[f]; + + //if the function is a constructor propose it + if(function.isConstructor()) { + //figure out parameter names and types + String[] wcParameterNames = function.getParameterNames(); + char[][] wcParameterTypes = QualificationHelpers.stringArrayToCharArray(function.getParameterTypes()); + for(int i = 0; i < wcParameterTypes.length; ++i) { + try { + wcParameterTypes[i] = Signature.toCharArray(wcParameterTypes[i]); + } catch(IllegalArgumentException e) { + /* ignore, this will happen if a name looking like it maybe a signature gets passed in, but isn't, such as "QName" + * the real future fix for this should be to completely stop using signatures + */ + } + } + + //accept the constructor + requestor.acceptConstructor( + function.getFlags(), + wcTypeFullName, + wcParameterNames == null ? 0 : wcParameterNames.length, + wcParameterTypes, + QualificationHelpers.stringArrayToCharArray(wcParameterNames), + workingCopy.getPath().toString(), + null); + } + } + } + } + } + } catch(JavaScriptModelException e) { + Logger.logException("Error while processing working copy", e); //$NON-NLS-1$ + } + } + } + + /** + * <p>Searches for all methods in the index and working copies.</p> + * + * @param functionRequester requester to report results to + * @param selectorPattern selector pattern that the results need to match + * @param declaringType type that all results must be defined on + * @param selectorPatternMatchRule the match rule used with the given <code>selectorPattern</code> + * @param scope of the search + * @param waitingPolicy policy to use when waiting for the index to index + * @param progressMonitor monitor to report status too + * + * @see SearchPattern + * + * @see IJob#ForceImmediate + * @see IJob#CancelIfNotReady + * @see IJob#WaitUntilReady + */ + public void searchAllFunctions(final IFunctionRequester functionRequester, + char[] selectorPattern, char[][] declaringTypes, final int selectorPatternMatchRule, + IJavaScriptSearchScope scope, + int waitingPolicy, IProgressMonitor progressMonitor) { + + //pattern for searching the index and working copies + final MethodPattern searchPattern = new MethodPattern(true, false, + selectorPattern, declaringTypes, selectorPatternMatchRule); + + //requester used to accept index matches + final HashSet workingCopiesPaths = this.getWorkingCopiesPaths(); + IndexQueryRequestor queryRequestor = new IndexQueryRequestor() { + /** + * @see org.eclipse.wst.jsdt.internal.core.search.IndexQueryRequestor#acceptIndexMatch(java.lang.String, org.eclipse.wst.jsdt.core.search.SearchPattern, org.eclipse.wst.jsdt.core.search.SearchParticipant, org.eclipse.wst.jsdt.internal.compiler.env.AccessRuleSet) + */ + public boolean acceptIndexMatch(String documentPath, + SearchPattern indexRecord, SearchParticipant participant, + AccessRuleSet access) { + + if(!workingCopiesPaths.contains(documentPath)) { + MethodPattern record = (MethodPattern)indexRecord; + + functionRequester.acceptFunction(record.selector, + QualificationHelpers.createFullyQualifiedNames(record.parameterQualifications, record.parameterSimpleNames), + record.parameterNames, + record.returnQualification, record.returnSimpleName, + record.getDeclaringQualification(), record.getDeclaringSimpleName(), + record.modifiers, + documentPath); + } + + return true; + } + }; + + // Find function matches from index + IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager(); + try { + if (progressMonitor != null) { + progressMonitor.beginTask(Messages.engine_searching, 1000); + } + + indexManager.performConcurrentJob( + new PatternSearchJob( + searchPattern, + getDefaultSearchParticipant(), // JavaScript search only + scope, + queryRequestor), + waitingPolicy, + progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 1000)); + } finally { + if (progressMonitor != null) { + progressMonitor.done(); + } + } + + // find function matches from working copies + IJavaScriptUnit[] workingCopies = this.getWorkingCopies(); + for (int workingCopyIndex = 0; workingCopies != null && workingCopyIndex < workingCopies.length; + workingCopyIndex++) { + + final IJavaScriptUnit workingCopy = workingCopies[workingCopyIndex]; + + //skip this working copy if not in the scope + if(!scope.encloses(workingCopy)) { + continue; + } + + try { + //make the working copy consistent if it is not + if(!workingCopy.isConsistent()) { + workingCopy.makeConsistent(progressMonitor); + } + + //get all functions defined at the compilation unit level + List allFunctions = new ArrayList(); + allFunctions.addAll(Arrays.asList(workingCopy.getFunctions())); + + //get all functions defined on global type + IType[] types = workingCopy.getTypes(); + if(types != null & types.length > 0) { + IType globalType = findGlobalType(workingCopy); + + if(globalType != null) { + allFunctions.addAll(Arrays.asList(globalType.getFunctions())); + } + } + + //check each field in the working copy for a match + for (int funcIndex = 0; funcIndex < allFunctions.size(); ++funcIndex) { + IFunction function = (IFunction)allFunctions.get(funcIndex); + + //selector must not be null for it to be a match + char[] wcSelector = null; + if(function.getElementName() != null) { + wcSelector = function.getElementName().toCharArray(); + } + if(wcSelector != null) { + + //create a pattern from the working copy method + char[] wcDeclaringType = null; + if(function.getDeclaringType() != null && function.getDeclaringType().getTypeQualifiedName() != null) { + wcDeclaringType = function.getDeclaringType().getTypeQualifiedName().toCharArray(); + } + wcDeclaringType = wcDeclaringType != null ? wcDeclaringType : IIndexConstants.GLOBAL_SYMBOL; + MethodPattern wcPattern = new MethodPattern(true, false, + wcSelector, declaringTypes, selectorPatternMatchRule); + + //if working copy function matches the search pattern then accept the function + if(searchPattern.matchesDecodedKey(wcPattern)) { + //figure out parameter types + char[][] wcParameterTypes = QualificationHelpers.stringArrayToCharArray(function.getParameterTypes()); + for(int i = 0; i < wcParameterTypes.length; ++i) { + try { + wcParameterTypes[i] = Signature.toCharArray(wcParameterTypes[i]); + } catch(IllegalArgumentException e) { + /* ignore, this will happen if a name looking like it maybe a signature gets passed in, but isn't, such as "QName" + * the real future fix for this should be to completely stop using signatures + */ + } + } + + //figure out the return type parts + char[] wcReturnQualification = null; + char[] wcReturnSimpleName = null; + String wcReturnTypeSig = function.getReturnType(); + if(wcReturnTypeSig != null) { + char[] wcReturnType = Signature.toString(wcReturnTypeSig).toCharArray(); + char[][] wcSeperatedReturnType = + QualificationHelpers.seperateFullyQualifedName(wcReturnType); + wcReturnQualification = wcSeperatedReturnType[QualificationHelpers.QULIFIERS_INDEX]; + wcReturnSimpleName = wcSeperatedReturnType[QualificationHelpers.SIMPLE_NAMES_INDEX]; + } + + //get the declaring type parts + char[][] wcSeperatedDeclaringType = QualificationHelpers.seperateFullyQualifedName(wcDeclaringType); + + //accept the method + functionRequester.acceptFunction(wcSelector, + wcParameterTypes, + QualificationHelpers.stringArrayToCharArray(function.getParameterNames()), + wcReturnQualification, wcReturnSimpleName, + wcSeperatedDeclaringType[QualificationHelpers.QULIFIERS_INDEX], + wcSeperatedDeclaringType[QualificationHelpers.SIMPLE_NAMES_INDEX], + function.getFlags(), workingCopy.getPath().toString()); + } + } + } + } catch(JavaScriptModelException e) { + Logger.logException("Error while processing working copy", e); + } + } + } + + + /** + * <p>Searches for all variables in the index and working copies.</p> + * + * @param variableRequester requester to report results to + * @param variablePattern selector pattern that the results need to match + * @param declaringType type that all results must be defined on + * @param variablePatternMatchRule the match rule used with the given <code>variablePattern</code> + * @param scope of the search + * @param waitingPolicy policy to use when waiting for the index to index + * @param progressMonitor monitor to report status too + * + * @see SearchPattern + * + * @see IJob#ForceImmediate + * @see IJob#CancelIfNotReady + * @see IJob#WaitUntilReady + */ + public void searchAllVariables(final IVariableRequester variableRequester, + char[] variablePattern, char[][] declaringTypes, final int variablePatternMatchRule, + IJavaScriptSearchScope scope, + int waitingPolicy, IProgressMonitor progressMonitor) { + + //determine the declaring type pattern characters + char[][] declaringTypePatternChars = null; + if(declaringTypes != null && declaringTypes.length > 0) { + declaringTypePatternChars = new char[declaringTypes.length][]; + for(int i = 0; i < declaringTypes.length; i++) + declaringTypePatternChars[i] = declaringTypes[i]; + } + + //pattern for searching the index and working copies + final FieldPattern searchPattern = new FieldPattern(true, false, false, true, + variablePattern, declaringTypePatternChars, null, null, variablePatternMatchRule, null); + + //requester used to accept index matches + final HashSet workingCopiesPaths = this.getWorkingCopiesPaths(); + IndexQueryRequestor queryRequestor = new IndexQueryRequestor() { + /** + * @see org.eclipse.wst.jsdt.internal.core.search.IndexQueryRequestor#acceptIndexMatch(java.lang.String, org.eclipse.wst.jsdt.core.search.SearchPattern, org.eclipse.wst.jsdt.core.search.SearchParticipant, org.eclipse.wst.jsdt.internal.compiler.env.AccessRuleSet) + */ + public boolean acceptIndexMatch(String documentPath, + SearchPattern indexRecord, SearchParticipant participant, + AccessRuleSet access) { + + if(!workingCopiesPaths.contains(documentPath)) { + FieldPattern record = (FieldPattern)indexRecord; + variableRequester.acceptVariable(record.name, + record.typeQualification, record.typeSimpleName, record.getDeclaringQualification(), + record.getDeclaringSimpleName(), + record.modifiers, + documentPath); + } + + return true; + } + }; + + // Find function matches from index + IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager(); + try { + if (progressMonitor != null) { + progressMonitor.beginTask(Messages.engine_searching, 1000); + } + + indexManager.performConcurrentJob( + new PatternSearchJob( + searchPattern, + getDefaultSearchParticipant(), // JavaScript search only + scope, + queryRequestor), + waitingPolicy, + progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 1000)); + } finally { + if (progressMonitor != null) { + progressMonitor.done(); + } + } + + // find function matches from working copies + IJavaScriptUnit[] workingCopies = this.getWorkingCopies(); + for (int workingCopyIndex = 0; workingCopies != null && workingCopyIndex < workingCopies.length; + workingCopyIndex++) { + + final IJavaScriptUnit workingCopy = workingCopies[workingCopyIndex]; + + //skip this working copy if not in the scope + if(!scope.encloses(workingCopy)) { + continue; + } + + try { + //make the working copy consistent if it is not + if(!workingCopy.isConsistent()) { + workingCopy.makeConsistent(progressMonitor); + } + + //get all fields defined at the compilation unit level + List allFields = new ArrayList(); + allFields.addAll(Arrays.asList(workingCopy.getFields())); + + //get all fields defined on global type defined in this file + IType[] types = workingCopy.getTypes(); + if(types != null & types.length > 0) { + IType globalType = findGlobalType(workingCopy); + + if(globalType != null) { + allFields.addAll(Arrays.asList(globalType.getFields())); + } + } + + //check each field in the working copy for a match + for (int fieldIndex = 0; fieldIndex < allFields.size(); ++fieldIndex) { + IField field = (IField)allFields.get(fieldIndex); + + //selector must not be null for it to be a match + char[] wcName = null; + if(field.getElementName() != null) { + wcName = field.getElementName().toCharArray(); + } + if(wcName != null) { + + //create a pattern from the working copy method + char[] wcDeclaringType = null; + if(field.getDeclaringType() != null && field.getDeclaringType().getTypeQualifiedName() != null) { + wcDeclaringType = field.getDeclaringType().getTypeQualifiedName().toCharArray(); + } + + wcDeclaringType = wcDeclaringType != null ? wcDeclaringType : IIndexConstants.GLOBAL_SYMBOL; + FieldPattern wcPattern = new FieldPattern(true, false, false, true, + wcName, declaringTypePatternChars, null, null, variablePatternMatchRule, null); + + //if working copy function matches the search pattern then accept the function + if(searchPattern.matchesDecodedKey(wcPattern)) { + + //figure out the return type parts + char[] wcTypeQualification = null; + char[] wcTypeSimpleName = null; + String wcTypeSig = field.getTypeSignature(); + if(wcTypeSig != null) { + char[] wcType = Signature.toString(wcTypeSig).toCharArray(); + char[][] wcSeperatedType = + QualificationHelpers.seperateFullyQualifedName(wcType); + wcTypeQualification = wcSeperatedType[QualificationHelpers.QULIFIERS_INDEX]; + wcTypeSimpleName = wcSeperatedType[QualificationHelpers.SIMPLE_NAMES_INDEX]; + } + + //get the declaring type parts + char[][] wcSeperatedDeclaringType = QualificationHelpers.seperateFullyQualifedName(wcDeclaringType); + + //accept the field + variableRequester.acceptVariable(wcName, + wcTypeQualification, wcTypeSimpleName, + wcSeperatedDeclaringType[QualificationHelpers.QULIFIERS_INDEX], + wcSeperatedDeclaringType[QualificationHelpers.SIMPLE_NAMES_INDEX], + field.getFlags(), workingCopy.getPath().toString()); + } + } + } + } catch(JavaScriptModelException e) { + Logger.logException("Error while processing working copy", e); + } + } + } + + /** + * <p> + * Finds the global type on the given unit if there is one. + * </p> + * + * @param unit + * {@link IJavaScriptUnit} to find the global type on + * + * @return global type in the given {@link IJavaScriptUnit}, or + * <code>null</code> if there is none + * + * @throws JavaScriptModelException + * getting the types on the unit can throw this + */ + private static IType findGlobalType(IJavaScriptUnit unit) throws JavaScriptModelException { + IType globalType = null; + + IType[] types = unit.getTypes(); + if(types != null & types.length > 0) { + for(int i = 0; i < types.length && globalType == null; ++i) { + if(types[i].getElementName().equals(GLOBAL_TYPE_SYMBOL)) { + globalType = types[i]; + } + } + } + + return globalType; } } |