/******************************************************************************* * Copyright (c) 2009, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Zend Technologies *******************************************************************************/ package org.eclipse.dltk.core.index2.search; import java.util.Collection; import java.util.LinkedList; import java.util.List; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.dltk.core.DLTKLanguageManager; import org.eclipse.dltk.core.IDLTKLanguageToolkit; import org.eclipse.dltk.core.IField; import org.eclipse.dltk.core.IMethod; import org.eclipse.dltk.core.IModelElement; import org.eclipse.dltk.core.ISearchPatternProcessor; import org.eclipse.dltk.core.ISourceModule; import org.eclipse.dltk.core.IType; import org.eclipse.dltk.core.index2.IElementResolver; import org.eclipse.dltk.core.index2.IIndexer; import org.eclipse.dltk.core.index2.IIndexerParticipant; import org.eclipse.dltk.core.index2.search.ISearchEngine.MatchRule; import org.eclipse.dltk.core.index2.search.ISearchEngine.SearchFor; import org.eclipse.dltk.core.search.IDLTKSearchScope; import org.eclipse.dltk.core.search.SearchPattern; import org.eclipse.dltk.internal.core.index2.IndexerManager; /** * Utility for accessing DLTK model elements through index * * @author michael * @since 2.0 * */ public class ModelAccess { /** * Finds field elements in index. Element qualifier (package name) will be * calculated from the field name. * * @param name * Element name * @param matchRule * Match rule * @param trueFlags * Logical OR of flags that must exist in element flags bitset. * Set to <code>0</code> to disable filtering by trueFlags. * @param falseFlags * Logical OR of flags that must not exist in the element flags * bitset. Set to <code>0</code> to disable filtering by * falseFlags. * @param scope * Search scope * @param monitor * Progress monitor * @return elements array, or <code>null</code> in case error has occurred. */ public IField[] findFields(String name, MatchRule matchRule, int trueFlags, int falseFlags, IDLTKSearchScope scope, IProgressMonitor monitor) { List<IField> result = new LinkedList<>(); if (!findElements(IModelElement.FIELD, name, matchRule, trueFlags, falseFlags, scope, result, monitor)) { return null; } return result.toArray(new IField[result.size()]); } /** * Finds field elements in index * * @param qualifier * Element qualifier (package name) * @param name * Element name * @param matchRule * Match rule * @param trueFlags * Logical OR of flags that must exist in element flags bitset. * Set to <code>0</code> to disable filtering by trueFlags. * @param falseFlags * Logical OR of flags that must not exist in the element flags * bitset. Set to <code>0</code> to disable filtering by * falseFlags. * @param scope * Search scope * @param monitor * Progress monitor * @return elements array, or <code>null</code> in case error has occurred. */ public IField[] findFields(String qualifier, String name, MatchRule matchRule, int trueFlags, int falseFlags, IDLTKSearchScope scope, IProgressMonitor monitor) { List<IField> result = new LinkedList<>(); if (!findElements(IModelElement.FIELD, qualifier, name, matchRule, trueFlags, falseFlags, scope, result, monitor)) { return null; } return result.toArray(new IField[result.size()]); } /** * Finds method elements in index.Element qualifier (package name) will be * calculated from the method name. * * @param name * Element name * @param matchRule * Match rule * @param trueFlags * Logical OR of flags that must exist in element flags bitset. * Set to <code>0</code> to disable filtering by trueFlags. * @param falseFlags * Logical OR of flags that must not exist in the element flags * bitset. Set to <code>0</code> to disable filtering by * falseFlags. * @param scope * Search scope * @param monitor * Progress monitor * @return elements array, or <code>null</code> in case error has occurred. */ public IMethod[] findMethods(String name, MatchRule matchRule, int trueFlags, int falseFlags, IDLTKSearchScope scope, IProgressMonitor monitor) { List<IMethod> result = new LinkedList<>(); if (!findElements(IModelElement.METHOD, name, matchRule, trueFlags, falseFlags, scope, result, monitor)) { return null; } return result.toArray(new IMethod[result.size()]); } /** * Finds method elements in index * * @param qualifier * Element qualifier (package name) * @param name * Element name * @param matchRule * Match rule * @param trueFlags * Logical OR of flags that must exist in element flags bitset. * Set to <code>0</code> to disable filtering by trueFlags. * @param falseFlags * Logical OR of flags that must not exist in the element flags * bitset. Set to <code>0</code> to disable filtering by * falseFlags. * @param scope * Search scope * @param monitor * Progress monitor * @return elements array, or <code>null</code> in case error has occurred. */ public IMethod[] findMethods(String qualifier, String name, MatchRule matchRule, int trueFlags, int falseFlags, IDLTKSearchScope scope, IProgressMonitor monitor) { List<IMethod> result = new LinkedList<>(); if (!findElements(IModelElement.METHOD, qualifier, name, matchRule, trueFlags, falseFlags, scope, result, monitor)) { return null; } return result.toArray(new IMethod[result.size()]); } /** * Finds type elements in index. Element qualifier (package name) will be * calculated from the type name. * * @param name * Element name * @param matchRule * Match rule * @param trueFlags * Logical OR of flags that must exist in element flags bitset. * Set to <code>0</code> to disable filtering by trueFlags. * @param falseFlags * Logical OR of flags that must not exist in the element flags * bitset. Set to <code>0</code> to disable filtering by * falseFlags. * @param scope * Search scope * @param monitor * Progress monitor * @return elements array, or <code>null</code> in case error has occurred. */ public IType[] findTypes(String name, MatchRule matchRule, int trueFlags, int falseFlags, IDLTKSearchScope scope, IProgressMonitor monitor) { List<IType> result = new LinkedList<>(); if (!findElements(IModelElement.TYPE, name, matchRule, trueFlags, falseFlags, scope, result, monitor)) { return null; } return result.toArray(new IType[result.size()]); } /** * Finds type elements in index. * * @param qualifier * Element qualifier (package name) * @param name * Element name * @param matchRule * Match rule * @param trueFlags * Logical OR of flags that must exist in element flags bitset. * Set to <code>0</code> to disable filtering by trueFlags. * @param falseFlags * Logical OR of flags that must not exist in the element flags * bitset. Set to <code>0</code> to disable filtering by * falseFlags. * @param scope * Search scope * @param monitor * Progress monitor * @return elements array, or <code>null</code> in case error has occurred. */ public IType[] findTypes(String qualifier, String name, MatchRule matchRule, int trueFlags, int falseFlags, IDLTKSearchScope scope, IProgressMonitor monitor) { List<IType> result = new LinkedList<>(); if (!findElements(IModelElement.TYPE, qualifier, name, matchRule, trueFlags, falseFlags, scope, result, monitor)) { return null; } return result.toArray(new IType[result.size()]); } protected <T extends IModelElement> boolean findElements(int elementType, String name, MatchRule matchRule, int trueFlags, int falseFlags, IDLTKSearchScope scope, final Collection<T> result, IProgressMonitor monitor) { String qualifier = null; if (name != null) { ISearchPatternProcessor processor = DLTKLanguageManager .getSearchPatternProcessor(scope.getLanguageToolkit()); if (processor != null) { String delim = processor.getDelimiterReplacementString(); int i = name.lastIndexOf(delim); if (i != -1) { qualifier = name.substring(0, i); name = name.substring(i + 1); } } } return findElements(elementType, qualifier, name, matchRule, trueFlags, falseFlags, scope, result, monitor); } protected <T extends IModelElement> boolean findElements(int elementType, String qualifier, String name, MatchRule matchRule, int trueFlags, int falseFlags, IDLTKSearchScope scope, final Collection<T> result, IProgressMonitor monitor) { return findElements(elementType, qualifier, name, null, matchRule, trueFlags, falseFlags, scope, result, monitor); } protected <T extends IModelElement> boolean findElements(int elementType, String qualifier, String name, String parent, MatchRule matchRule, int trueFlags, int falseFlags, IDLTKSearchScope scope, final Collection<T> result, IProgressMonitor monitor) { IDLTKLanguageToolkit toolkit = scope.getLanguageToolkit(); if (toolkit == null) { return false; } final IElementResolver elementResolver = getElementResolver(toolkit); if (elementResolver == null) { return false; } ISearchEngine searchEngine = getSearchEngine(toolkit); if (searchEngine == null) { return false; } ISearchRequestor requestor = new ISearchRequestor() { @Override @SuppressWarnings("unchecked") public void match(int elementType, int flags, int offset, int length, int nameOffset, int nameLength, String elementName, String metadata, String doc, String qualifier, String parent, ISourceModule sourceModule, boolean isReference) { IModelElement element = elementResolver.resolve(elementType, flags, offset, length, nameOffset, nameLength, elementName, metadata, doc, qualifier, parent, sourceModule); if (element != null) { result.add((T) element); } } }; if (searchEngine instanceof ISearchEngineExtension) { ((ISearchEngineExtension) searchEngine).search(elementType, qualifier, name, parent, trueFlags, falseFlags, 0, SearchFor.DECLARATIONS, matchRule, scope, requestor, monitor); } else { searchEngine.search(elementType, qualifier, name, trueFlags, falseFlags, 0, SearchFor.DECLARATIONS, matchRule, scope, requestor, monitor); } return true; } /** * Converts old-style search flags to MatchRule. * * @param searchRule * Search flags: {@link SearchPattern#R_EXACT_MATCH}, etc... * @return match rule. If searchRule is not supported by the new mechanism * {@link MatchRule#EXACT} is returned. */ public static MatchRule convertSearchRule(int searchRule) { MatchRule matchRule; if ((searchRule & SearchPattern.R_PREFIX_MATCH) != 0) { matchRule = MatchRule.PREFIX; } else if ((searchRule & SearchPattern.R_CAMELCASE_MATCH) != 0) { matchRule = MatchRule.CAMEL_CASE; } else if ((searchRule & SearchPattern.R_PATTERN_MATCH) != 0) { matchRule = MatchRule.PATTERN; } else { matchRule = MatchRule.EXACT; } return matchRule; } /** * Creates search participant * * @param toolkit * Language toolkit * @return indexer participant instance or <code>null</code> in case new * indexing infrastructure is not initiated */ public static IIndexerParticipant getIndexerParticipant( IDLTKLanguageToolkit toolkit) { if (toolkit == null) { return null; } IIndexer indexer = IndexerManager.getIndexer(); if (indexer == null) { return null; } return IndexerManager.getIndexerParticipant(indexer, toolkit.getNatureId()); } /** * Creates new search engine instance * * @param toolkit * Language toolkit * @return search engine instance or <code>null</code> in case new indexing * infrastructure is not initiated */ public static ISearchEngine getSearchEngine(IDLTKLanguageToolkit toolkit) { if (toolkit != null) { IIndexer indexer = IndexerManager.getIndexer(); if (indexer != null) { return indexer.createSearchEngine(); } } return null; } /** * Creates element resolver * * @param toolkit * Language toolkit * @return element resolver or <code>null</code> in case new indexing * infrastructure is not initiated */ public static IElementResolver getElementResolver( IDLTKLanguageToolkit toolkit) { if (toolkit != null) { IIndexerParticipant participant = getIndexerParticipant(toolkit); if (participant != null) { return participant.getElementResolver(); } } return null; } }