blob: c724485d3d1672cd1fe4be9f3ee2602b5a137932 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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 org.jetbrains.plugins.groovy.findUsages;
import com.intellij.openapi.application.QueryExecutorBase;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.*;
import com.intellij.psi.search.searches.MethodReferencesSearch;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.search.GrSourceFilterScope;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
/**
* @author ven
*/
public class MethodLateBoundReferencesSearcher extends QueryExecutorBase<PsiReference, MethodReferencesSearch.SearchParameters> {
public MethodLateBoundReferencesSearcher() {
super(true);
}
@Override
public void processQuery(@NotNull MethodReferencesSearch.SearchParameters queryParameters, @NotNull Processor<PsiReference> consumer) {
final PsiMethod method = queryParameters.getMethod();
SearchScope searchScope = GroovyScopeUtil.restrictScopeToGroovyFiles(queryParameters.getScope()).intersectWith(getUseScope(method));
PsiClass aClass = method.getContainingClass();
String className = aClass == null ? null : aClass.getName();
orderSearching(searchScope, method.getName(), method, queryParameters.getOptimizer(), method.getParameterList().getParametersCount());
final String propName = PropertyUtil.getPropertyName(method);
if (propName != null) {
orderSearching(searchScope, propName, method, queryParameters.getOptimizer(), -1);
}
}
private static SearchScope getUseScope(final PsiMethod method) {
final SearchScope scope = method.getUseScope();
final PsiFile file = method.getContainingFile();
if (file != null && scope instanceof GlobalSearchScope) {
final VirtualFile vfile = file.getOriginalFile().getVirtualFile();
final Project project = method.getProject();
if (vfile != null && ProjectRootManager.getInstance(project).getFileIndex().isInSource(vfile)) {
return new GrSourceFilterScope((GlobalSearchScope)scope);
}
}
return scope;
}
private static void orderSearching(SearchScope searchScope,
final String name,
@NotNull PsiMethod searchTarget,
@NotNull SearchRequestCollector collector,
final int paramCount) {
if (StringUtil.isEmpty(name)) return;
collector.searchWord(name, searchScope, UsageSearchContext.IN_CODE, true, searchTarget, new RequestResultProcessor("groovy.lateBound") {
@Override
public boolean processTextOccurrence(@NotNull PsiElement element, int offsetInElement, @NotNull Processor<PsiReference> consumer) {
if (!(element instanceof GrReferenceExpression)) {
return true;
}
final GrReferenceExpression ref = (GrReferenceExpression)element;
if (!name.equals(ref.getReferenceName()) || PsiUtil.isLValue(ref) || ref.resolve() != null) {
return true;
}
PsiElement parent = ref.getParent();
if (parent instanceof GrMethodCall) {
if (!argumentsMatch((GrMethodCall)parent, paramCount)) {
return true;
}
} else if (ResolveUtil.isKeyOfMap(ref)) {
return true;
}
return consumer.process((PsiReference)element);
}
});
}
private static boolean argumentsMatch(GrMethodCall call, int paramCount) {
int argCount = call.getExpressionArguments().length;
if (PsiImplUtil.hasNamedArguments(call.getArgumentList())) {
argCount++;
}
return argCount == paramCount;
}
}