[python] PY-85031 Use PyAstNamedParameter.isSelf when reporting legacy positional-only parameters

It correctly takes into account the first argument of `__new__` that is also implicit,
and thus should be excluded when reporting positional-only parameters following
non-positional-only ones.

GitOrigin-RevId: abf09c6be5e49c21c12264d22bf63a51018fdcd6
This commit is contained in:
Mikhail Golubev
2025-10-28 15:32:15 +00:00
committed by intellij-monorepo-bot
parent e7fedc4208
commit aea9e8688f
3 changed files with 3 additions and 13 deletions
@@ -790,15 +790,6 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements
return getStubOrPsiChild(PyStubElementTypes.ANNOTATION);
}
/**
* is `function` a method or a classmethod
*/
public static boolean isMethod(PyFunction function) {
final var isMethod = ScopeUtil.getScopeOwner(function) instanceof PyClass;
final var modifier = function.getModifier();
return (isMethod && modifier == null) || modifier == CLASSMETHOD;
}
/**
* @param self should be this
*/
@@ -19,7 +19,6 @@ import com.intellij.lang.annotation.HighlightSeverity;
import com.jetbrains.python.PyPsiBundle;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.ParamHelper;
import com.jetbrains.python.psi.impl.PyFunctionImpl;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
@@ -38,7 +37,6 @@ public class PyParameterListAnnotatorVisitor extends PyElementVisitor {
@Override
public void visitPyParameterList(final @NotNull PyParameterList paramlist) {
final LanguageLevel languageLevel = LanguageLevel.forElement(paramlist);
final var hasImplicit = paramlist.getParent() instanceof PyFunction function && PyFunctionImpl.isMethod(function);
ParamHelper.walkDownParamArray(
paramlist.getParameters(),
@@ -55,7 +53,7 @@ public class PyParameterListAnnotatorVisitor extends PyElementVisitor {
@Override
public void visitNamedParameter(PyNamedParameter parameter, boolean first, boolean last) {
final var name = parameter.getName();
if (!hadKeyword && name != null && !(hasImplicit && first) && !isPrivate(name)) {
if (!hadKeyword && name != null && !parameter.isSelf() && !isPrivate(name)) {
hadKeyword = true;
}
else if (hadKeyword && !hadPositionalContainer && !hadSingleStar && name != null && !hadSlash && isPrivate(name)) {
@@ -15,4 +15,5 @@ class A:
@staticmethod
def s1(__b): pass
@staticmethod
def s1(a, <warning descr="Positional-only parameter follows parameter that is not positional-only">__b</warning>): pass
def s1(a, <warning descr="Positional-only parameter follows parameter that is not positional-only">__b</warning>): pass
def __new__(cls, __b): pass