AnalyzeCalleeResults (@NotNull PyCallSiteExpression callSite, @NotNull PyCallExpression.PyArgumentsMapping mapping) { final PyCallableType callableType = mapping.getCallableType(); if (callableType == null) return null; final List<AnalyzeArgumentResult> result = new ArrayList<>(); final List<UnexpectedArgumentForParamSpec> unexpectedArgumentForParamSpecs = new ArrayList<>(); final List<UnfilledParameterFromParamSpec> unfilledParameterFromParamSpecs = new ArrayList<>(); final var receiver = callSite.getReceiver(callableType.getCallable()); final var substitutions = PyTypeChecker.unifyReceiver(receiver, myTypeEvalContext); final var mappedParameters = mapping.getMappedParameters(); final var regularMappedParameters = getRegularMappedParameters(mappedParameters); for (Map.Entry<PyExpression, PyCallableParameter> entry : regularMappedParameters.entrySet()) { final PyExpression argument = entry.getKey(); final PyCallableParameter parameter = entry.getValue(); final PyType expected = parameter.getArgumentType(myTypeEvalContext); final PyType promotedToLiteral = PyLiteralType.Companion.promoteToLiteral(argument, expected, myTypeEvalContext, substitutions); final var actual = promotedToLiteral != null ? promotedToLiteral : myTypeEvalContext.getType(argument); if (expected instanceof PyParamSpecType) { final var allArguments = callSite.getArguments(callableType.getCallable()); analyzeParamSpec((PyParamSpecType)expected, allArguments, substitutions, result, unexpectedArgumentForParamSpecs, unfilledParameterFromParamSpecs); break; } else if (expected instanceof PyConcatenateType concatenateType) { final var allArguments = callSite.getArguments(callableType.getCallable()); if (allArguments.isEmpty()) break; final var firstExpectedTypes = concatenateType.getFirstTypes(); final var argumentRightBound = Math.min(firstExpectedTypes.size(), allArguments.size()); final var firstArguments = allArguments.subList(0, argumentRightBound); matchArgumentsAndTypes(firstArguments, firstExpectedTypes, substitutions, result); if (argumentRightBound < allArguments.size()) { final var paramSpec = concatenateType.getParamSpec(); final var restArguments = allArguments.subList(argumentRightBound, allArguments.size()); analyzeParamSpec(paramSpec, restArguments, substitutions, result, unexpectedArgumentForParamSpecs, unfilledParameterFromParamSpecs); } break; } else { final boolean matched = matchParameterAndArgument(expected, actual, argument, substitutions); result.add(new AnalyzeArgumentResult(argument, expected, substituteGenerics(expected, substitutions), actual, matched)); } } PyCallableParameter positionalContainer = getMappedPositionalContainer(mappedParameters); List<PyExpression> positionalArguments = getArgumentsMappedToPositionalContainer(mappedParameters); PyCallableParameter keywordContainer = getMappedKeywordContainer(mappedParameters); List<PyExpression> keywordArguments = getArgumentsMappedToKeywordContainer(mappedParameters); List<PyExpression> allArguments = ContainerUtil.concat(positionalArguments, keywordArguments); PyParamSpecType paramSpecType = getParamSpecTypeFromContainerParameters(keywordContainer, positionalContainer); if (paramSpecType != null) { analyzeParamSpec(paramSpecType, allArguments, substitutions, result, unexpectedArgumentForParamSpecs, unfilledParameterFromParamSpecs); } else { if (positionalContainer != null) { result.addAll(analyzeContainerMapping(positionalContainer, positionalArguments, substitutions)); } if (keywordContainer != null) { result.addAll(analyzeContainerMapping(keywordContainer, keywordArguments, substitutions)); } } List<UnfilledPositionalVararg> unfilledPositionalVarargs = new ArrayList<>(); for (var unmappedContainer: mapping.getUnmappedContainerParameters()) { PyType containerType = unmappedContainer.getArgumentType(myTypeEvalContext); if (unmappedContainer.getName() == null || !(containerType instanceof PyVariadicType)) continue; PyType expandedVararg = PyTypeChecker.substitute(containerType, substitutions, myTypeEvalContext); if (!(expandedVararg instanceof PyUnpackedTupleType unpackedTuple) || unpackedTuple.isUnbound()) continue; unfilledPositionalVarargs.add( new UnfilledPositionalVararg(unmappedContainer.getName(), PythonDocumentationProvider.getTypeName(expandedVararg, myTypeEvalContext))); } return new AnalyzeCalleeResults(callableType, callableType.getCallable(), result, unexpectedArgumentForParamSpecs, unfilledParameterFromParamSpecs, unfilledPositionalVarargs); }