/*
 * Copyright 2003-2005 Dave Griffith
 *
 * 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.siyeh.ig.performance;

import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import org.jetbrains.annotations.NotNull;

class MethodReferenceVisitor extends PsiRecursiveElementVisitor{

    private boolean m_referencesStaticallyAccessible = true;
    private PsiMethod m_method;

    MethodReferenceVisitor(PsiMethod method){
        super();
        m_method = method;
    }

    public boolean areReferencesStaticallyAccessible(){
        return m_referencesStaticallyAccessible;
    }

    public void visitElement(PsiElement element) {
        if(!m_referencesStaticallyAccessible){
            return;
        }
        super.visitElement(element);
    }

    public void visitReferenceElement(PsiJavaCodeReferenceElement reference){
        super.visitReferenceElement(reference);

        final PsiElement resolvedElement = reference.resolve();
        if(!(resolvedElement instanceof PsiClass)){
            return;
        }
        final PsiClass aClass = (PsiClass) resolvedElement;
        final PsiElement scope = aClass.getScope();
        if(!(scope instanceof PsiClass)){
            return;
        }
        if (aClass.hasModifierProperty(PsiModifier.STATIC)){
            return;
        }
        m_referencesStaticallyAccessible = false;
    }

    public void visitReferenceExpression(
            @NotNull PsiReferenceExpression expression){
        super.visitReferenceExpression(expression);
        final PsiElement qualifier = expression.getQualifierExpression();
        if (qualifier != null && !(qualifier instanceof PsiThisExpression) &&
                !(qualifier instanceof PsiSuperExpression)){
            return;
        }
        final PsiElement element = expression.resolve();
        if(element instanceof PsiMember){
            if (isMemberStaticallyAccessible((PsiMember) element)){
                return;
            }
        } else {
            return;
        }
        m_referencesStaticallyAccessible = false;
    }

    public void visitThisExpression(@NotNull PsiThisExpression expression){
        super.visitThisExpression(expression);
        m_referencesStaticallyAccessible = false;
    }

    private boolean isMethodStaticallyAccessible(PsiMethod method){
        if(m_method.equals(method)){
            return true;
        }
        if(method.hasModifierProperty(PsiModifier.STATIC)){
            return true;
        }
        if(method.isConstructor()){
            return true;
        }
        final PsiClass referenceContainingClass = m_method.getContainingClass();
        final PsiClass methodContainingClass = method.getContainingClass();
        return !InheritanceUtil.isCorrectDescendant(referenceContainingClass,
                                                  methodContainingClass, true);
    }

    private boolean isMemberStaticallyAccessible(PsiMember member){
        if(m_method.equals(member)){
            return true;
        }
        if(member.hasModifierProperty(PsiModifier.STATIC)){
            return true;
        }
        final PsiClass referenceContainingClass = m_method.getContainingClass();
        final PsiClass containingClass = member.getContainingClass();
        return !InheritanceUtil.isCorrectDescendant(referenceContainingClass,
                                                  containingClass, true);
    }
}
@@ -2775,638 +2775,8 @@
  %7D%0A%0A
-    private boolean isMethodStaticallyAccessible(PsiMethod method)%7B%0A        if(m_method.equals(method))%7B%0A            return true;%0A        %7D%0A        if(method.hasModifierProperty(PsiModifier.STATIC))%7B%0A            return true;%0A        %7D%0A        if(method.isConstructor())%7B%0A            return true;%0A        %7D%0A        final PsiClass referenceContainingClass = m_method.getContainingClass();%0A        final PsiClass methodContainingClass = method.getContainingClass();%0A        return !InheritanceUtil.isCorrectDescendant(referenceContainingClass,%0A                                                  methodContainingClass, true);%0A    %7D%0A%0A  
   pr
@@ -2833,26 +2833,24 @@
 er member)%7B%0A
-  
       if(m_m
@@ -2874,34 +2874,32 @@
 er))%7B%0A          
-  
 return true;%0A   
@@ -2893,38 +2893,34 @@
 urn true;%0A      
-  %7D%0A  
+%7D%0A
       if(member.
@@ -2963,34 +2963,32 @@
 IC))%7B%0A          
-  
 return true;%0A   
@@ -2980,26 +2980,24 @@
 eturn true;%0A
-  
       %7D%0A    
@@ -2990,34 +2990,32 @@
 ;%0A      %7D%0A      
-  
 final PsiClass r
@@ -3069,34 +3069,32 @@
 gClass();%0A      
-  
 final PsiClass c
@@ -3141,26 +3141,24 @@
 ss();%0A      
- 
- 
 return !Inhe
@@ -3263,18 +3263,16 @@
         
-  
 containi
@@ -3287,15 +3287,13 @@
  true);%0A
-  
   %7D%0A%7D

incorrect warning for the following class: