/*
 * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
 *
 * 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.psiutils;

import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PropertyUtil;
import org.jetbrains.annotations.NotNull;

public class SideEffectChecker {

  private SideEffectChecker() {
    super();
  }

  public static boolean mayHaveSideEffects(@NotNull PsiExpression exp) {
    final SideEffectsVisitor visitor = new SideEffectsVisitor();
    exp.accept(visitor);
    return visitor.mayHaveSideEffects();
  }

  private static class SideEffectsVisitor extends JavaRecursiveElementWalkingVisitor {

    private boolean mayHaveSideEffects = false;

    @Override
    public void visitElement(@NotNull PsiElement element) {
      if (!mayHaveSideEffects) {
        super.visitElement(element);
      }
    }

    @Override
    public void visitAssignmentExpression(
      @NotNull PsiAssignmentExpression expression) {
      if (mayHaveSideEffects) {
        return;
      }
      super.visitAssignmentExpression(expression);
      mayHaveSideEffects = true;
    }

    @Override
    public void visitMethodCallExpression(
      @NotNull PsiMethodCallExpression expression) {
      if (mayHaveSideEffects) {
        return;
      }
      super.visitMethodCallExpression(expression);
      final PsiReferenceExpression methodExpression = expression.getMethodExpression();
      final String methodName = methodExpression.getReferenceName();
      if ((methodName.startsWith("is") || methodName.startsWith("get")) && expression.getArgumentList().getExpressions().length == 0) {
        final PsiMethod method = expression.resolveMethod();
        if (PropertyUtil.isSimpleGetter(method)) {
          return;
        }
      }
      mayHaveSideEffects = true;
    }

    @Override
    public void visitNewExpression(@NotNull PsiNewExpression expression) {
      if (mayHaveSideEffects) {
        return;
      }
      super.visitNewExpression(expression);
      mayHaveSideEffects = true;
    }

    @Override
    public void visitPostfixExpression(
      @NotNull PsiPostfixExpression expression) {
      if (mayHaveSideEffects) {
        return;
      }
      super.visitPostfixExpression(expression);
      final IElementType tokenType = expression.getOperationTokenType();
      if (tokenType.equals(JavaTokenType.PLUSPLUS) ||
          tokenType.equals(JavaTokenType.MINUSMINUS)) {
        mayHaveSideEffects = true;
      }
    }

    @Override
    public void visitPrefixExpression(
      @NotNull PsiPrefixExpression expression) {
      if (mayHaveSideEffects) {
        return;
      }
      super.visitPrefixExpression(expression);
      final IElementType tokenType = expression.getOperationTokenType();
      if (tokenType.equals(JavaTokenType.PLUSPLUS) ||
          tokenType.equals(JavaTokenType.MINUSMINUS)) {
        mayHaveSideEffects = true;
      }
    }

    public boolean mayHaveSideEffects() {
      return mayHaveSideEffects;
    }
  }
}

@@ -664,13 +664,51 @@
 lij.
-psi.*
+codeInspection.dataFlow.ControlFlowAnalyzer
 ;%0Aim
@@ -733,25 +733,9 @@
 psi.
-tree.IElementType
+*
 ;%0Aim
@@ -760,25 +760,25 @@
 psi.
-util.PropertyUtil
+tree.IElementType
 ;%0Aim
@@ -1900,146 +1900,48 @@
  Psi
-ReferenceExpression methodExpression = expression.getMethodExpression();%0A      final String methodName = methodExpression.getReferenceName
+Method method = expression.resolveMethod
 ();%0A
@@ -1953,235 +1953,53 @@
  if 
-(
 (method
-Name.startsWith(%22is%22) %7C%7C methodName.startsWith(%22get%22)) && expression.getArgumentList().getExpressions().length == 0) %7B%0A        final PsiMethod method = expression.resolveMethod();%0A        if (PropertyUtil.isSimpleGetter
+ != null && ControlFlowAnalyzer.isPure
 (met
@@ -2010,34 +2010,32 @@
 ) %7B%0A        
-  
 return;%0A
         %7D%0A  
@@ -2018,26 +2018,24 @@
     return;%0A
-  
       %7D%0A    
@@ -2032,25 +2032,24 @@
     %7D%0A      
-%7D
 %0A      mayHa

use declared method purity in general side effect checker (e.g. for completion in debugger evaluation)