@Override
    public void visitPyFunction(final @NotNull PyFunction node) {
      for (PyInspectionExtension extension : PyInspectionExtension.EP_NAME.getExtensionList()) {
        if (extension.ignoreMethodParameters(node, myTypeEvalContext)) {
          return;
        }
      }

      // analyze function itself
      PyUtil.MethodFlags flags = PyUtil.MethodFlags.of(node);
      if (flags != null) {
        PyParameterList plist = node.getParameterList();
        PyParameter[] params = plist.getParameters();
        final String methodName = node.getName();
        if (params.length == 0) { // fix: add
          // check for "staticmetod"
          if (flags.isStaticMethod()) return; // no params may be fine
          // check actual param list
          ASTNode name_node = node.getNameNode();
          if (name_node != null) {
            PsiElement open_paren = plist.getFirstChild();
            PsiElement close_paren = plist.getLastChild();
            if (
              open_paren != null && close_paren != null &&
              "(".equals(open_paren.getText()) && ")".equals(close_paren.getText())
            ) {
              String paramName;
              if (flags.isMetaclassMethod() || flags.isClassMethod()) {
                paramName = PyNames.CANONICAL_CLS;
              }
              else {
                paramName = PyNames.CANONICAL_SELF;
              }
              registerProblem(
                plist, PyPsiBundle.message("INSP.must.have.first.parameter", paramName),
                ProblemHighlightType.GENERIC_ERROR, null, new AddSelfQuickFix(paramName)
              );
            }
          }
        }
        else { // fix: rename
          PyNamedParameter first_param = params[0].getAsNamed();
          if (first_param != null) {
            String pname = first_param.getName();
            if (pname == null) {
              return;
            }
            // every dup, swap, drop, or dup+drop of "self"
            @NonNls String[] mangled = {"eslf", "sself", "elf", "felf", "slef", "seelf", "slf", "sslf", "sefl", "sellf", "sef", "seef"};
            if (PyUtil.among(pname, mangled)) {
              registerProblem(
                PyUtil.sure(params[0].getNode()).getPsi(),
                PyPsiBundle.message("INSP.probably.mistyped.self"),
                new RenameParameterQuickFix(PyNames.CANONICAL_SELF)
              );
              return;
            }
            if (flags.isMetaclassMethod()) {
              if (flags.isStaticMethod() && !PyNames.NEW.equals(methodName)) {
                return;
              }
              String expectedName;
              Set<String> alternativeNames;
              if (PyNames.NEW.equals(methodName) || flags.isClassMethod()) {
                expectedName = PyNames.CANONICAL_CLS;
                alternativeNames = Set.of("mcs", "mcls", "metacls");
              }
              else if (flags.isSpecialMetaclassMethod()) {
                expectedName = PyNames.CANONICAL_CLS;
                alternativeNames = Set.of();
              }
              else {
                expectedName = PyNames.CANONICAL_SELF;
                alternativeNames = Set.of(PyNames.CANONICAL_CLS);
              }
              if (!expectedName.equals(pname) && !alternativeNames.contains(pname)) {
                registerProblem(
                  PyUtil.sure(params[0].getNode()).getPsi(),
                  PyPsiBundle.message("INSP.usually.named", expectedName),
                  new RenameParameterQuickFix(expectedName)
                );
              }
            }
            else if (flags.isClassMethod() || PyNames.NEW.equals(methodName)) {
              if (!PyNames.CANONICAL_CLS.equals(pname)) {
                registerProblem(
                  PyUtil.sure(params[0].getNode()).getPsi(),
                  PyPsiBundle.message("INSP.usually.named", PyNames.CANONICAL_CLS),
                  new RenameParameterQuickFix(PyNames.CANONICAL_CLS)
                );
              }
            }
            else if (!flags.isStaticMethod() && !first_param.isPositionalContainer() && !PyNames.CANONICAL_SELF.equals(pname)) {
              registerProblem(
                PyUtil.sure(params[0].getNode()).getPsi(),
                PyPsiBundle.message("INSP.usually.named.self"),
                new RenameParameterQuickFix(PyNames.CANONICAL_SELF)
              );
            }
          }
          else { // the unusual case of a method with first tuple param
            if (!flags.isStaticMethod()) {
              registerProblem(plist, PyPsiBundle.message("INSP.first.param.must.not.be.tuple"));
            }
          }
        }
      }
    }
@Override
    public void visitPyFunction(final @NotNull PyFunction node)