| /* |
| * Copyright 2000-2009 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 com.intellij.psi.impl.search; |
| |
| import com.intellij.psi.*; |
| import com.intellij.psi.search.RequestResultProcessor; |
| import com.intellij.psi.util.MethodSignature; |
| import com.intellij.psi.util.MethodSignatureUtil; |
| import com.intellij.psi.util.TypeConversionUtil; |
| import com.intellij.util.Processor; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.Arrays; |
| |
| /** |
| * @author peter |
| */ |
| public class MethodTextOccurrenceProcessor extends RequestResultProcessor { |
| private static final PsiReferenceService ourReferenceService = PsiReferenceService.getService(); |
| private final PsiMethod[] myMethods; |
| protected final PsiClass myContainingClass; |
| protected final boolean myStrictSignatureSearch; |
| |
| public MethodTextOccurrenceProcessor(@NotNull final PsiClass aClass, final boolean strictSignatureSearch, final PsiMethod... methods) { |
| super(strictSignatureSearch, Arrays.asList(methods)); |
| myMethods = methods; |
| myContainingClass = aClass; |
| myStrictSignatureSearch = strictSignatureSearch; |
| } |
| |
| @Override |
| public final boolean processTextOccurrence(@NotNull PsiElement element, int offsetInElement, @NotNull final Processor<PsiReference> consumer) { |
| for (PsiReference ref : ourReferenceService.getReferences(element, new PsiReferenceService.Hints(myMethods[0], offsetInElement))) { |
| if (ReferenceRange.containsOffsetInElement(ref, offsetInElement) && !processReference(consumer, ref)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| private boolean processReference(Processor<PsiReference> consumer, PsiReference ref) { |
| for (PsiMethod method : myMethods) { |
| if (!method.isValid()) { |
| continue; |
| } |
| |
| if (ref instanceof ResolvingHint && !((ResolvingHint)ref).canResolveTo(PsiMethod.class)) { |
| return true; |
| } |
| if (ref.isReferenceTo(method)) { |
| return consumer.process(ref); |
| } |
| |
| if (!processInexactReference(ref, ref.resolve(), method, consumer)) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| protected boolean processInexactReference(PsiReference ref, PsiElement refElement, PsiMethod method, Processor<PsiReference> consumer) { |
| if (refElement instanceof PsiMethod) { |
| PsiMethod refMethod = (PsiMethod)refElement; |
| PsiClass refMethodClass = refMethod.getContainingClass(); |
| if (refMethodClass == null) return true; |
| |
| if (!refMethod.hasModifierProperty(PsiModifier.STATIC)) { |
| PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(myContainingClass, refMethodClass, PsiSubstitutor.EMPTY); |
| if (substitutor != null) { |
| MethodSignature superSignature = method.getSignature(substitutor); |
| MethodSignature refSignature = refMethod.getSignature(PsiSubstitutor.EMPTY); |
| |
| if (MethodSignatureUtil.isSubsignature(superSignature, refSignature)) { |
| if (!consumer.process(ref)) return false; |
| } |
| } |
| } |
| |
| if (!myStrictSignatureSearch) { |
| PsiManager manager = method.getManager(); |
| if (manager.areElementsEquivalent(refMethodClass, myContainingClass)) { |
| if (!consumer.process(ref)) return false; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| } |