@Override
    public void visitPyClass(final @NotNull PyClass node) {
      super.visitPyClass(node);
      // check property() and @property
      node.scanProperties(property -> {
        PyTargetExpression target = property.getDefinitionSite();
        if (target != null) {
          // target = property(); args may be all funny
          PyCallExpression call = (PyCallExpression)target.findAssignedValue();
          assert call != null : "Property has a null call assigned to it";
          final PyArgumentList arglist = call.getArgumentList();
          assert arglist != null : "Property call has null arglist";
          // we assume fget, fset, fdel, doc names
          final PyCallExpression.PyArgumentsMapping mapping = ContainerUtil.getFirstItem(call.multiMapArguments(getResolveContext()));
          if (mapping != null) {
            for (Map.Entry<PyExpression, PyCallableParameter> entry : mapping.getMappedParameters().entrySet()) {
              final String paramName = entry.getValue().getName();
              PyExpression argument = PyUtil.peelArgument(entry.getKey());
              checkPropertyCallArgument(paramName, argument, node.getContainingFile());
            }
          }
        }
        else {
          // @property; we only check getter, others are checked by visitPyFunction
          // getter is always present with this form
          final PyCallable callable = property.getGetter().valueOrNull();
          if (callable instanceof PyFunction) {
            checkGetter(callable, getFunctionMarkingElement((PyFunction)callable));
          }
        }
        return false;  // always want more
      }, false);
    }
@Override
    public void visitPyClass(final @NotNull PyClass node)