package com.siyeh.ig.performance;

import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.psi.*;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.ExpressionInspection;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NotNull;

public class CallToSimpleGetterInClassInspection extends ExpressionInspection{
    public String getID(){
        return "CallToSimpleGetterFromWithinClass";
    }

    public String getDisplayName(){
        return "Call to simple getter from within class";
    }
    public String getGroupDisplayName(){
        return GroupNames.PERFORMANCE_GROUP_NAME;
    }

    public String buildErrorString(PsiElement location){
        return "Call to simple getter '#ref()' from within class #loc";
    }

    public BaseInspectionVisitor buildVisitor(){
        return new CallToSimpleGetterInClassVisitor();
    }

    private class CallToSimpleGetterInClassVisitor
            extends BaseInspectionVisitor{


        public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call){
            super.visitMethodCallExpression(call);
            final PsiReferenceExpression methodExpression = call.getMethodExpression();
            if(methodExpression == null)
            {
                return;
            }
            final String methodName = methodExpression.getReferenceName();
            if(methodName == null)
            {
                return;
            }
            if(!methodName.startsWith("get")&& !methodName.startsWith("is"))
            {
                return;
            }
            final PsiExpressionList argList = call.getArgumentList();
            if(argList == null){
                return;
            }

            final PsiExpression[] args = argList.getExpressions();
            if(args == null || args.length != 0){
                return;
            }
            final PsiClass containingClass =
                    ClassUtils.getContainingClass(call);
            if(containingClass == null){
                return;
            }
            final PsiMethod method = call.resolveMethod();
            if(method == null){
                return;
            }
            if(!containingClass.equals(method.getContainingClass())){
                return;
            }
            if(!isSimpleGetter(method)){
                return;
            }
            registerMethodCallError(call);
        }
    }

    private boolean isSimpleGetter(PsiMethod method){
        if(method.hasModifierProperty(PsiModifier.SYNCHRONIZED))
        {
            return false;
        }
        final PsiCodeBlock body = method.getBody();
        if(body == null){
            return false;
        }
        final PsiStatement[] statements = body.getStatements();
        if(statements.length != 1){
            return false;
        }
        final PsiStatement statement = statements[0];
        if(!(statement instanceof PsiReturnStatement)){
            return false;
        }
        final PsiReturnStatement returnStatement =
                (PsiReturnStatement) statement;
        final PsiExpression value = returnStatement.getReturnValue();
        if(value == null){
            return false;
        }
        if(!(value instanceof PsiReferenceExpression))
        {
           return false;
        }

        final PsiReferenceExpression reference = (PsiReferenceExpression) value;
        final PsiExpression qualifier = reference.getQualifierExpression();
        if(qualifier!=null && !"this".equals(qualifier.getText()))
        {
            return false;
        }
        final PsiElement referent = reference.resolve();
        if(referent == null)
        {
            return false;
        }
        if(!(referent instanceof PsiField))
        {
            return false;
        }
        final PsiField field = (PsiField) referent;
        final PsiType fieldType = field.getType();
        final PsiType returnType = method.getReturnType();
        if(fieldType == null ||returnType == null)
        {
            return false;
        }
        if(!fieldType.getCanonicalText().equals(returnType.getCanonicalText()))
        {
            return false;
        }
        return field.getContainingClass().equals(method.getContainingClass());
    }
}

@@ -121,115 +121,401 @@
 com.
-siyeh.ig.BaseInspectionVisitor;%0Aimport com.siyeh.ig.ExpressionInspection;%0Aimport com.siyeh.ig.psiutils.Clas
+intellij.openapi.project.Project;%0Aimport com.intellij.codeInspection.ProblemDescriptor;%0Aimport com.intellij.util.IncorrectOperationException;%0Aimport com.intellij.pom.java.LanguageLevel;%0Aimport com.siyeh.ig.BaseInspectionVisitor;%0Aimport com.siyeh.ig.ExpressionInspection;%0Aimport com.siyeh.ig.InspectionGadgetsFix;%0Aimport com.siyeh.ig.psiutils.ClassUtils;%0Aimport com.siyeh.ig.psiutils.Parenthese
 sUti
@@ -640,16 +640,76 @@
 ection%7B%0A
+    private final InlineCallFix fix = new InlineCallFix();%0A%0A
     publ
@@ -1112,32 +1112,1400 @@
 s #loc%22;%0A    %7D%0A%0A
+    public InspectionGadgetsFix buildFix(PsiElement location)%7B%0A        return fix;%0A    %7D%0A%0A    private static class InlineCallFix extends InspectionGadgetsFix%7B%0A        public String getName()%7B%0A            return %22Inline call to getter%22;%0A        %7D%0A%0A        public void doFix(Project project, ProblemDescriptor descriptor)%0A                                                                         throws IncorrectOperationException%7B%0A            final PsiElement methodIdentifier = descriptor.getPsiElement();%0A            final PsiReferenceExpression methodExpression =%0A                    (PsiReferenceExpression) methodIdentifier.getParent();%0A            assert methodExpression != null;%0A            final PsiMethodCallExpression call =%0A                    (PsiMethodCallExpression) methodExpression.getParent();%0A            assert call != null;%0A            final PsiMethod method = call.resolveMethod();%0A            assert method != null;%0A            final PsiCodeBlock body = method.getBody();%0A            final PsiStatement%5B%5D statements = body.getStatements();%0A            final PsiReturnStatement returnStatement = (PsiReturnStatement) statements%5B0%5D;%0A            final PsiExpression returnValue = returnStatement.getReturnValue();%0A            final String returnValueText = returnValue.getText();%0A            replaceExpression(call, returnValueText);%0A        %7D%0A    %7D%0A
     public BaseI

Fix for IDEABKL-3149