| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * xored software, Inc. - initial API and Implementation |
| * xored software, Inc. - Search All occurences bugfix, |
| * hilight only class name when class is in search results ( Alex Panchenko <alex@xored.com>) |
| *******************************************************************************/ |
| package org.eclipse.dltk.core.search.matching; |
| |
| import java.io.IOException; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.dltk.ast.ASTNode; |
| import org.eclipse.dltk.ast.declarations.FieldDeclaration; |
| import org.eclipse.dltk.ast.declarations.MethodDeclaration; |
| import org.eclipse.dltk.ast.declarations.ModuleDeclaration; |
| import org.eclipse.dltk.ast.declarations.TypeDeclaration; |
| import org.eclipse.dltk.compiler.env.INameEnvironment; |
| import org.eclipse.dltk.compiler.env.ISourceType; |
| import org.eclipse.dltk.compiler.env.lookup.Scope; |
| import org.eclipse.dltk.compiler.util.SimpleLookupTable; |
| import org.eclipse.dltk.compiler.util.SimpleSet; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.DLTKLanguageManager; |
| import org.eclipse.dltk.core.IDLTKLanguageToolkit; |
| import org.eclipse.dltk.core.IField; |
| import org.eclipse.dltk.core.IMember; |
| import org.eclipse.dltk.core.IMethod; |
| import org.eclipse.dltk.core.IModelElement; |
| import org.eclipse.dltk.core.IModelStatusConstants; |
| import org.eclipse.dltk.core.IParent; |
| import org.eclipse.dltk.core.IScriptProject; |
| import org.eclipse.dltk.core.ISearchableEnvironment; |
| import org.eclipse.dltk.core.ISourceModule; |
| import org.eclipse.dltk.core.IType; |
| import org.eclipse.dltk.core.ModelException; |
| import org.eclipse.dltk.core.search.BasicSearchEngine; |
| import org.eclipse.dltk.core.search.FieldDeclarationMatch; |
| import org.eclipse.dltk.core.search.FieldReferenceMatch; |
| import org.eclipse.dltk.core.search.IDLTKSearchScope; |
| import org.eclipse.dltk.core.search.IMatchLocatorParser; |
| import org.eclipse.dltk.core.search.MethodDeclarationMatch; |
| import org.eclipse.dltk.core.search.MethodReferenceMatch; |
| import org.eclipse.dltk.core.search.SearchDocument; |
| import org.eclipse.dltk.core.search.SearchMatch; |
| import org.eclipse.dltk.core.search.SearchParticipant; |
| import org.eclipse.dltk.core.search.SearchPattern; |
| import org.eclipse.dltk.core.search.SearchRequestor; |
| import org.eclipse.dltk.core.search.TypeDeclarationMatch; |
| import org.eclipse.dltk.core.search.TypeReferenceMatch; |
| import org.eclipse.dltk.core.search.index.Index; |
| import org.eclipse.dltk.internal.compiler.env.AccessRestriction; |
| import org.eclipse.dltk.internal.compiler.impl.ITypeRequestor; |
| import org.eclipse.dltk.internal.compiler.lookup.LookupEnvironment; |
| import org.eclipse.dltk.internal.compiler.lookup.SourceModuleScope; |
| import org.eclipse.dltk.internal.core.ArchiveProjectFragment; |
| import org.eclipse.dltk.internal.core.ModelElement; |
| import org.eclipse.dltk.internal.core.ModelManager; |
| import org.eclipse.dltk.internal.core.ModelStatus; |
| import org.eclipse.dltk.internal.core.NameLookup; |
| import org.eclipse.dltk.internal.core.Openable; |
| import org.eclipse.dltk.internal.core.ScriptProject; |
| import org.eclipse.dltk.internal.core.SourceModule; |
| import org.eclipse.dltk.internal.core.SourceRefElement; |
| import org.eclipse.dltk.internal.core.search.IndexQueryRequestor; |
| import org.eclipse.dltk.internal.core.search.matching.AndPattern; |
| import org.eclipse.dltk.internal.core.search.matching.InternalSearchPattern; |
| import org.eclipse.dltk.internal.core.search.matching.MatchingNodeSet; |
| import org.eclipse.dltk.internal.core.search.matching.OrPattern; |
| import org.eclipse.dltk.internal.core.util.HandleFactory; |
| import org.eclipse.dltk.internal.core.util.Util; |
| |
| public class MatchLocator implements IMatchLocator, ITypeRequestor { |
| public static final int MAX_AT_ONCE; |
| static { |
| long maxMemory = Runtime.getRuntime().maxMemory(); |
| int ratio = (int) Math.round(((double) maxMemory) / (64 * 0x100000)); |
| switch (ratio) { |
| case 0: |
| case 1: |
| MAX_AT_ONCE = 100; |
| break; |
| case 2: |
| MAX_AT_ONCE = 200; |
| break; |
| case 3: |
| MAX_AT_ONCE = 300; |
| break; |
| default: |
| MAX_AT_ONCE = 400; |
| break; |
| } |
| } |
| |
| // permanent state |
| public SearchPattern pattern; |
| |
| public PatternLocator patternLocator; |
| |
| public int matchContainer; |
| |
| public SearchRequestor requestor; |
| |
| public IDLTKSearchScope scope; |
| |
| private IProgressMonitor progressMonitor; |
| |
| public org.eclipse.dltk.core.ISourceModule[] workingCopies; |
| |
| private HandleFactory handleFactory; |
| |
| // cache of all super type names if scope is hierarchy scope |
| public char[][][] allSuperTypeNames; |
| |
| // the following is valid for the current project |
| public IMatchLocatorParser parser; |
| |
| // private Parser basicParser; |
| public INameEnvironment nameEnvironment; |
| |
| public NameLookup nameLookup; |
| |
| public LookupEnvironment lookupEnvironment; |
| |
| // management of PossibleMatch to be processed |
| public int numberOfMatches; // (numberOfMatches - 1) is the last unit in |
| |
| // matchesToProcess |
| public PossibleMatch[] matchesToProcess; |
| |
| public PossibleMatch currentPossibleMatch; |
| |
| /* |
| * Time spent in the IJavaSearchResultCollector |
| */ |
| public long resultCollectorTime = 0; |
| |
| // Progress information |
| protected int progressStep; |
| |
| protected int progressWorked; |
| |
| // Binding resolution and cache |
| protected SourceModuleScope unitScope; |
| |
| protected SimpleLookupTable bindings; |
| |
| // Cache for handles |
| private HashSet handles; |
| |
| static public class WrappedCoreException extends RuntimeException { |
| private static final long serialVersionUID = 8354329870126121212L; // backward |
| |
| // compatible |
| public CoreException coreException; |
| |
| public WrappedCoreException(CoreException coreException) { |
| this.coreException = coreException; |
| } |
| } |
| |
| public static void setFocus(InternalSearchPattern pattern, |
| IModelElement focus) { |
| pattern.focus = focus; |
| if (pattern instanceof OrPattern) { |
| for (SearchPattern child : ((OrPattern) pattern).getPatterns()) { |
| child.focus = focus; |
| } |
| } |
| } |
| |
| public static SearchPattern createAndPattern( |
| final SearchPattern leftPattern, final SearchPattern rightPattern) { |
| Assert.isNotNull(leftPattern.getToolkit()); |
| Assert.isTrue( |
| leftPattern.getToolkit().equals(rightPattern.getToolkit())); |
| return new AndPattern(0/* no kind */, 0/* no rule */, |
| leftPattern.getToolkit()) { |
| SearchPattern current = leftPattern; |
| |
| @Override |
| public SearchPattern currentPattern() { |
| return this.current; |
| } |
| |
| @Override |
| public boolean hasNextQuery() { |
| if (this.current == leftPattern) { |
| this.current = rightPattern; |
| return true; |
| } |
| return false; |
| } |
| |
| @Override |
| public void resetQuery() { |
| this.current = leftPattern; |
| } |
| }; |
| } |
| |
| /** |
| * Query a given index for matching entries. Assumes the sender has opened |
| * the index and will close when finished. |
| */ |
| public static void findIndexMatches(InternalSearchPattern pattern, |
| Index index, IndexQueryRequestor requestor, |
| SearchParticipant participant, IDLTKSearchScope scope, |
| IProgressMonitor monitor) throws IOException { |
| pattern.findIndexMatches(index, requestor, participant, scope, monitor); |
| } |
| |
| public static IModelElement getProjectOrArchive(IModelElement element) { |
| while (!(element instanceof IScriptProject) |
| && !(element instanceof ArchiveProjectFragment)) { |
| element = element.getParent(); |
| } |
| return element; |
| } |
| |
| public static boolean isPolymorphicSearch(InternalSearchPattern pattern) { |
| return pattern.isPolymorphicSearch(); |
| } |
| |
| public static IModelElement projectOrArchiveFocus( |
| InternalSearchPattern pattern) { |
| return pattern == null || pattern.focus == null ? null |
| : getProjectOrArchive(pattern.focus); |
| } |
| |
| public MatchLocator() { |
| } |
| |
| @Override |
| public void initialize(SearchPattern pattern, IDLTKSearchScope scope) { |
| this.pattern = pattern; |
| this.patternLocator = PatternLocator.patternLocator(this.pattern, |
| scope.getLanguageToolkit()); |
| this.matchContainer = this.patternLocator.matchContainer(); |
| this.scope = scope; |
| } |
| |
| @Override |
| public void setRequestor(SearchRequestor requestor) { |
| this.requestor = requestor; |
| } |
| |
| @Override |
| public void setProgressMonitor(IProgressMonitor progressMonitor) { |
| this.progressMonitor = progressMonitor; |
| } |
| |
| /** |
| * Add an additional compilation unit into the loop -> build compilation |
| * unit declarations, their bindings and record their results. |
| */ |
| public void accept(ISourceModule sourceUnit, |
| AccessRestriction accessRestriction) { |
| } |
| |
| /** |
| * Add additional source types |
| */ |
| public void accept(ISourceType[] sourceTypes, |
| AccessRestriction accessRestriction) { |
| } |
| |
| /* |
| * / Computes the super type names of the focus type if any. |
| */ |
| protected char[][][] computeSuperTypeNames(IType focusType) { |
| return null; |
| } |
| |
| /** |
| * Creates an IMethod from the given method declaration and type. |
| */ |
| protected IModelElement createHandle(MethodDeclaration method, |
| IModelElement parent) { |
| // if (!(parent instanceof IType)) return parent; |
| if (parent instanceof IType) { |
| IType type = (IType) parent; |
| return createMethodHandle(type, method.getName()); |
| } else if (parent instanceof ISourceModule) { |
| return createMethodHandle((ISourceModule) parent, method.getName()); |
| } |
| return null; |
| } |
| |
| /** |
| * Creates an IMethod from the given method declaration and type. |
| */ |
| protected IModelElement createHandle(FieldDeclaration field, |
| IModelElement parent) { |
| // if (!(parent instanceof IType)) return parent; |
| if (parent instanceof IType) { |
| IType type = (IType) parent; |
| return createFieldHandle(type, field.getName()); |
| } else if (parent instanceof ISourceModule) { |
| return createFieldHandle((ISourceModule) parent, field.getName()); |
| } |
| return null; |
| } |
| |
| /* |
| * Create method handle. Store occurences for create handle to retrieve |
| * possible duplicate ones. |
| */ |
| protected IModelElement createMethodHandle(IType type, String methodName) { |
| IMethod methodHandle = type.getMethod(methodName); |
| resolveDuplicates(methodHandle); |
| return methodHandle; |
| } |
| |
| /** |
| * Increment the {@link SourceRefElement#occurrenceCount} until the |
| * specified handle is unique. |
| * |
| * @param handle |
| */ |
| protected void resolveDuplicates(IMember handle) { |
| if (handle instanceof SourceRefElement) { |
| while (this.handles.contains(handle)) { |
| ((SourceRefElement) handle).occurrenceCount++; |
| } |
| this.handles.add(handle); |
| } |
| } |
| |
| protected IModelElement createTypeHandle(IType parent, String name) { |
| final IType typeHandle = parent.getType(name); |
| resolveDuplicates(typeHandle); |
| return typeHandle; |
| } |
| |
| /* |
| * Create method handle. Store occurrences for create handle to retrieve |
| * possible duplicate ones. |
| */ |
| protected IModelElement createMethodHandle(ISourceModule module, |
| String methodName) { |
| |
| IMethod methodHandle = module.getMethod(methodName); |
| resolveDuplicates(methodHandle); |
| return methodHandle; |
| } |
| |
| /* |
| * Create method handle. Store occurences for create handle to retrieve |
| * possible duplicate ones. |
| */ |
| protected IModelElement createFieldHandle(IType type, String methodName) { |
| IField fieldHandle = type.getField(methodName); |
| resolveDuplicates(fieldHandle); |
| return fieldHandle; |
| } |
| |
| /* |
| * Create method handle. Store occurences for create handle to retrieve |
| * possible duplicate ones. |
| */ |
| protected IModelElement createFieldHandle(ISourceModule module, |
| String methodName) { |
| |
| IField fieldHandle = module.getField(methodName); |
| resolveDuplicates(fieldHandle); |
| return fieldHandle; |
| } |
| |
| /** |
| * Creates an IType from the given simple top level type name. |
| */ |
| protected IType createTypeHandle(String simpleTypeName) { |
| Openable openable = this.currentPossibleMatch.openable; |
| IType type = null; |
| if (openable instanceof ISourceModule) |
| type = ((ISourceModule) openable).getType(simpleTypeName); |
| resolveDuplicates(type); |
| return type; |
| } |
| |
| /** |
| * Creates an IType from the given simple top level type name. |
| */ |
| protected ISourceModule createSourceModuleHandle() { |
| Openable openable = this.currentPossibleMatch.openable; |
| if (openable instanceof ISourceModule) |
| return ((ISourceModule) openable); |
| return null; |
| } |
| |
| /** |
| * Creates an IType from the given simple top level type name. |
| */ |
| protected IMethod createMethodHandle(String simpleTypeName) { |
| Openable openable = this.currentPossibleMatch.openable; |
| IMethod method = null; |
| if (openable instanceof ISourceModule) |
| method = ((ISourceModule) openable).getMethod(simpleTypeName); |
| resolveDuplicates(method); |
| return method; |
| } |
| |
| /** |
| * Creates an IType from the given simple top level type name. |
| */ |
| protected IField createFieldHandle(String simpleTypeName) { |
| Openable openable = this.currentPossibleMatch.openable; |
| IField field; |
| if (openable instanceof ISourceModule) { |
| field = ((SourceModule) openable).getField(simpleTypeName); |
| } else { |
| field = null; |
| } |
| resolveDuplicates(field); |
| return field; |
| } |
| |
| protected boolean encloses(IModelElement element) { |
| return element != null && this.scope.encloses(element); |
| } |
| |
| protected void getMethodBodies(ModuleDeclaration unit, |
| MatchingNodeSet nodeSet) { |
| |
| try { |
| this.parser.setNodeSet(nodeSet); |
| this.parser.parseBodies(unit); |
| } finally { |
| this.parser.setNodeSet(null); |
| } |
| } |
| |
| /** |
| * Create a new parser for the given project, as well as a lookup |
| * environment. |
| * |
| * @since 2.0 |
| */ |
| public void initialize(IScriptProject project, int possibleMatchSize) |
| throws ModelException { |
| // clean up name environment only if there are several possible match as |
| // it is |
| // reused |
| // when only one possible match (bug 58581) |
| if (this.nameEnvironment != null && possibleMatchSize != 1) |
| this.nameEnvironment.cleanup(); |
| |
| ISearchableEnvironment searchableEnvironment = ((ScriptProject) project) |
| .newSearchableNameEnvironment(this.workingCopies); |
| |
| // if only one possible match, a file name environment costs too much, |
| // so use the existing searchable environment which will populate the |
| // scriptmodel |
| // only for this possible match and its required types. |
| |
| this.nameEnvironment = possibleMatchSize == 1 |
| ? (INameEnvironment) searchableEnvironment |
| : null;// (INameEnvironment) |
| |
| this.lookupEnvironment = new LookupEnvironment(this, /* |
| * problemReporter, |
| */ |
| this.nameEnvironment); |
| |
| IDLTKLanguageToolkit tk = null; |
| tk = DLTKLanguageManager.getLanguageToolkit(project); |
| if (tk == null) { |
| throw new ModelException(new ModelStatus( |
| IModelStatusConstants.INVALID_PROJECT, project, |
| Messages.MatchLocator_languageToolkitNotFoundForProject)); |
| } |
| this.parser = DLTKLanguageManager.createMatchParser(tk.getNatureId(), |
| this); |
| |
| // remember project's name lookup |
| this.nameLookup = searchableEnvironment.getNameLookup(); |
| |
| // initialize queue of units |
| this.numberOfMatches = 0; |
| this.matchesToProcess = new PossibleMatch[possibleMatchSize]; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| protected void locateMatches(IScriptProject scriptProject, |
| PossibleMatch[] possibleMatches, int start, int length) |
| throws CoreException { |
| initialize(scriptProject, length); |
| // create and resolve binding (equivalent to beginCompilation() in |
| // Compiler) |
| for (int i = start, maxUnits = start + length; i < maxUnits; i++) { |
| PossibleMatch possibleMatch = possibleMatches[i]; |
| try { |
| if (!parse(possibleMatch)) |
| continue; |
| worked(); |
| process(possibleMatch); |
| if (this.numberOfMatches > 0 |
| && this.matchesToProcess[this.numberOfMatches |
| - 1] == possibleMatch) { |
| // forget last possible match as it was processed |
| this.numberOfMatches--; |
| } |
| } finally { |
| possibleMatch.cleanUp(); |
| } |
| } |
| } |
| |
| private boolean parse(PossibleMatch possibleMatch) { |
| if (this.progressMonitor != null && this.progressMonitor.isCanceled()) |
| throw new OperationCanceledException(); |
| |
| try { |
| if (BasicSearchEngine.VERBOSE) |
| System.out.println("Parsing " //$NON-NLS-1$ |
| + possibleMatch.openable.toStringWithAncestors()); |
| |
| this.parser.setNodeSet(possibleMatch.nodeSet); |
| ModuleDeclaration parsedUnit = this.parser.parse(possibleMatch); |
| if (parsedUnit != null) { |
| |
| // if (hasAlreadyDefinedType(parsedUnit)) return false; // skip |
| // type has it is hidden so not visible |
| getMethodBodies(parsedUnit, possibleMatch.nodeSet); |
| |
| // add the possibleMatch with its parsedUnit to matchesToProcess |
| possibleMatch.parsedUnit = parsedUnit; |
| int size = this.matchesToProcess.length; |
| if (this.numberOfMatches == size) |
| System.arraycopy(this.matchesToProcess, 0, |
| this.matchesToProcess = new PossibleMatch[size == 0 |
| ? 1 |
| : size * 2], |
| 0, this.numberOfMatches); |
| this.matchesToProcess[this.numberOfMatches++] = possibleMatch; |
| } |
| } finally { |
| this.parser.setNodeSet(null); |
| } |
| return true; |
| } |
| |
| /** |
| * Locate the matches amongst the possible matches. |
| * |
| * @noreference This method is not intended to be referenced by clients. |
| */ |
| protected void locateMatches(IScriptProject scriptProject, |
| PossibleMatchSet matchSet, int expected) throws CoreException { |
| PossibleMatch[] possibleMatches = matchSet |
| .getPossibleMatches(scriptProject.getProjectFragments()); |
| int length = possibleMatches.length; |
| // increase progress from duplicate matches not stored in matchSet while |
| // adding... |
| if (this.progressMonitor != null && expected > length) { |
| this.progressWorked += expected - length; |
| this.progressMonitor.worked(expected - length); |
| } |
| // locate matches (processed matches are limited to avoid problem while |
| // using Interpreter default memory heap size) |
| for (int index = 0; index < length;) { |
| int max = Math.min(MAX_AT_ONCE, length - index); |
| locateMatches(scriptProject, possibleMatches, index, max); |
| index += max; |
| } |
| this.patternLocator.clear(); |
| } |
| |
| /** |
| * Locate the matches in the given files and report them using the search |
| * requestor. |
| */ |
| @Override |
| public void locateMatches(SearchDocument[] searchDocuments) |
| throws CoreException { |
| int docsLength = searchDocuments.length; |
| if (BasicSearchEngine.VERBOSE) { |
| System.out.println("Locating matches in documents ["); //$NON-NLS-1$ |
| for (int i = 0; i < docsLength; i++) |
| System.out.println("\t" + searchDocuments[i]); //$NON-NLS-1$ |
| System.out.println("]"); //$NON-NLS-1$ |
| } |
| // init infos for progress increasing |
| int n = docsLength < 1000 |
| ? Math.min(Math.max(docsLength / 200 + 1, 2), 4) |
| : 5 * (docsLength / 1000); |
| this.progressStep = docsLength < n ? 1 : docsLength / n; // step |
| // should |
| // not be 0 |
| this.progressWorked = 0; |
| // extract working copies |
| this.workingCopies = ModuleFactory.selectWorkingCopies(searchDocuments); |
| ModelManager manager = ModelManager.getModelManager(); |
| this.bindings = new SimpleLookupTable(); |
| try { |
| // optimize access to zip files during search operation |
| manager.cacheZipFiles(); |
| // initialize handle factory (used as a cache of handles so as to |
| // optimize space) |
| if (this.handleFactory == null) |
| this.handleFactory = new HandleFactory(); |
| final ModuleFactory moduleFactory = new ModuleFactory(handleFactory, |
| this.scope); |
| if (this.progressMonitor != null) { |
| this.progressMonitor.beginTask("", searchDocuments.length); //$NON-NLS-1$ |
| } |
| // initialize pattern for polymorphic search (ie. method reference |
| // pattern) |
| this.patternLocator.initializePolymorphicSearch(this); |
| IScriptProject previousScriptProject = null; |
| PossibleMatchSet matchSet = new PossibleMatchSet(); |
| Util.sort(searchDocuments, (a, b) -> ((SearchDocument) a).getPath() |
| .compareTo(((SearchDocument) b).getPath())); |
| int displayed = 0; // progress worked displayed |
| final Set<String> previousPaths = new HashSet<>(); |
| for (int i = 0; i < docsLength; i++) { |
| if (this.progressMonitor != null |
| && this.progressMonitor.isCanceled()) { |
| throw new OperationCanceledException(); |
| } |
| // skip duplicate paths |
| SearchDocument searchDocument = searchDocuments[i]; |
| searchDocuments[i] = null; // free current document |
| if (!previousPaths.add(searchDocument.getPath())) { |
| worked(); |
| displayed++; |
| continue; |
| } |
| final ISourceModule openable = moduleFactory |
| .create(searchDocument); |
| if (openable == null) { |
| worked(); |
| displayed++; |
| continue; // match is outside buildpath |
| } |
| // create new parser and lookup environment if this is a new |
| // project |
| IScriptProject scriptProject = openable.getScriptProject(); |
| IResource resource = openable.getResource(); |
| if (resource == null) |
| resource = scriptProject.getProject(); // case of a file in |
| // an external jar |
| if (!scriptProject.equals(previousScriptProject)) { |
| // locate matches in previous project |
| if (previousScriptProject != null) { |
| try { |
| locateMatches(previousScriptProject, matchSet, |
| i - displayed); |
| displayed = i; |
| } catch (ModelException e) { |
| // problem with buildpath in this project -> skip it |
| DLTKCore.error("error in locateMatches", e); //$NON-NLS-1$ |
| } |
| matchSet.reset(); |
| } |
| previousScriptProject = scriptProject; |
| } |
| matchSet.add(new PossibleMatch(this, resource, openable, |
| searchDocument)); |
| } |
| // last project |
| if (previousScriptProject != null) { |
| try { |
| locateMatches(previousScriptProject, matchSet, |
| docsLength - displayed); |
| } catch (ModelException e) { |
| // problem with buildpath in last project -> ignore |
| DLTKCore.error("error in locateMatches", e); //$NON-NLS-1$ |
| } |
| } |
| if (this.progressMonitor != null) |
| this.progressMonitor.done(); |
| } finally { |
| if (this.nameEnvironment != null) |
| this.nameEnvironment.cleanup(); |
| manager.flushZipFiles(); |
| this.bindings = null; |
| } |
| } |
| |
| private void worked() { |
| if (this.progressMonitor != null) { |
| this.progressWorked++; |
| if ((this.progressWorked % this.progressStep) == 0) |
| this.progressMonitor.worked(this.progressStep); |
| } |
| } |
| |
| public SearchMatch newDeclarationMatch(IModelElement element, int accuracy, |
| int offset, int length) { |
| SearchParticipant participant = getParticipant(); |
| IResource resource = this.currentPossibleMatch.resource; |
| return newDeclarationMatch(element, accuracy, offset, length, |
| participant, resource); |
| } |
| |
| public SearchMatch newDeclarationMatch(IModelElement element, int accuracy, |
| int offset, int length, SearchParticipant participant, |
| IResource resource) { |
| switch (element.getElementType()) { |
| case IModelElement.TYPE: |
| return new TypeDeclarationMatch(element, accuracy, offset, length, |
| participant, resource); |
| case IModelElement.FIELD: |
| return new FieldDeclarationMatch(element, accuracy, offset, length, |
| participant, resource); |
| |
| case IModelElement.METHOD: |
| return new MethodDeclarationMatch(element, accuracy, offset, length, |
| participant, resource); |
| default: |
| return null; |
| } |
| } |
| |
| public SearchMatch newFieldReferenceMatch(IModelElement enclosingElement, |
| int accuracy, int offset, int length, ASTNode reference) { |
| SearchParticipant participant = getParticipant(); |
| IResource resource = this.currentPossibleMatch.resource; |
| boolean insideDocComment = false; |
| boolean isReadAccess = false; |
| boolean isWriteAccess = false; |
| |
| if (enclosingElement instanceof IParent |
| && reference instanceof FieldDeclaration) { |
| IParent parent = (IParent) enclosingElement; |
| IModelElement[] children; |
| try { |
| FieldDeclaration decl = (FieldDeclaration) reference; |
| children = parent.getChildren(); |
| boolean found = false; |
| for (int i = 0; i < children.length; i++) { |
| if (children[i].getElementName().equals(decl.getName()) |
| && children[i] instanceof IField) { |
| enclosingElement = children[i]; |
| found = true; |
| break; |
| } |
| } |
| if (!found) { |
| return null; |
| } |
| } catch (ModelException e) { |
| return null; |
| } |
| } |
| return new FieldReferenceMatch(enclosingElement, reference, accuracy, |
| offset, length, isReadAccess, isWriteAccess, insideDocComment, |
| participant, resource); |
| } |
| |
| public SearchMatch newMethodReferenceMatch(IModelElement enclosingElement, |
| int accuracy, int offset, int length, boolean isConstructor, |
| boolean isSynthetic, ASTNode reference) { |
| SearchParticipant participant = getParticipant(); |
| IResource resource = this.currentPossibleMatch.resource; |
| return new MethodReferenceMatch(enclosingElement, accuracy, offset, |
| length, isConstructor, isSynthetic, false, participant, |
| resource, reference); |
| } |
| |
| public TypeReferenceMatch newTypeReferenceMatch( |
| IModelElement enclosingElement, int accuracy, int offset, |
| int length, ASTNode reference) { |
| SearchParticipant participant = getParticipant(); |
| IResource resource = this.currentPossibleMatch.resource; |
| return new TypeReferenceMatch(enclosingElement, accuracy, offset, |
| length, false, participant, resource); |
| } |
| |
| public TypeReferenceMatch newTypeReferenceMatch( |
| IModelElement enclosingElement, int accuracy, ASTNode reference) { |
| return newTypeReferenceMatch(enclosingElement, accuracy, |
| reference.sourceStart(), |
| reference.sourceEnd() - reference.sourceStart() + 1, reference); |
| } |
| |
| /* |
| * Process a compilation unit already parsed and build. |
| */ |
| protected void process(PossibleMatch possibleMatch) throws CoreException { |
| this.currentPossibleMatch = possibleMatch; |
| ModuleDeclaration unit = possibleMatch.parsedUnit; |
| try { |
| if (unit == null || unit.isEmpty()) { |
| return; |
| } |
| reportMatching(unit); |
| } finally { |
| this.currentPossibleMatch = null; |
| } |
| } |
| |
| public SearchParticipant getParticipant() { |
| return this.currentPossibleMatch.document.getParticipant(); |
| } |
| |
| protected void report(SearchMatch match) throws CoreException { |
| long start = -1; |
| if (BasicSearchEngine.VERBOSE) { |
| start = System.currentTimeMillis(); |
| System.out.println("Reporting match"); //$NON-NLS-1$ |
| System.out.println("\tResource: " + match.getResource());//$NON-NLS-1$ |
| System.out.println("\tPositions: [offset=" + match.getOffset() //$NON-NLS-1$ |
| + ", length=" + match.getLength() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ |
| try { |
| ModelElement modelElement = (ModelElement) match.getElement(); |
| System.out.println("\tJava element: " //$NON-NLS-1$ |
| + modelElement.toStringWithAncestors()); |
| if (!modelElement.exists()) |
| System.out.println( |
| "\t\tWARNING: this element does NOT exist!"); //$NON-NLS-1$ |
| } catch (Exception e) { |
| // it's just for debug purposes... ignore all exceptions in this |
| // area |
| } |
| if (match instanceof TypeReferenceMatch) { |
| try { |
| TypeReferenceMatch typeRefMatch = (TypeReferenceMatch) match; |
| ModelElement local = (ModelElement) typeRefMatch |
| .getLocalElement(); |
| if (local != null) { |
| System.out.println("\tLocal element: " //$NON-NLS-1$ |
| + local.toStringWithAncestors()); |
| } |
| IModelElement[] others = typeRefMatch.getOtherElements(); |
| if (others != null) { |
| int length = others.length; |
| if (length > 0) { |
| System.out.println("\tOther elements:"); //$NON-NLS-1$ |
| for (int i = 0; i < length; i++) { |
| ModelElement other = (ModelElement) others[i]; |
| System.out.println("\t\t- " //$NON-NLS-1$ |
| + other.toStringWithAncestors()); |
| } |
| } |
| } |
| } catch (Exception e) { |
| // it's just for debug purposes... ignore all exceptions in |
| // this area |
| } |
| } |
| System.out.println(match.getAccuracy() == SearchMatch.A_ACCURATE |
| ? "\tAccuracy: EXACT_MATCH" //$NON-NLS-1$ |
| : "\tAccuracy: POTENTIAL_MATCH"); //$NON-NLS-1$ |
| System.out.print("\tRule: "); //$NON-NLS-1$ |
| if (match.isExact()) { |
| System.out.println("EXACT"); //$NON-NLS-1$ |
| } else if (match.isEquivalent()) { |
| System.out.println("EQUIVALENT"); //$NON-NLS-1$ |
| } else if (match.isErasure()) { |
| System.out.println("ERASURE"); //$NON-NLS-1$ |
| } else { |
| System.out.println("INVALID RULE"); //$NON-NLS-1$ |
| } |
| System.out.println("\tRaw: " + match.isRaw()); //$NON-NLS-1$ |
| } |
| if (this.requestor != null) { |
| this.requestor.acceptSearchMatch(match); |
| } |
| if (BasicSearchEngine.VERBOSE) |
| this.resultCollectorTime += System.currentTimeMillis() - start; |
| } |
| |
| private void resolvePotentialMatches(MatchingNodeSet nodeSet) { |
| Object[] nodes = nodeSet.possibleMatchingNodesSet.values; |
| for (int i = 0, l = nodes.length; i < l; i++) { |
| ASTNode node = (ASTNode) nodes[i]; |
| if (node != null) { |
| nodeSet.addMatch(node, PatternLocator.ACCURATE_MATCH); |
| /** |
| * FIXME originally it was |
| * |
| * <pre> |
| * nodeSet.addMatch(node, |
| * this.patternLocator.resolveLevel(node)); |
| * </pre> |
| * |
| * but resolveLevel() are not ported |
| */ |
| } |
| } |
| nodeSet.possibleMatchingNodesSet = new SimpleSet(3); |
| if (BasicSearchEngine.VERBOSE) { |
| int size = nodeSet.matchingNodes == null ? 0 |
| : nodeSet.matchingNodes.elementSize; |
| System.out.print(" - node set: accurate=" + size); //$NON-NLS-1$ |
| size = nodeSet.possibleMatchingNodesSet == null ? 0 |
| : nodeSet.possibleMatchingNodesSet.elementSize; |
| System.out.println(", possible=" + size); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * Visit the given resolved parse tree and report the nodes that match the |
| * search pattern. |
| */ |
| protected void reportMatching(ModuleDeclaration unit) throws CoreException { |
| MatchingNodeSet nodeSet = this.currentPossibleMatch.nodeSet; |
| |
| if (BasicSearchEngine.VERBOSE) { |
| System.out.println("Report matching: "); //$NON-NLS-1$ |
| int size = nodeSet.matchingNodes == null ? 0 |
| : nodeSet.matchingNodes.elementSize; |
| System.out.print(" - node set: accurate=" + size); //$NON-NLS-1$ |
| size = nodeSet.possibleMatchingNodesSet == null ? 0 |
| : nodeSet.possibleMatchingNodesSet.elementSize; |
| System.out.println(", possible=" + size); //$NON-NLS-1$ |
| |
| } |
| |
| /* |
| * move the possible matching nodes that exactly match the search |
| * pattern to the matching nodes set |
| */ |
| resolvePotentialMatches(nodeSet); |
| |
| this.unitScope = null; |
| if (nodeSet.matchingNodes.elementSize == 0) |
| return; // no matching nodes were found |
| this.handles = new HashSet(); |
| boolean matchedUnitContainer = (this.matchContainer |
| & PatternLocator.COMPILATION_UNIT_CONTAINER) != 0; |
| // report references in javadoc |
| |
| TypeDeclaration[] types = unit.getTypes(); |
| if (types != null) { |
| for (int i = 0, l = types.length; i < l; i++) { |
| if (nodeSet.matchingNodes.elementSize == 0) |
| return; // reported all the matching nodes |
| TypeDeclaration type = types[i]; |
| Integer level = (Integer) nodeSet.matchingNodes |
| .removeKey(parser.processType(type)); |
| int accuracy = (level != null && matchedUnitContainer) |
| ? level.intValue() |
| : -1; |
| reportMatching(type, null, accuracy, nodeSet, 1); |
| } |
| } |
| // Visit functions |
| MethodDeclaration[] methods = unit.getFunctions(); |
| if (methods != null) { |
| for (int i = 0, l = methods.length; i < l; i++) { |
| if (nodeSet.matchingNodes.elementSize == 0) |
| return; // reported all the matching nodes |
| MethodDeclaration method = methods[i]; |
| Integer level = (Integer) nodeSet.matchingNodes |
| .removeKey(parser.processMethod(method)); |
| int accuracy = (level != null && matchedUnitContainer) |
| ? level.intValue() |
| : -1; |
| reportMatching(unit, method, null, accuracy, nodeSet); |
| } |
| } |
| // Visit global variables |
| FieldDeclaration[] fields = unit.getVariables(); |
| if (fields != null) { |
| for (int i = 0, l = fields.length; i < l; i++) { |
| if (nodeSet.matchingNodes.elementSize == 0) |
| return; // reported all the matching nodes |
| FieldDeclaration method = fields[i]; |
| Integer level = (Integer) nodeSet.matchingNodes |
| .removeKey(method); |
| int accuracy = (level != null && matchedUnitContainer) |
| ? level.intValue() |
| : -1; |
| reportMatching(unit, method, null, accuracy, nodeSet); |
| } |
| } |
| |
| // references in this module |
| ASTNode[] nodes = nodeSet.matchingNodes(unit.sourceStart(), |
| unit.sourceEnd()); |
| if (nodes != null) { |
| if ((this.matchContainer |
| & PatternLocator.COMPILATION_UNIT_CONTAINER) != 0) { |
| ISourceModule enclosingElement = createSourceModuleHandle(); |
| if (encloses(enclosingElement)) { |
| for (int i = 0, l = nodes.length; i < l; i++) { |
| ASTNode node = nodes[i]; |
| Integer level = (Integer) nodeSet.matchingNodes |
| .removeKey(node); |
| if (DLTKCore.DEBUG) { |
| System.out.println( |
| "TODO: Searching. Add scope support."); //$NON-NLS-1$ |
| } |
| this.patternLocator.matchReportReference(node, |
| enclosingElement, (Scope) null, |
| level.intValue(), this); |
| |
| } |
| } |
| } |
| for (int i = 0, l = nodes.length; i < l; i++) |
| nodeSet.matchingNodes.removeKey(nodes[i]); |
| } |
| |
| // Clear handle cache |
| this.handles = null; |
| this.bindings.removeKey(this.pattern); |
| } |
| |
| /** |
| * type Visit the given type declaration and report the nodes that match |
| * exactly the search pattern (ie. the ones in the matching nodes set) |
| */ |
| protected void reportMatching(TypeDeclaration type, IModelElement parent, |
| int accuracy, MatchingNodeSet nodeSet, int occurrenceCount) |
| throws CoreException { |
| // create type handle |
| IModelElement enclosingElement = parent; |
| if (enclosingElement == null) { |
| enclosingElement = createTypeHandle(type.getName()); |
| } else if (enclosingElement instanceof IType) { |
| enclosingElement = createTypeHandle((IType) parent, type.getName()); |
| } else if (enclosingElement instanceof IMember) { |
| IMember member = (IMember) parent; |
| enclosingElement = member.getType(type.getName(), occurrenceCount); |
| } |
| if (enclosingElement == null) |
| return; |
| boolean enclosesElement = encloses(enclosingElement); |
| // report the type declaration |
| if (accuracy > -1 && enclosesElement) { |
| SearchMatch match = this.patternLocator.newDeclarationMatch(type, |
| enclosingElement, accuracy, this); |
| report(match); |
| } |
| boolean matchedClassContainer = (this.matchContainer |
| & PatternLocator.CLASS_CONTAINER) != 0; |
| |
| // filter out element not in hierarchy scope |
| if (DLTKCore.DEBUG) { |
| System.out |
| .println("TODO: Searching. add variable handling here..."); //$NON-NLS-1$ |
| } |
| |
| boolean typeInHierarchy = true;// type.binding == null || |
| |
| // Visit methods |
| MethodDeclaration[] methods = type.getMethods(); |
| if (methods != null) { |
| if (nodeSet.matchingNodes.elementSize == 0) |
| return; // end as all matching nodes were reported |
| for (int i = 0, l = methods.length; i < l; i++) { |
| MethodDeclaration method = methods[i]; |
| Integer level = (Integer) nodeSet.matchingNodes |
| .removeKey(parser.processMethod(method)); |
| int value = (level != null && matchedClassContainer) |
| ? level.intValue() |
| : -1; |
| reportMatching(type, method, enclosingElement, value, true, |
| nodeSet); |
| } |
| } |
| // Visit types |
| TypeDeclaration[] memberTypes = type.getTypes(); |
| if (memberTypes != null) { |
| for (int i = 0, l = memberTypes.length; i < l; i++) { |
| if (nodeSet.matchingNodes.elementSize == 0) |
| return; // end as all matching nodes were reported |
| TypeDeclaration memberType = memberTypes[i]; |
| Integer level = (Integer) nodeSet.matchingNodes |
| .removeKey(parser.processType(memberType)); |
| int value = (level != null && matchedClassContainer) |
| ? level.intValue() |
| : -1; |
| reportMatching(memberType, enclosingElement, value, nodeSet, 1); |
| } |
| } |
| |
| // Visit variables |
| FieldDeclaration[] fields = type.getVariables(); |
| if (fields != null) { |
| for (int i = 0, l = fields.length; i < l; i++) { |
| if (nodeSet.matchingNodes.elementSize == 0) |
| return; // reported all the matching nodes |
| FieldDeclaration field = fields[i]; |
| Integer level = (Integer) nodeSet.matchingNodes |
| .removeKey(field); |
| int value = (level != null && matchedClassContainer) |
| ? level.intValue() |
| : -1; |
| reportMatching(type, field, enclosingElement, value, true, |
| nodeSet); |
| } |
| } |
| |
| // references in this type |
| if (typeInHierarchy) { |
| ASTNode[] nodes = nodeSet.matchingNodes(type.sourceStart(), |
| type.sourceEnd()); |
| if (nodes != null) { |
| if ((this.matchContainer |
| & PatternLocator.METHOD_CONTAINER) != 0) { |
| if (encloses(enclosingElement)) { |
| for (int i = 0, l = nodes.length; i < l; i++) { |
| ASTNode node = nodes[i]; |
| Integer level = (Integer) nodeSet.matchingNodes |
| .removeKey(node); |
| if (DLTKCore.DEBUG) { |
| System.out.println( |
| "TODO: Searching. Add scope support."); //$NON-NLS-1$ |
| } |
| this.patternLocator.matchReportReference(node, |
| enclosingElement, (Scope) null, |
| level.intValue(), this); |
| } |
| return; |
| } |
| } |
| for (int i = 0, l = nodes.length; i < l; i++) |
| nodeSet.matchingNodes.removeKey(nodes[i]); |
| } |
| } |
| } |
| |
| /** |
| * Visit the given method declaration and report the nodes that match |
| * exactly the search pattern (ie. the ones in the matching nodes set) Note |
| * that the method declaration has already been checked. |
| */ |
| protected void reportMatching(TypeDeclaration type, |
| MethodDeclaration method, IModelElement parent, int accuracy, |
| boolean typeInHierarchy, MatchingNodeSet nodeSet) |
| throws CoreException { |
| IModelElement enclosingElement = null; |
| if (accuracy > -1) { |
| enclosingElement = createHandle(method, parent); |
| if (enclosingElement != null) { // skip if unable to find method |
| if (encloses(enclosingElement)) { |
| SearchMatch match = null; |
| if (DLTKCore.DEBUG) { |
| System.out |
| .println("TODO: AST Add constructor support."); //$NON-NLS-1$ |
| } |
| match = this.patternLocator.newDeclarationMatch(method, |
| enclosingElement, accuracy, this); |
| // } |
| if (match != null) { |
| report(match); |
| } |
| } |
| } |
| } |
| |
| // references in this method |
| if (typeInHierarchy) { |
| ASTNode[] nodes = nodeSet.matchingNodes(method.sourceStart(), |
| method.sourceEnd()); |
| if (nodes != null) { |
| if ((this.matchContainer |
| & PatternLocator.CLASS_CONTAINER) != 0) { |
| if (enclosingElement == null) |
| enclosingElement = createHandle(method, parent); |
| if (encloses(enclosingElement)) { |
| for (int i = 0, l = nodes.length; i < l; i++) { |
| ASTNode node = nodes[i]; |
| Integer level = (Integer) nodeSet.matchingNodes |
| .removeKey(node); |
| if (DLTKCore.DEBUG) { |
| System.out.println( |
| "TODO: Searching. Add scope support."); //$NON-NLS-1$ |
| } |
| this.patternLocator.matchReportReference(node, |
| enclosingElement, (Scope) null, |
| level.intValue(), this); |
| } |
| return; |
| } |
| } |
| for (int i = 0, l = nodes.length; i < l; i++) |
| nodeSet.matchingNodes.removeKey(nodes[i]); |
| } |
| } |
| } |
| |
| /** |
| * Visit the given method declaration and report the nodes that match |
| * exactly the search pattern (ie. the ones in the matching nodes set) Note |
| * that the method declaration has already been checked. |
| */ |
| protected void reportMatching(TypeDeclaration type, FieldDeclaration field, |
| IModelElement parent, int accuracy, boolean typeInHierarchy, |
| MatchingNodeSet nodeSet) throws CoreException { |
| IModelElement enclosingElement = null; |
| if (accuracy > -1) { |
| enclosingElement = createHandle(field, parent); |
| if (enclosingElement != null) { // skip if unable to find method |
| if (encloses(enclosingElement)) { |
| SearchMatch match = null; |
| if (DLTKCore.DEBUG) { |
| System.out |
| .println("TODO: AST Add constructor support."); //$NON-NLS-1$ |
| } |
| match = this.patternLocator.newDeclarationMatch(field, |
| enclosingElement, accuracy, this); |
| // } |
| if (match != null) { |
| report(match); |
| } |
| } |
| } |
| } |
| |
| // references in this method |
| if (typeInHierarchy) { |
| ASTNode[] nodes = nodeSet.matchingNodes(field.sourceStart(), |
| field.sourceEnd()); |
| if (nodes != null) { |
| if ((this.matchContainer |
| & PatternLocator.CLASS_CONTAINER) != 0) { |
| if (enclosingElement == null) |
| enclosingElement = createHandle(field, parent); |
| if (encloses(enclosingElement)) { |
| for (int i = 0, l = nodes.length; i < l; i++) { |
| ASTNode node = nodes[i]; |
| Integer level = (Integer) nodeSet.matchingNodes |
| .removeKey(node); |
| if (DLTKCore.DEBUG) { |
| System.out.println( |
| "TODO: Searching. Add scope support."); //$NON-NLS-1$ |
| } |
| this.patternLocator.matchReportReference(node, |
| enclosingElement, (Scope) null, |
| level.intValue(), this); |
| } |
| return; |
| } |
| } |
| for (int i = 0, l = nodes.length; i < l; i++) |
| nodeSet.matchingNodes.removeKey(nodes[i]); |
| } |
| } |
| } |
| |
| /** |
| * Visit the given method declaration and report the nodes that match |
| * exactly the search pattern (ie. the ones in the matching nodes set) Note |
| * that the method declaration has already been checked. |
| */ |
| protected void reportMatching(ModuleDeclaration module, |
| FieldDeclaration field, IModelElement parent, int accuracy, |
| MatchingNodeSet nodeSet) throws CoreException { |
| IModelElement enclosingElement = null; |
| if (accuracy > -1) { |
| if (parent == null) { |
| parent = createSourceModuleHandle(); |
| } |
| enclosingElement = createHandle(field, parent); |
| if (enclosingElement == null) { |
| enclosingElement = createFieldHandle(field.getName()); |
| } |
| if (enclosingElement != null) { // skip if unable to find method |
| if (encloses(enclosingElement)) { |
| SearchMatch match = null; |
| if (DLTKCore.DEBUG) { |
| System.out |
| .println("TODO: AST Add constructor support."); //$NON-NLS-1$ |
| } |
| match = this.patternLocator.newDeclarationMatch(field, |
| enclosingElement, accuracy, this); |
| // } |
| if (match != null) { |
| report(match); |
| } |
| } |
| } |
| } |
| |
| // references in this method |
| ASTNode[] nodes = nodeSet.matchingNodes(field.sourceStart(), |
| field.sourceEnd()); |
| if (nodes != null) { |
| if (parent == null) { |
| parent = createSourceModuleHandle(); |
| } |
| if ((this.matchContainer & PatternLocator.METHOD_CONTAINER) != 0) { |
| if (enclosingElement == null) |
| enclosingElement = createHandle(field, parent); |
| if (encloses(enclosingElement)) { |
| for (int i = 0, l = nodes.length; i < l; i++) { |
| ASTNode node = nodes[i]; |
| Integer level = (Integer) nodeSet.matchingNodes |
| .removeKey(node); |
| if (DLTKCore.DEBUG) { |
| System.out.println( |
| "TODO: Searching. Add scope support."); //$NON-NLS-1$ |
| } |
| this.patternLocator.matchReportReference(node, |
| enclosingElement, (Scope) null, |
| level.intValue(), this); |
| } |
| return; |
| } |
| } |
| for (int i = 0, l = nodes.length; i < l; i++) |
| nodeSet.matchingNodes.removeKey(nodes[i]); |
| } |
| } |
| |
| protected void reportMatching(ModuleDeclaration module, |
| MethodDeclaration method, IModelElement parent, int accuracy, |
| MatchingNodeSet nodeSet) throws CoreException { |
| IModelElement enclosingElement = null; |
| if (accuracy > -1) { |
| if (parent == null) { |
| parent = createSourceModuleHandle(); |
| } |
| enclosingElement = createHandle(method, parent); |
| if (enclosingElement == null) { |
| enclosingElement = createMethodHandle(method.getName()); |
| } |
| if (enclosingElement != null) { // skip if unable to find method |
| if (encloses(enclosingElement)) { |
| SearchMatch match = null; |
| if (DLTKCore.DEBUG) { |
| System.out |
| .println("TODO: AST Add constructor support."); //$NON-NLS-1$ |
| } |
| match = this.patternLocator.newDeclarationMatch(method, |
| enclosingElement, accuracy, this); |
| // } |
| if (match != null) { |
| report(match); |
| } |
| } |
| } |
| } |
| |
| // references in this method |
| ASTNode[] nodes = nodeSet.matchingNodes(method.sourceStart(), |
| method.sourceEnd()); |
| if (nodes != null) { |
| if (parent == null) { |
| parent = createSourceModuleHandle(); |
| } |
| if ((this.matchContainer & PatternLocator.METHOD_CONTAINER) != 0) { |
| if (enclosingElement == null) |
| enclosingElement = createHandle(method, parent); |
| if (encloses(enclosingElement)) { |
| for (int i = 0, l = nodes.length; i < l; i++) { |
| ASTNode node = nodes[i]; |
| Integer level = (Integer) nodeSet.matchingNodes |
| .removeKey(node); |
| if (DLTKCore.DEBUG) { |
| System.out.println( |
| "TODO: Searching. Add scope support."); //$NON-NLS-1$ |
| } |
| this.patternLocator.matchReportReference(node, |
| enclosingElement, (Scope) null, |
| level.intValue(), this); |
| } |
| return; |
| } |
| } |
| for (int i = 0, l = nodes.length; i < l; i++) |
| nodeSet.matchingNodes.removeKey(nodes[i]); |
| } |
| } |
| |
| protected IType findTypeFrom(IModelElement[] childs, String name, |
| String parentName, char delimiter) { |
| try { |
| for (int i = 0; i < childs.length; ++i) { |
| if (childs[i] instanceof IType) { |
| IType type = (IType) childs[i]; |
| String qname = name + delimiter + type.getElementName(); |
| if (qname.equals(parentName)) { |
| return type; |
| } |
| IType val = findTypeFrom(type.getChildren(), qname, |
| parentName, delimiter); |
| if (val != null) { |
| return val; |
| } |
| } |
| } |
| } catch (ModelException e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| } |
| return null; |
| } |
| |
| } |