void (@NotNull PyCallExpression callExpression) { final Set<String> keywordArgumentNames = new HashSet<>(); boolean seenKeywordArgument = false; boolean seenKeywordContainer = false; boolean seenPositionalContainer = false; for (PyExpression argument : callExpression.getArguments()) { if (argument instanceof PyKeywordArgument) { final String keyword = ((PyKeywordArgument)argument).getKeyword(); if (keywordArgumentNames.contains(keyword)) { registerProblem(argument, PyPsiBundle.message("INSP.compatibility.keyword.argument.repeated"), new PyRemoveArgumentQuickFix()); } else if (seenKeywordContainer) { registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON35) && registerForLanguageLevel(level), PyPsiBundle.message("INSP.compatibility.feature.allow.keyword.arguments.after.kwargs"), argument, new PyRemoveArgumentQuickFix()); } seenKeywordArgument = true; keywordArgumentNames.add(keyword); } else if (argument instanceof PyStarArgument starArgument) { if (starArgument.isKeyword()) { if (seenKeywordContainer) { registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON35) && registerForLanguageLevel(level), PyPsiBundle.message("INSP.compatibility.feature.allow.duplicate.kwargs"), argument, new PyRemoveArgumentQuickFix()); } seenKeywordContainer = true; } else { if (seenPositionalContainer) { registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON35) && registerForLanguageLevel(level), PyPsiBundle.message("INSP.compatibility.feature.allow.duplicate.positional.varargs"), argument, new PyRemoveArgumentQuickFix()); } seenPositionalContainer = true; } } else { if (seenKeywordArgument) { registerProblem(argument, PyPsiBundle.message("INSP.compatibility.positional.argument.after.keyword.argument"), new PyRemoveArgumentQuickFix()); } else if (seenPositionalContainer) { registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON35) && registerForLanguageLevel(level), PyPsiBundle.message("INSP.compatibility.feature.allow.positional.arguments.after.expression"), argument, new PyRemoveArgumentQuickFix()); } else if (seenKeywordContainer) { registerProblem(argument, PyPsiBundle.message("INSP.compatibility.positional.argument.after.kwargs"), new PyRemoveArgumentQuickFix()); } } } /* check for trailing comma */ PyExpression lastArg = ContainerUtil.getLastItem(Arrays.asList(callExpression.getArguments())); if (lastArg instanceof PyStarArgument) { PsiElement sibling = PyPsiUtils.getNextNonWhitespaceSibling(lastArg); if (sibling != null && sibling.getNode().getElementType() == PyTokenTypes.COMMA) { boolean isKeyword = ((PyStarArgument)lastArg).isKeyword(); String message; if (isKeyword) { message = PyPsiBundle.message("INSP.compatibility.feature.allow.trailing.comma.after.kwargs"); } else { message = PyPsiBundle.message("INSP.compatibility.feature.allow.trailing.comma.after.positional.vararg"); } registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON35) && registerForLanguageLevel(level), message, sibling); } } }