diff --git a/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java b/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java index e848b91e1f21..823c78e33159 100644 --- a/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyArgumentListInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -21,6 +21,8 @@ import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiPolyVariantReference; +import com.intellij.psi.ResolveResult; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyNames; @@ -35,7 +37,9 @@ import com.jetbrains.python.psi.types.PyTypeChecker; import com.jetbrains.python.psi.types.TypeEvalContext; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -115,9 +119,13 @@ public class PyArgumentListInspection extends PyInspection { final PyCallExpression.PyMarkedCallee callee = mapping.getMarkedCallee(); if (callee != null) { final PyCallable callable = callee.getCallable(); - // Decorate functions may have different parameter lists. We don't match arguments with parameters of decorators yet - if (callable instanceof PyFunction && PyUtil.hasCustomDecorators((PyFunction)callable)) { - return; + if (callable instanceof PyFunction) { + final PyFunction function = (PyFunction)callable; + + // Decorate functions may have different parameter lists. We don't match arguments with parameters of decorators yet + if (PyUtil.hasCustomDecorators(function) || decoratedClassInitCall(callExpr.getCallee(), function)) { + return; + } } } highlightParametersMismatch(node, holder, mapping); @@ -128,6 +136,19 @@ public class PyArgumentListInspection extends PyInspection { inspectPyArgumentList(node, holder, context, 0); } + private static boolean decoratedClassInitCall(@Nullable PyExpression callee, @NotNull PyFunction function) { + if (callee instanceof PyReferenceExpression && PyUtil.isInit(function)) { + final PsiPolyVariantReference classReference = ((PyReferenceExpression)callee).getReference(); + + return Arrays + .stream(classReference.multiResolve(false)) + .map(ResolveResult::getElement) + .anyMatch(element -> element instanceof PyClass && PyUtil.hasCustomDecorators((PyClass)element)); + } + + return false; + } + private static void highlightStarArgumentTypeMismatch(PyArgumentList node, ProblemsHolder holder, TypeEvalContext context) { for (PyExpression arg : node.getArguments()) { if (arg instanceof PyStarArgument) { diff --git a/python/testData/inspections/PyArgumentListInspection/classDecoratedThroughCall.py b/python/testData/inspections/PyArgumentListInspection/classDecoratedThroughCall.py new file mode 100644 index 000000000000..a75cd3cff6fe --- /dev/null +++ b/python/testData/inspections/PyArgumentListInspection/classDecoratedThroughCall.py @@ -0,0 +1,8 @@ +import attr + +class A(object): + a = attr.ib() + +A = attr.s(A) + +A(a="test") \ No newline at end of file diff --git a/python/testData/inspections/PyArgumentListInspection/classDecoratedThroughDecorator.py b/python/testData/inspections/PyArgumentListInspection/classDecoratedThroughDecorator.py new file mode 100644 index 000000000000..c959ed4fbd2f --- /dev/null +++ b/python/testData/inspections/PyArgumentListInspection/classDecoratedThroughDecorator.py @@ -0,0 +1,7 @@ +import attr + +@attr.s +class A(object): + a = attr.ib() + +A(a="test") \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java index 0973405ad428..de9015dceeda 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyArgumentListInspectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -44,6 +44,16 @@ public class PyArgumentListInspectionTest extends PyTestCase { PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), null); } } + + // PY-19130 + public void testClassDecoratedThroughDecorator() { + doTest(); + } + + // PY-19130 + public void testClassDecoratedThroughCall() { + doTest(); + } public void testTupleVsLiteralList() { doTest();