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

com.jetbrains.python.inspections.PyRedundantParenthesesInspection Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition python-community 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 com.jetbrains.python.inspections;

import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.xmlb.SmartSerializer;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.inspections.quickfix.RedundantParenthesesQuickFix;
import com.jetbrains.python.psi.*;
import org.jdom.Element;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;

/**
 * User: catherine
 *
 * Inspection to detect redundant parentheses in if/while statement.
 */
public class PyRedundantParenthesesInspection extends PyInspection {

  private final SmartSerializer mySerializer = new SmartSerializer();

  public boolean myIgnorePercOperator = false;
  public boolean myIgnoreTupleInReturn = false;
  public boolean myIgnoreEmptyBaseClasses = false;

  @Nls
  @NotNull
  @Override
  public String getDisplayName() {
    return PyBundle.message("INSP.NAME.redundant.parentheses");
  }

  @NotNull
  @Override
  public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
                                        boolean isOnTheFly,
                                        @NotNull LocalInspectionToolSession session) {
    return new Visitor(holder, session);
  }

  @Override
  public void writeSettings(@NotNull Element node) throws WriteExternalException {
    mySerializer.writeExternal(this, node);
  }

  @Override
  public void readSettings(@NotNull Element node) throws InvalidDataException {
    mySerializer.readExternal(this, node);
  }

  private class Visitor extends PyInspectionVisitor {
    public Visitor(@NotNull ProblemsHolder holder, @NotNull LocalInspectionToolSession session) {
      super(holder, session);
    }

    @Override
    public void visitPyParenthesizedExpression(final PyParenthesizedExpression node) {
      PyExpression expression = node.getContainedExpression();
      if (node.getText().contains("\n")) return;
      PyYieldExpression yieldExpression = PsiTreeUtil.getParentOfType(expression, PyYieldExpression.class, false);
      if (yieldExpression != null) return;
      if (expression instanceof PyTupleExpression && myIgnoreTupleInReturn) {
        return;
      }
      if (expression instanceof PyReferenceExpression || expression instanceof PyLiteralExpression) {
        if (myIgnorePercOperator) {
          PsiElement parent = node.getParent();
          if (parent instanceof PyBinaryExpression) {
            if (((PyBinaryExpression)parent).getOperator() == PyTokenTypes.PERC) return;
          }
        }
        
        if (node.getParent() instanceof PyPrintStatement)
          return;
        registerProblem(node, PyBundle.message("QFIX.redundant.parentheses"), new RedundantParenthesesQuickFix());
      }
      else if (node.getParent() instanceof PyIfPart || node.getParent() instanceof PyWhilePart
                  || node.getParent() instanceof PyReturnStatement) {
          registerProblem(node, PyBundle.message("QFIX.redundant.parentheses"), new RedundantParenthesesQuickFix());
      }
      else if (expression instanceof PyBinaryExpression) {
        PyBinaryExpression binaryExpression = (PyBinaryExpression)expression;

        if (node.getParent() instanceof PyPrefixExpression)
          return;
        if (binaryExpression.getOperator() == PyTokenTypes.AND_KEYWORD ||
            binaryExpression.getOperator() == PyTokenTypes.OR_KEYWORD) {
          final PyExpression leftExpression = binaryExpression.getLeftExpression();
          final PyExpression rightExpression = binaryExpression.getRightExpression();
          if (leftExpression instanceof PyParenthesizedExpression && rightExpression instanceof PyParenthesizedExpression &&
            !(((PyParenthesizedExpression)leftExpression).getContainedExpression() instanceof PyBinaryExpression) &&
            !(((PyParenthesizedExpression)rightExpression).getContainedExpression() instanceof PyBinaryExpression)) {
            registerProblem(node, PyBundle.message("QFIX.redundant.parentheses"), new RedundantParenthesesQuickFix());
          }
        }
      }
      else if (expression instanceof PyParenthesizedExpression) {
        registerProblem(expression, PyBundle.message("QFIX.redundant.parentheses"), new RedundantParenthesesQuickFix());
      }
    }

    @Override
    public void visitPyArgumentList(PyArgumentList node) {
      if (!(node.getParent() instanceof PyClass)) {
        return;
      }
      if (!myIgnoreEmptyBaseClasses && node.getArguments().length == 0) {
        registerProblem(node, PyBundle.message("QFIX.redundant.parentheses"), new RedundantParenthesesQuickFix());
      }
    }
  }

  @Override
  public JComponent createOptionsPanel() {
    MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
    panel.addCheckbox("Ignore argument of % operator", "myIgnorePercOperator");
    panel.addCheckbox("Ignore tuples", "myIgnoreTupleInReturn");
    panel.addCheckbox("Ignore empty lists of base classes", "myIgnoreEmptyBaseClasses");
    return panel;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy