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

com.jetbrains.python.inspections.PyMethodFirstArgAssignmentInspection 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.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;

/**
 * Reports assignment to 'self' or 'cls'.
 * @author dcheryasov
 */
public class PyMethodFirstArgAssignmentInspection extends PyInspection {
  @Nls
  @NotNull
  public String getDisplayName() {
    return PyBundle.message("INSP.NAME.first.arg.assign");
  }

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

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

    private void complain(PsiElement element, String name) {
      registerProblem(element, PyBundle.message("INSP.first.arg.$0.assigned", name));
    }

    private void handleTarget(PyQualifiedExpression target, String name) {
      if (!target.isQualified() && name.equals(target.getText())) {
        complain(target, name);
      }
    }

    @Nullable
    private static String extractFirstParamName(PyElement node) {
      // are we a method?
      List place = PyUtil.searchForWrappingMethod(node, true);
      if (place == null || place.size() < 2) return null;
      PyFunction method = (PyFunction)place.get(place.size()-2);
      //PyClass owner = (PyClass)place.get(place.size()-1);
      // what is our first param?
      PyParameter[] params = method.getParameterList().getParameters();
      if (params.length < 1) return null; // no params
      PyNamedParameter first_parm = params[0].getAsNamed();
      if (first_parm == null) return null;
      if (first_parm.isKeywordContainer() || first_parm.isPositionalContainer()) return null; // legal but crazy cases; back off
      final String first_param_name = first_parm.getName();
      if (first_param_name == null || first_param_name.length() < 1) return null; // ignore cases of incorrect code
      // is it a static method?
      PyFunction.Modifier modifier = method.getModifier();
      if (modifier == PyFunction.Modifier.STATICMETHOD) return null; // these may do whatever they please
      return first_param_name;
    }

    private void markNameDefiner(NameDefiner definer) {
      final String first_param_name = extractFirstParamName((PyElement)definer);
      if (first_param_name != null) {
        // check the targets
        for (PyElement elt : definer.iterateNames()) {
          if (elt instanceof PyTargetExpression) handleTarget((PyTargetExpression)elt, first_param_name);
        }
      }
    }

    @Override
    public void visitPyAssignmentStatement(PyAssignmentStatement node) {
      markNameDefiner(node);
    }

    @Override
    public void visitPyAugAssignmentStatement(PyAugAssignmentStatement node) {
      final String first_param_name = extractFirstParamName(node);
      if (first_param_name != null) {
        PyExpression target = node.getTarget();
        if (target instanceof PyQualifiedExpression) handleTarget((PyQualifiedExpression)target, first_param_name);
        else if (target instanceof PyTupleExpression) {
          for (PyExpression elt : PyUtil.flattenedParensAndTuples(((PyTupleExpression)target).getElements())) {
            if (elt instanceof PyQualifiedExpression) handleTarget((PyQualifiedExpression)elt, first_param_name);
          }
        }
      }
    }

    @Override
    public void visitPyForStatement(PyForStatement node) {
      markNameDefiner(node);
    }

    /* TODO: implement when WithStmt is part-ified
    @Override
    public void visitPyWithStatement(PyWithStatement node) {
      super.visitPyWithStatement(node);
    }
    */

    private void markDefinition(PyElement definer) {
      final String first_param_name = extractFirstParamName(definer);
      if (first_param_name != null && first_param_name.equals(definer.getName())) {
        complain(definer.getNode().findChildByType(PyTokenTypes.IDENTIFIER).getPsi(), first_param_name); // no NPE here, or we won't have the name
      }
    }

    @Override
    public void visitPyFunction(PyFunction definer) {
      markDefinition(definer);
    }

    @Override
    public void visitPyClass(PyClass definer) {
      markDefinition(definer);
    }


  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy