diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyCallExpression.java b/python/psi-api/src/com/jetbrains/python/psi/PyCallExpression.java index e716edd74955..8c4ea4433e6f 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyCallExpression.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyCallExpression.java @@ -374,6 +374,7 @@ public interface PyCallExpression extends PyCallSiteExpression { class PyArgumentsMapping { @NotNull private final PyCallSiteExpression myCallSiteExpression; @Nullable private final PyMarkedCallee myMarkedCallee; + @NotNull private final List myImplicitParameters; @NotNull private final Map myMappedParameters; @NotNull private final List myUnmappedParameters; @NotNull private final List myUnmappedArguments; @@ -383,6 +384,7 @@ public interface PyCallExpression extends PyCallSiteExpression { public PyArgumentsMapping(@NotNull PyCallSiteExpression callSiteExpression, @Nullable PyMarkedCallee markedCallee, + @NotNull List implicitParameters, @NotNull Map mappedParameters, @NotNull List unmappedParameters, @NotNull List unmappedArguments, @@ -391,6 +393,7 @@ public interface PyCallExpression extends PyCallSiteExpression { @NotNull Map tupleMappedParameters) { myCallSiteExpression = callSiteExpression; myMarkedCallee = markedCallee; + myImplicitParameters = implicitParameters; myMappedParameters = mappedParameters; myUnmappedParameters = unmappedParameters; myUnmappedArguments = unmappedArguments; @@ -399,10 +402,29 @@ public interface PyCallExpression extends PyCallSiteExpression { myMappedTupleParameters = tupleMappedParameters; } + /** + * @deprecated + * Use {@link #PyArgumentsMapping(PyCallSiteExpression, PyMarkedCallee, List, Map, List, List, List, List, Map)} that includes + * implicitly mapped parameters. This constructor will be removed in 2018.2. + */ + @Deprecated + public PyArgumentsMapping(@NotNull PyCallSiteExpression callSiteExpression, + @Nullable PyMarkedCallee markedCallee, + @NotNull Map mappedParameters, + @NotNull List unmappedParameters, + @NotNull List unmappedArguments, + @NotNull List parametersMappedToVariadicPositionalArguments, + @NotNull List parametersMappedToVariadicKeywordArguments, + @NotNull Map tupleMappedParameters) { + this(callSiteExpression, markedCallee, Collections.emptyList(), mappedParameters, unmappedParameters, unmappedArguments, + parametersMappedToVariadicPositionalArguments, parametersMappedToVariadicKeywordArguments, tupleMappedParameters); + } + @NotNull public static PyArgumentsMapping empty(@NotNull PyCallSiteExpression callSiteExpression) { return new PyCallExpression.PyArgumentsMapping(callSiteExpression, null, + Collections.emptyList(), Collections.emptyMap(), Collections.emptyList(), Collections.emptyList(), @@ -421,6 +443,11 @@ public interface PyCallExpression extends PyCallSiteExpression { return myMarkedCallee; } + @NotNull + public List getImplicitParameters() { + return myImplicitParameters; + } + @NotNull public Map getMappedParameters() { return myMappedParameters; diff --git a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java index d9d5a3c75a22..27fee7dff030 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java +++ b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java @@ -724,12 +724,15 @@ public class PyCallExpressionHelper { final List parameters = markedCallee.getCallableType().getParameters(context); if (parameters == null) return PyCallExpression.PyArgumentsMapping.empty(callExpression); - final List explicitParameters = dropImplicitParameters(parameters, markedCallee.getImplicitOffset()); + final int safeImplicitOffset = Math.min(markedCallee.getImplicitOffset(), parameters.size()); + final List explicitParameters = parameters.subList(safeImplicitOffset, parameters.size()); + final List implicitParameters = parameters.subList(0, safeImplicitOffset); final List arguments = Arrays.asList(argumentList.getArguments()); final ArgumentMappingResults mappingResults = analyzeArguments(arguments, explicitParameters); return new PyCallExpression.PyArgumentsMapping(callExpression, markedCallee, + implicitParameters, mappingResults.getMappedParameters(), mappingResults.getUnmappedParameters(), mappingResults.getUnmappedArguments(), @@ -798,26 +801,18 @@ public class PyCallExpressionHelper { if (parameters == null) return PyCallExpression.PyArgumentsMapping.empty(callSite); final List arguments = callSite.getArguments(callable); - final List explicitParameters = - filterExplicitParameters(parameters, callable, callSite, resolveContext); + final List explicitParameters = filterExplicitParameters(parameters, callable, callSite, resolveContext); + final List implicitParameters = parameters.subList(0, parameters.size() - explicitParameters.size()); final ArgumentMappingResults mappingResults = analyzeArguments(arguments, explicitParameters); - final Map mapped = new LinkedHashMap<>(); - final PyExpression receiver = callSite.getReceiver(callable); - if (receiver != null && !explicitParameters.equals(parameters)) { - final PyCallableParameter first = ContainerUtil.getFirstItem(parameters); - if (first != null && first.getParameter() != null && first.getParameter().isSelf()) { - mapped.put(receiver, first); - } - } - mapped.putAll(mappingResults.getMappedParameters()); final PyCallExpression.PyMarkedCallee markedCallee = new PyCallExpression.PyMarkedCallee(callableType, callable, null, 0, false, RatedResolveResult.RATE_NORMAL); return new PyCallExpression.PyArgumentsMapping(callSite, markedCallee, - mapped, + implicitParameters, + mappingResults.getMappedParameters(), mappingResults.getUnmappedParameters(), mappingResults.getUnmappedArguments(), mappingResults.getParametersMappedToVariadicPositionalArguments(), diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index 596ade04a864..f2325c6ce516 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -230,10 +230,17 @@ public class PyFunctionImpl extends PyBaseElementImpl implements } final PyExpression receiver = callSite.getReceiver(this); - final Map mapping = - PyCallExpressionHelper.mapArguments(callSite, this, context).getMappedParameters(); + final PyCallExpression.PyArgumentsMapping fullMapping = PyCallExpressionHelper.mapArguments(callSite, this, context); + final Map mappedExplicitParameters = fullMapping.getMappedParameters(); - return getCallType(receiver, mapping, context); + final Map allMappedParameters = new LinkedHashMap<>(); + final PyCallableParameter firstImplicit = ContainerUtil.getFirstItem(fullMapping.getImplicitParameters()); + if (receiver != null && firstImplicit != null) { + allMappedParameters.put(receiver, firstImplicit); + } + allMappedParameters.putAll(mappedExplicitParameters); + + return getCallType(receiver, allMappedParameters, context); } @Nullable