All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.siyeh.ig.dataflow.ScopeUtils Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition java-analysis-impl library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * 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.dataflow;

import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.PsiElementOrderComparator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Arrays;

class ScopeUtils {

  private ScopeUtils() {}

  @Nullable
  public static PsiElement findTighterDeclarationLocation(@NotNull PsiElement sibling, @NotNull PsiVariable variable) {
    PsiElement prevSibling = sibling.getPrevSibling();
    while (prevSibling instanceof PsiWhiteSpace || prevSibling instanceof PsiComment) {
      prevSibling = prevSibling.getPrevSibling();
    }
    if (prevSibling instanceof PsiDeclarationStatement) {
      if (prevSibling.equals(variable.getParent())) {
        return null;
      }
      return findTighterDeclarationLocation(prevSibling, variable);
    }
    return prevSibling;
  }

  @Nullable
  public static PsiElement getChildWhichContainsElement(@NotNull PsiElement ancestor, @NotNull PsiElement element) {
    PsiElement child = element;
    PsiElement parent = child.getParent();
    while (!parent.equals(ancestor)) {
      child = parent;
      parent = child.getParent();
      if (parent == null) {
        return null;
      }
    }
    return child;
  }

  @Nullable
  public static PsiElement getCommonParent(@NotNull PsiElement[] referenceElements) {
    Arrays.sort(referenceElements, PsiElementOrderComparator.getInstance());
    PsiElement commonParent = null;
    for (PsiElement referenceElement : referenceElements) {
      final PsiElement parent = PsiTreeUtil.getParentOfType(referenceElement, PsiCodeBlock.class, PsiForStatement.class);
      if (parent != null && commonParent != null) {
        if (!commonParent.equals(parent)) {
          commonParent = PsiTreeUtil.findCommonParent(commonParent, parent);
          commonParent = PsiTreeUtil.getNonStrictParentOfType(commonParent, PsiCodeBlock.class, PsiForStatement.class);
        }
      }
      else {
        commonParent = parent;
      }
    }

    // make common parent may only be for-statement if first reference is
    // the initialization of the for statement or the initialization is
    // empty.
    if (commonParent instanceof PsiForStatement) {
      final PsiForStatement forStatement = (PsiForStatement)commonParent;
      final PsiElement referenceElement = referenceElements[0];
      final PsiStatement initialization = forStatement.getInitialization();
      if (!(initialization instanceof PsiEmptyStatement)) {
        if (initialization instanceof PsiExpressionStatement) {
          final PsiExpressionStatement statement = (PsiExpressionStatement)initialization;
          final PsiExpression expression = statement.getExpression();
          if (expression instanceof PsiAssignmentExpression) {
            final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)expression;
            final PsiExpression lExpression = ParenthesesUtils.stripParentheses(assignmentExpression.getLExpression());
            if (!lExpression.equals(referenceElement)) {
              commonParent = PsiTreeUtil.getParentOfType(commonParent, PsiCodeBlock.class);
            }
          }
          else {
            commonParent = PsiTreeUtil.getParentOfType(commonParent, PsiCodeBlock.class);
          }
        }
        else {
          commonParent = PsiTreeUtil.getParentOfType(commonParent, PsiCodeBlock.class);
        }
      }
    }

    // common parent may not be a switch() statement to avoid narrowing
    // scope to inside switch branch
    if (commonParent != null) {
      final PsiElement parent = commonParent.getParent();
      if (parent instanceof PsiSwitchStatement) {
        if (referenceElements.length > 1) {
          commonParent = PsiTreeUtil.getParentOfType(parent, PsiCodeBlock.class, false);
        }
        else if (PsiTreeUtil.getParentOfType(referenceElements[0], PsiSwitchLabelStatement.class, true, PsiCodeBlock.class) != null) {
          // reference is a switch label
          commonParent = PsiTreeUtil.getParentOfType(parent, PsiCodeBlock.class, false);
        }
      }
    }
    return commonParent;
  }

  @Nullable
  public static PsiElement moveOutOfLoopsAndClasses(@NotNull PsiElement scope, @NotNull PsiElement maxScope) {
    PsiElement result = maxScope;
    if (result instanceof PsiLoopStatement) {
      return result;
    }
    while (!result.equals(scope)) {
      final PsiElement element = getChildWhichContainsElement(result, scope);
      if (element instanceof PsiForStatement) {
        final PsiForStatement forStatement = (PsiForStatement)element;
        if (forStatement.getInitialization() instanceof PsiEmptyStatement) {
          return element;
        }
      }
      if (element == null || element instanceof PsiLoopStatement || element instanceof PsiClass) {
        while (result != null && !(result instanceof PsiCodeBlock)) {
          result = result.getParent();
        }
        return result;
      }
      else {
        result = element;
      }
    }
    return scope;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy