blob: 9a9a2537797bf686c09c3481c88a8c945f51ffad [file] [log] [blame]
/*
* Copyright (c) 2013, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.engine.internal.search;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.dart.engine.element.ClassElement;
import com.google.dart.engine.element.CompilationUnitElement;
import com.google.dart.engine.element.ConstructorElement;
import com.google.dart.engine.element.Element;
import com.google.dart.engine.element.FunctionElement;
import com.google.dart.engine.element.FunctionTypeAliasElement;
import com.google.dart.engine.element.ImportElement;
import com.google.dart.engine.element.LibraryElement;
import com.google.dart.engine.element.LocalVariableElement;
import com.google.dart.engine.element.MethodElement;
import com.google.dart.engine.element.ParameterElement;
import com.google.dart.engine.element.PropertyAccessorElement;
import com.google.dart.engine.element.PropertyInducingElement;
import com.google.dart.engine.element.TypeParameterElement;
import com.google.dart.engine.element.VariableElement;
import com.google.dart.engine.element.angular.AngularElement;
import com.google.dart.engine.index.Index;
import com.google.dart.engine.index.Location;
import com.google.dart.engine.index.LocationWithData;
import com.google.dart.engine.index.Relationship;
import com.google.dart.engine.index.RelationshipCallback;
import com.google.dart.engine.internal.element.member.Member;
import com.google.dart.engine.internal.index.IndexConstants;
import com.google.dart.engine.internal.index.NameElementImpl;
import com.google.dart.engine.internal.search.listener.CountingSearchListener;
import com.google.dart.engine.internal.search.listener.FilteredSearchListener;
import com.google.dart.engine.internal.search.listener.GatheringSearchListener;
import com.google.dart.engine.internal.search.listener.NameMatchingSearchListener;
import com.google.dart.engine.internal.search.scope.LibrarySearchScope;
import com.google.dart.engine.search.MatchKind;
import com.google.dart.engine.search.MatchQuality;
import com.google.dart.engine.search.SearchEngine;
import com.google.dart.engine.search.SearchFilter;
import com.google.dart.engine.search.SearchListener;
import com.google.dart.engine.search.SearchMatch;
import com.google.dart.engine.search.SearchPattern;
import com.google.dart.engine.search.SearchScope;
import com.google.dart.engine.type.Type;
import com.google.dart.engine.utilities.source.SourceRange;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
/**
* Implementation of {@link SearchEngine}.
*
* @coverage dart.engine.search
*/
public class SearchEngineImpl implements SearchEngine {
/**
* Instances of the class <code>RelationshipCallbackImpl</code> implement a callback that can be
* used to report results to a search listener.
*/
private static class RelationshipCallbackImpl implements RelationshipCallback {
private final SearchScope scope;
/**
* The kind of matches that are represented by the results that will be provided to this
* callback.
*/
private MatchKind matchKind;
/**
* The search listener that should be notified when results are found.
*/
private SearchListener listener;
/**
* Initialize a newly created callback to report matches of the given kind to the given listener
* when results are found.
*
* @param scope the {@link SearchScope} to return matches from, may be {@code null} to return
* all matches
* @param matchKind the kind of matches that are represented by the results
* @param listener the search listener that should be notified when results are found
*/
public RelationshipCallbackImpl(SearchScope scope, MatchKind matchKind, SearchListener listener) {
this.scope = scope;
this.matchKind = matchKind;
this.listener = listener;
}
@Override
public void hasRelationships(Element element, Relationship relationship, Location[] locations) {
for (Location location : locations) {
Element targetElement = location.getElement();
// check scope
if (scope != null && !scope.encloses(targetElement)) {
continue;
}
SourceRange range = new SourceRange(location.getOffset(), location.getLength());
// TODO(scheglov) IndexConstants.DYNAMIC for MatchQuality.NAME
MatchQuality quality = MatchQuality.EXACT;
// MatchQuality quality = element.getResource() != IndexConstants.DYNAMIC
// ? MatchQuality.EXACT : MatchQuality.NAME;
SearchMatch match = new SearchMatch(quality, matchKind, targetElement, range);
match.setQualified(relationship == IndexConstants.IS_REFERENCED_BY_QUALIFIED
|| relationship == IndexConstants.IS_INVOKED_BY_QUALIFIED);
listener.matchFound(match);
}
listener.searchComplete();
}
}
/**
* The interface <code>SearchRunner</code> defines the behavior of objects that can be used to
* perform an asynchronous search.
*/
private interface SearchRunner {
/**
* Perform an asynchronous search, passing the results to the given listener.
*
* @param listener the listener to which search results should be passed @ if the results could
* not be computed
*/
public void performSearch(SearchListener listener);
}
/**
* Apply the given filter to the given listener.
*
* @param filter the filter to be used before passing matches on to the listener, or {@code null}
* if all matches should be passed on
* @param listener the listener that will only be given matches that pass the filter
* @return a search listener that will pass to the given listener any matches that pass the given
* filter
*/
private static SearchListener applyFilter(SearchFilter filter, SearchListener listener) {
if (filter == null) {
return listener;
}
return new FilteredSearchListener(filter, listener);
}
/**
* Apply the given pattern to the given listener.
*
* @param pattern the pattern to be used before passing matches on to the listener, or
* {@code null} if all matches should be passed on
* @param listener the listener that will only be given matches that match the pattern
* @return a search listener that will pass to the given listener any matches that match the given
* pattern
*/
private static SearchListener applyPattern(SearchPattern pattern, SearchListener listener) {
if (pattern == null) {
return listener;
}
return new NameMatchingSearchListener(pattern, listener);
}
private static Element[] createElements(SearchScope scope) {
if (scope instanceof LibrarySearchScope) {
return ((LibrarySearchScope) scope).getLibraries();
}
return new Element[] {IndexConstants.UNIVERSE};
}
private static RelationshipCallback newCallback(MatchKind matchKind, SearchScope scope,
SearchListener listener) {
return new RelationshipCallbackImpl(scope, matchKind, listener);
}
/**
* The index used to respond to the search requests.
*/
private Index index;
/**
* Initialize a newly created search engine to use the given index.
*
* @param index the index used to respond to the search requests
*/
public SearchEngineImpl(Index index) {
this.index = index;
}
@Override
public Set<Type> searchAssignedTypes(PropertyInducingElement variable, SearchScope scope) {
PropertyAccessorElement setter = variable.getSetter();
int numRequests = (setter != null ? 2 : 0) + 2;
// find locations
final List<Location> locations = Lists.newArrayList();
final CountDownLatch latch = new CountDownLatch(numRequests);
class Callback implements RelationshipCallback {
@Override
public void hasRelationships(Element element, Relationship relationship, Location[] locs) {
Collections.addAll(locations, locs);
latch.countDown();
}
}
if (setter != null) {
index.getRelationships(setter, IndexConstants.IS_REFERENCED_BY_QUALIFIED, new Callback());
index.getRelationships(setter, IndexConstants.IS_REFERENCED_BY_UNQUALIFIED, new Callback());
}
index.getRelationships(variable, IndexConstants.IS_REFERENCED_BY, new Callback());
index.getRelationships(variable, IndexConstants.IS_DEFINED_BY, new Callback());
Uninterruptibles.awaitUninterruptibly(latch);
// get types from locations
Set<Type> types = Sets.newHashSet();
for (Location location : locations) {
// check scope
if (scope != null) {
Element targetElement = location.getElement();
if (!scope.encloses(targetElement)) {
continue;
}
}
// we need data
if (!(location instanceof LocationWithData<?>)) {
continue;
}
LocationWithData<?> locationWithData = (LocationWithData<?>) location;
// add type
Object data = locationWithData.getData();
if (data instanceof Type) {
Type type = (Type) data;
types.add(type);
}
}
// done
return types;
}
@Override
public List<SearchMatch> searchDeclarations(final String name, final SearchScope scope,
final SearchFilter filter) {
return gatherResults(new SearchRunner() {
@Override
public void performSearch(SearchListener listener) {
searchDeclarations(name, scope, filter, listener);
}
});
}
@Override
public void searchDeclarations(String name, SearchScope scope, SearchFilter filter,
SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
index.getRelationships(
new NameElementImpl(name),
IndexConstants.IS_DEFINED_BY,
newCallback(MatchKind.NAME_DECLARATION, scope, listener));
}
@Override
public List<SearchMatch> searchFunctionDeclarations(final SearchScope scope,
final SearchPattern pattern, final SearchFilter filter) {
return gatherResults(new SearchRunner() {
@Override
public void performSearch(SearchListener listener) {
searchFunctionDeclarations(scope, pattern, filter, listener);
}
});
}
@Override
public void searchFunctionDeclarations(SearchScope scope, SearchPattern pattern,
SearchFilter filter, SearchListener listener) {
assert listener != null;
Element[] elements = createElements(scope);
listener = applyPattern(pattern, listener);
listener = applyFilter(filter, listener);
listener = new CountingSearchListener(elements.length, listener);
for (Element element : elements) {
index.getRelationships(
element,
IndexConstants.DEFINES_FUNCTION,
newCallback(MatchKind.FUNCTION_DECLARATION, scope, listener));
}
}
@Override
public List<SearchMatch> searchQualifiedMemberReferences(final String name,
final SearchScope scope, final SearchFilter filter) {
return gatherResults(new SearchRunner() {
@Override
public void performSearch(SearchListener listener) {
searchQualifiedMemberReferences(name, scope, filter, listener);
}
});
}
@Override
public void searchQualifiedMemberReferences(String name, SearchScope scope, SearchFilter filter,
SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
listener = new CountingSearchListener(10, listener);
index.getRelationships(
new NameElementImpl(name),
IndexConstants.IS_REFERENCED_BY_QUALIFIED_RESOLVED,
newCallback(MatchKind.NAME_REFERENCE_RESOLVED, scope, listener));
index.getRelationships(
new NameElementImpl(name),
IndexConstants.IS_REFERENCED_BY_QUALIFIED_UNRESOLVED,
newCallback(MatchKind.NAME_REFERENCE_UNRESOLVED, scope, listener));
// granular resolved operations
index.getRelationships(
new NameElementImpl(name),
IndexConstants.NAME_IS_INVOKED_BY_RESOLVED,
newCallback(MatchKind.NAME_INVOCATION_RESOLVED, scope, listener));
index.getRelationships(
new NameElementImpl(name),
IndexConstants.NAME_IS_READ_BY_RESOLVED,
newCallback(MatchKind.NAME_READ_RESOLVED, scope, listener));
index.getRelationships(
new NameElementImpl(name),
IndexConstants.NAME_IS_READ_WRITTEN_BY_RESOLVED,
newCallback(MatchKind.NAME_READ_WRITE_RESOLVED, scope, listener));
index.getRelationships(
new NameElementImpl(name),
IndexConstants.NAME_IS_WRITTEN_BY_RESOLVED,
newCallback(MatchKind.NAME_WRITE_RESOLVED, scope, listener));
// granular unresolved operations
index.getRelationships(
new NameElementImpl(name),
IndexConstants.NAME_IS_INVOKED_BY_UNRESOLVED,
newCallback(MatchKind.NAME_INVOCATION_UNRESOLVED, scope, listener));
index.getRelationships(
new NameElementImpl(name),
IndexConstants.NAME_IS_READ_BY_UNRESOLVED,
newCallback(MatchKind.NAME_READ_UNRESOLVED, scope, listener));
index.getRelationships(
new NameElementImpl(name),
IndexConstants.NAME_IS_READ_WRITTEN_BY_UNRESOLVED,
newCallback(MatchKind.NAME_READ_WRITE_UNRESOLVED, scope, listener));
index.getRelationships(
new NameElementImpl(name),
IndexConstants.NAME_IS_WRITTEN_BY_UNRESOLVED,
newCallback(MatchKind.NAME_WRITE_UNRESOLVED, scope, listener));
}
@Override
public List<SearchMatch> searchReferences(final Element element, final SearchScope scope,
final SearchFilter filter) {
return gatherResults(new SearchRunner() {
@Override
public void performSearch(SearchListener listener) {
searchReferences(element, scope, filter, listener);
}
});
}
@Override
public void searchReferences(Element element, SearchScope scope, SearchFilter filter,
SearchListener listener) {
if (element == null) {
listener.searchComplete();
return;
}
if (element instanceof Member) {
element = ((Member) element).getBaseElement();
}
switch (element.getKind()) {
case ANGULAR_COMPONENT:
case ANGULAR_CONTROLLER:
case ANGULAR_FORMATTER:
case ANGULAR_PROPERTY:
case ANGULAR_SCOPE_PROPERTY:
case ANGULAR_SELECTOR:
searchReferences((AngularElement) element, scope, filter, listener);
return;
case CLASS:
searchReferences((ClassElement) element, scope, filter, listener);
return;
case COMPILATION_UNIT:
searchReferences((CompilationUnitElement) element, scope, filter, listener);
return;
case CONSTRUCTOR:
searchReferences((ConstructorElement) element, scope, filter, listener);
return;
case FIELD:
case TOP_LEVEL_VARIABLE:
searchReferences((PropertyInducingElement) element, scope, filter, listener);
return;
case FUNCTION:
searchReferences((FunctionElement) element, scope, filter, listener);
return;
case GETTER:
case SETTER:
searchReferences((PropertyAccessorElement) element, scope, filter, listener);
return;
case IMPORT:
searchReferences((ImportElement) element, scope, filter, listener);
return;
case LIBRARY:
searchReferences((LibraryElement) element, scope, filter, listener);
return;
case LOCAL_VARIABLE:
searchReferences((LocalVariableElement) element, scope, filter, listener);
return;
case METHOD:
searchReferences((MethodElement) element, scope, filter, listener);
return;
case PARAMETER:
searchReferences((ParameterElement) element, scope, filter, listener);
return;
case FUNCTION_TYPE_ALIAS:
searchReferences((FunctionTypeAliasElement) element, scope, filter, listener);
return;
case TYPE_PARAMETER:
searchReferences((TypeParameterElement) element, scope, filter, listener);
return;
default:
listener.searchComplete();
return;
}
}
@Override
public List<SearchMatch> searchSubtypes(final ClassElement type, final SearchScope scope,
final SearchFilter filter) {
return gatherResults(new SearchRunner() {
@Override
public void performSearch(SearchListener listener) {
searchSubtypes(type, scope, filter, listener);
}
});
}
@Override
public void searchSubtypes(ClassElement type, SearchScope scope, SearchFilter filter,
SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
listener = new CountingSearchListener(3, listener);
index.getRelationships(
type,
IndexConstants.IS_EXTENDED_BY,
newCallback(MatchKind.EXTENDS_REFERENCE, scope, listener));
index.getRelationships(
type,
IndexConstants.IS_MIXED_IN_BY,
newCallback(MatchKind.WITH_REFERENCE, scope, listener));
index.getRelationships(
type,
IndexConstants.IS_IMPLEMENTED_BY,
newCallback(MatchKind.IMPLEMENTS_REFERENCE, scope, listener));
}
@Override
public List<SearchMatch> searchTypeDeclarations(final SearchScope scope,
final SearchPattern pattern, final SearchFilter filter) {
return gatherResults(new SearchRunner() {
@Override
public void performSearch(SearchListener listener) {
searchTypeDeclarations(scope, pattern, filter, listener);
}
});
}
@Override
public void searchTypeDeclarations(SearchScope scope, SearchPattern pattern, SearchFilter filter,
SearchListener listener) {
assert listener != null;
Element[] elements = createElements(scope);
listener = applyPattern(pattern, listener);
listener = applyFilter(filter, listener);
listener = new CountingSearchListener(elements.length * 3, listener);
for (Element element : elements) {
index.getRelationships(
element,
IndexConstants.DEFINES_CLASS,
newCallback(MatchKind.CLASS_DECLARATION, scope, listener));
index.getRelationships(
element,
IndexConstants.DEFINES_CLASS_ALIAS,
newCallback(MatchKind.CLASS_ALIAS_DECLARATION, scope, listener));
index.getRelationships(
element,
IndexConstants.DEFINES_FUNCTION_TYPE,
newCallback(MatchKind.FUNCTION_TYPE_DECLARATION, scope, listener));
}
}
@Override
public List<SearchMatch> searchVariableDeclarations(final SearchScope scope,
final SearchPattern pattern, final SearchFilter filter) {
return gatherResults(new SearchRunner() {
@Override
public void performSearch(SearchListener listener) {
searchVariableDeclarations(scope, pattern, filter, listener);
}
});
}
@Override
public void searchVariableDeclarations(SearchScope scope, SearchPattern pattern,
SearchFilter filter, SearchListener listener) {
assert listener != null;
Element[] elements = createElements(scope);
listener = applyPattern(pattern, listener);
listener = applyFilter(filter, listener);
listener = new CountingSearchListener(elements.length, listener);
for (Element element : elements) {
index.getRelationships(
element,
IndexConstants.DEFINES_VARIABLE,
newCallback(MatchKind.VARIABLE_DECLARATION, scope, listener));
}
}
/**
* Use the given runner to perform the given number of asynchronous searches, then wait until the
* search has completed and return the results that were produced.
*
* @param runner the runner used to perform an asynchronous search
* @return the results that were produced @ if the results of at least one of the searched could
* not be computed
*/
private List<SearchMatch> gatherResults(SearchRunner runner) {
GatheringSearchListener listener = new GatheringSearchListener();
runner.performSearch(listener);
while (!listener.isComplete()) {
Thread.yield();
}
return listener.getMatches();
}
private void searchReferences(AngularElement element, SearchScope scope, SearchFilter filter,
SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
listener = new CountingSearchListener(2, listener);
index.getRelationships(
element,
IndexConstants.ANGULAR_REFERENCE,
newCallback(MatchKind.ANGULAR_REFERENCE, scope, listener));
index.getRelationships(
element,
IndexConstants.ANGULAR_CLOSING_TAG_REFERENCE,
newCallback(MatchKind.ANGULAR_CLOSING_TAG_REFERENCE, scope, listener));
}
private void searchReferences(ClassElement type, SearchScope scope, SearchFilter filter,
SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
index.getRelationships(
type,
IndexConstants.IS_REFERENCED_BY,
newCallback(MatchKind.TYPE_REFERENCE, scope, listener));
}
private void searchReferences(CompilationUnitElement unit, SearchScope scope,
SearchFilter filter, SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
index.getRelationships(
unit,
IndexConstants.IS_REFERENCED_BY,
newCallback(MatchKind.UNIT_REFERENCE, scope, listener));
}
private void searchReferences(ConstructorElement constructor, SearchScope scope,
SearchFilter filter, SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
listener = new CountingSearchListener(2, listener);
index.getRelationships(
constructor,
IndexConstants.IS_DEFINED_BY,
newCallback(MatchKind.CONSTRUCTOR_DECLARATION, scope, listener));
index.getRelationships(
constructor,
IndexConstants.IS_REFERENCED_BY,
newCallback(MatchKind.CONSTRUCTOR_REFERENCE, scope, listener));
}
private void searchReferences(FunctionElement function, SearchScope scope, SearchFilter filter,
SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
listener = new CountingSearchListener(2, listener);
index.getRelationships(
function,
IndexConstants.IS_REFERENCED_BY,
newCallback(MatchKind.FUNCTION_REFERENCE, scope, listener));
index.getRelationships(
function,
IndexConstants.IS_INVOKED_BY,
newCallback(MatchKind.FUNCTION_EXECUTION, scope, listener));
}
private void searchReferences(FunctionTypeAliasElement alias, SearchScope scope,
SearchFilter filter, SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
index.getRelationships(
alias,
IndexConstants.IS_REFERENCED_BY,
newCallback(MatchKind.FUNCTION_TYPE_REFERENCE, scope, listener));
}
private void searchReferences(ImportElement imp, SearchScope scope, SearchFilter filter,
SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
index.getRelationships(
imp,
IndexConstants.IS_REFERENCED_BY,
newCallback(MatchKind.IMPORT_REFERENCE, scope, listener));
}
private void searchReferences(LibraryElement library, SearchScope scope, SearchFilter filter,
SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
index.getRelationships(
library,
IndexConstants.IS_REFERENCED_BY,
newCallback(MatchKind.LIBRARY_REFERENCE, scope, listener));
}
private void searchReferences(MethodElement method, SearchScope scope, SearchFilter filter,
SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
// TODO(scheglov) use "5" when add named matches
listener = new CountingSearchListener(4, listener);
// exact matches
index.getRelationships(
method,
IndexConstants.IS_INVOKED_BY_UNQUALIFIED,
newCallback(MatchKind.METHOD_INVOCATION, scope, listener));
index.getRelationships(
method,
IndexConstants.IS_INVOKED_BY_QUALIFIED,
newCallback(MatchKind.METHOD_INVOCATION, scope, listener));
index.getRelationships(
method,
IndexConstants.IS_REFERENCED_BY_UNQUALIFIED,
newCallback(MatchKind.METHOD_REFERENCE, scope, listener));
index.getRelationships(
method,
IndexConstants.IS_REFERENCED_BY_QUALIFIED,
newCallback(MatchKind.METHOD_REFERENCE, scope, listener));
// TODO(scheglov)
// inexact matches
// index.getRelationships(
// new Element(IndexConstants.DYNAMIC, method.getElementName()),
// IndexConstants.IS_INVOKED_BY_QUALIFIED,
// newCallback(MatchKind.METHOD_INVOCATION, listener));
}
private void searchReferences(ParameterElement parameter, SearchScope scope, SearchFilter filter,
SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
listener = new CountingSearchListener(5, listener);
index.getRelationships(
parameter,
IndexConstants.IS_READ_BY,
newCallback(MatchKind.VARIABLE_READ, scope, listener));
index.getRelationships(
parameter,
IndexConstants.IS_READ_WRITTEN_BY,
newCallback(MatchKind.VARIABLE_READ_WRITE, scope, listener));
index.getRelationships(
parameter,
IndexConstants.IS_WRITTEN_BY,
newCallback(MatchKind.VARIABLE_WRITE, scope, listener));
index.getRelationships(
parameter,
IndexConstants.IS_REFERENCED_BY,
newCallback(MatchKind.NAMED_PARAMETER_REFERENCE, scope, listener));
index.getRelationships(
parameter,
IndexConstants.IS_INVOKED_BY,
newCallback(MatchKind.FUNCTION_EXECUTION, scope, listener));
}
private void searchReferences(PropertyAccessorElement accessor, SearchScope scope,
SearchFilter filter, SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
listener = new CountingSearchListener(2, listener);
index.getRelationships(
accessor,
IndexConstants.IS_REFERENCED_BY_QUALIFIED,
newCallback(MatchKind.PROPERTY_ACCESSOR_REFERENCE, scope, listener));
index.getRelationships(
accessor,
IndexConstants.IS_REFERENCED_BY_UNQUALIFIED,
newCallback(MatchKind.PROPERTY_ACCESSOR_REFERENCE, scope, listener));
}
private void searchReferences(PropertyInducingElement field, SearchScope scope,
SearchFilter filter, SearchListener listener) {
assert listener != null;
PropertyAccessorElement getter = field.getGetter();
PropertyAccessorElement setter = field.getSetter();
int numRequests = (getter != null ? 4 : 0) + (setter != null ? 2 : 0) + 2;
listener = applyFilter(filter, listener);
listener = new CountingSearchListener(numRequests, listener);
if (getter != null) {
index.getRelationships(
getter,
IndexConstants.IS_REFERENCED_BY_QUALIFIED,
newCallback(MatchKind.FIELD_READ, scope, listener));
index.getRelationships(
getter,
IndexConstants.IS_REFERENCED_BY_UNQUALIFIED,
newCallback(MatchKind.FIELD_READ, scope, listener));
index.getRelationships(
getter,
IndexConstants.IS_INVOKED_BY_QUALIFIED,
newCallback(MatchKind.FIELD_INVOCATION, scope, listener));
index.getRelationships(
getter,
IndexConstants.IS_INVOKED_BY_UNQUALIFIED,
newCallback(MatchKind.FIELD_INVOCATION, scope, listener));
}
if (setter != null) {
index.getRelationships(
setter,
IndexConstants.IS_REFERENCED_BY_QUALIFIED,
newCallback(MatchKind.FIELD_WRITE, scope, listener));
index.getRelationships(
setter,
IndexConstants.IS_REFERENCED_BY_UNQUALIFIED,
newCallback(MatchKind.FIELD_WRITE, scope, listener));
}
index.getRelationships(
field,
IndexConstants.IS_REFERENCED_BY,
newCallback(MatchKind.FIELD_REFERENCE, scope, listener));
index.getRelationships(
field,
IndexConstants.IS_REFERENCED_BY_QUALIFIED,
newCallback(MatchKind.FIELD_REFERENCE, scope, listener));
}
private void searchReferences(TypeParameterElement typeParameter, SearchScope scope,
SearchFilter filter, SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
index.getRelationships(
typeParameter,
IndexConstants.IS_REFERENCED_BY,
newCallback(MatchKind.TYPE_PARAMETER_REFERENCE, scope, listener));
}
private void searchReferences(VariableElement variable, SearchScope scope, SearchFilter filter,
SearchListener listener) {
assert listener != null;
listener = applyFilter(filter, listener);
listener = new CountingSearchListener(4, listener);
index.getRelationships(
variable,
IndexConstants.IS_READ_BY,
newCallback(MatchKind.VARIABLE_READ, scope, listener));
index.getRelationships(
variable,
IndexConstants.IS_READ_WRITTEN_BY,
newCallback(MatchKind.VARIABLE_READ_WRITE, scope, listener));
index.getRelationships(
variable,
IndexConstants.IS_WRITTEN_BY,
newCallback(MatchKind.VARIABLE_WRITE, scope, listener));
index.getRelationships(
variable,
IndexConstants.IS_INVOKED_BY,
newCallback(MatchKind.FUNCTION_EXECUTION, scope, listener));
}
}