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

org.jetbrains.plugins.groovy.codeInspection.unassignedVariable.UnassignedVariableAccessInspection Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition groovy-psi library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2000-2014 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 org.jetbrains.plugins.groovy.codeInspection.unassignedVariable;

import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeInspection.GrInspectionUtil;
import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle;
import org.jetbrains.plugins.groovy.codeInspection.GroovyLocalInspectionBase;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrWhileStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrTraditionalForClause;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ControlFlowBuilderUtil;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;

import javax.swing.*;

/**
 * @author ven
 */
public class UnassignedVariableAccessInspection extends GroovyLocalInspectionBase {
  public boolean myIgnoreBooleanExpressions = true;

  @Nullable
  @Override
  public JComponent createOptionsPanel() {
    final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this);
    optionsPanel.addCheckbox(GroovyInspectionBundle.message("ignore.boolean.expressions"), "myIgnoreBooleanExpressions");
    return optionsPanel;
  }

  @Override
  @Nls
  @NotNull
  public String getGroupDisplayName() {
    return GroovyInspectionBundle.message("groovy.dfa.issues");
  }

  @Override
  @Nls
  @NotNull
  public String getDisplayName() {
    return GroovyInspectionBundle.message("unassigned.access");
  }

  @Override
  @NonNls
  @NotNull
  public String getShortName() {
    return "GroovyVariableNotAssigned";
  }

  @Override
  public boolean isEnabledByDefault() {
    return true;
  }

  @Override
  protected void check(@NotNull GrControlFlowOwner owner, @NotNull ProblemsHolder problemsHolder) {
    Instruction[] flow = owner.getControlFlow();
    ReadWriteVariableInstruction[] reads = ControlFlowBuilderUtil.getReadsWithoutPriorWrites(flow, true);
    for (ReadWriteVariableInstruction read : reads) {
      PsiElement element = read.getElement();
      if (element instanceof GroovyPsiElement && !(element instanceof GrClosableBlock)) {
        String name = read.getVariableName();
        GroovyPsiElement property = ResolveUtil.resolveProperty((GroovyPsiElement)element, name);
        if (property != null &&
            !(property instanceof PsiParameter) &&
            !(property instanceof PsiField) &&
            PsiTreeUtil.isAncestor(owner, property, false) &&
            !(myIgnoreBooleanExpressions && isBooleanCheck(element))
          ) {
          problemsHolder.registerProblem(element, GroovyInspectionBundle.message("unassigned.access.tooltip", name));
        }
      }
    }
  }

  private static boolean isBooleanCheck(PsiElement element) {
    final PsiElement parent = element.getParent();
    return parent instanceof GrIfStatement && ((GrIfStatement)parent).getCondition() == element ||
           parent instanceof GrWhileStatement && ((GrWhileStatement)parent).getCondition() == element ||
           parent instanceof GrTraditionalForClause && ((GrTraditionalForClause)parent).getCondition() == element ||
           isLogicalExpression(parent) ||
           parent instanceof GrUnaryExpression && ((GrUnaryExpression)parent).getOperationTokenType() == GroovyTokenTypes.mBNOT ||
           isCheckForNull(parent, element);
  }

  private static boolean isLogicalExpression(PsiElement parent) {
    return parent instanceof GrBinaryExpression &&
           (((GrBinaryExpression)parent).getOperationTokenType() == GroovyTokenTypes.mLAND ||
            ((GrBinaryExpression)parent).getOperationTokenType() == GroovyTokenTypes.mLOR);
  }

  private static boolean isCheckForNull(PsiElement parent, PsiElement element) {
    if (!(parent instanceof GrBinaryExpression)) return false;

    final IElementType tokenType = ((GrBinaryExpression)parent).getOperationTokenType();
    if (!(tokenType == GroovyTokenTypes.mEQUAL || tokenType == GroovyTokenTypes.mNOT_EQUAL)) return false;
    if (element == ((GrBinaryExpression)parent).getLeftOperand()) {
      final GrExpression rightOperand = ((GrBinaryExpression)parent).getRightOperand();
      return rightOperand != null && GrInspectionUtil.isNull(rightOperand);
    }
    else {
      return GrInspectionUtil.isNull(((GrBinaryExpression)parent).getLeftOperand());
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy