mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Changed the API for arguments-paramters mapping to PyCallExpression.mapArguments()
Moved CallArgumentsMappingImpl to PyCallExpressionHelper.mapArguments() and switched from returning a map of mapped parameters to a class that will contain more info about mappings.
This commit is contained in:
@@ -22,6 +22,8 @@ import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents an entire call expression, like <tt>foo()</tt> or <tt>foo.bar[1]('x')</tt>.
|
||||
*/
|
||||
@@ -114,6 +116,9 @@ public interface PyCallExpression extends PyCallSiteExpression {
|
||||
@Nullable
|
||||
PyMarkedCallee resolveCallee(PyResolveContext resolveContext, int implicitOffset);
|
||||
|
||||
@NotNull
|
||||
PyArgumentsMapping mapArguments(@NotNull PyResolveContext resolveContext);
|
||||
|
||||
/**
|
||||
* Checks if the unqualified name of the callee matches any of the specified names
|
||||
*
|
||||
@@ -122,7 +127,6 @@ public interface PyCallExpression extends PyCallSiteExpression {
|
||||
*/
|
||||
boolean isCalleeText(@NotNull String... nameCandidates);
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the qualified name of the callee matches any of the specified names provided by provider.
|
||||
* @see com.jetbrains.python.nameResolver
|
||||
@@ -131,6 +135,26 @@ public interface PyCallExpression extends PyCallSiteExpression {
|
||||
*/
|
||||
boolean isCallee(@NotNull FQNamesProvider... name);
|
||||
|
||||
class PyArgumentsMapping {
|
||||
@Nullable private final PyMarkedCallee myCallee;
|
||||
@NotNull private final Map<PyExpression, PyNamedParameter> myMappedParameters;
|
||||
|
||||
public PyArgumentsMapping(@Nullable PyMarkedCallee markedCallee, @NotNull Map<PyExpression, PyNamedParameter> mappedParameters) {
|
||||
myCallee = markedCallee;
|
||||
myMappedParameters = mappedParameters;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PyMarkedCallee getMarkedCallee() {
|
||||
return myCallee;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Map<PyExpression, PyNamedParameter> getMappedParameters() {
|
||||
return myMappedParameters;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Couples function with a flag describing the way it is called.
|
||||
*/
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.intellij.psi.PsiReference;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.inspections.quickfix.RemoveArgumentEqualDefaultQuickFix;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.CallArgumentsMappingImpl;
|
||||
import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import com.jetbrains.python.psi.types.PyClassType;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
@@ -98,9 +97,9 @@ public class PyArgumentEqualDefaultInspection extends PyInspection {
|
||||
}
|
||||
|
||||
private void checkArguments(PyCallExpression callExpr, PyExpression[] arguments) {
|
||||
final Map<PyExpression, PyNamedParameter> mapping = CallArgumentsMappingImpl.map(callExpr, getResolveContext());
|
||||
final PyCallExpression.PyArgumentsMapping mapping = callExpr.mapArguments(getResolveContext());
|
||||
Set<PyExpression> problemElements = new HashSet<PyExpression>();
|
||||
for (Map.Entry<PyExpression, PyNamedParameter> e : mapping.entrySet()) {
|
||||
for (Map.Entry<PyExpression, PyNamedParameter> e : mapping.getMappedParameters().entrySet()) {
|
||||
PyExpression defaultValue = e.getValue().getDefaultValue();
|
||||
if (defaultValue != null) {
|
||||
PyExpression key = e.getKey();
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.CallArgumentsMappingImpl;
|
||||
import com.jetbrains.python.psi.types.PyClassType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
@@ -91,13 +90,13 @@ public class PyCallByClassInspection extends PyInspection {
|
||||
PyClass qual_class = qual_class_type.getPyClass();
|
||||
final PyArgumentList arglist = call.getArgumentList();
|
||||
if (arglist != null) {
|
||||
final PyCallExpression.PyMarkedCallee markedCallee = call.resolveCallee(getResolveContext());
|
||||
final PyCallExpression.PyArgumentsMapping mapping = call.mapArguments(getResolveContext());
|
||||
final PyCallExpression.PyMarkedCallee markedCallee = mapping.getMarkedCallee();
|
||||
if (markedCallee != null && markedCallee.getModifier() != STATICMETHOD) {
|
||||
final List<PyParameter> params = PyUtil.getParameters(markedCallee.getCallable(), myTypeEvalContext);
|
||||
if (params.size() > 0 && params.get(0) instanceof PyNamedParameter) {
|
||||
PyNamedParameter first_param = (PyNamedParameter)params.get(0);
|
||||
final Map<PyExpression, PyNamedParameter> mapping = CallArgumentsMappingImpl.map(call, getResolveContext());
|
||||
for (Map.Entry<PyExpression, PyNamedParameter> entry : mapping.entrySet()) {
|
||||
for (Map.Entry<PyExpression, PyNamedParameter> entry : mapping.getMappedParameters().entrySet()) {
|
||||
// we ignore *arg and **arg which we cannot analyze
|
||||
if (entry.getValue() == first_param) {
|
||||
PyExpression first_arg = entry.getKey();
|
||||
|
||||
@@ -34,7 +34,6 @@ import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.inspections.quickfix.PyUpdatePropertySignatureQuickFix;
|
||||
import com.jetbrains.python.inspections.quickfix.RenameParameterQuickFix;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.CallArgumentsMappingImpl;
|
||||
import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import com.jetbrains.python.psi.types.PyClassType;
|
||||
import com.jetbrains.python.psi.types.PyNoneType;
|
||||
@@ -121,8 +120,8 @@ public class PyPropertyDefinitionInspection extends PyInspection {
|
||||
final PyArgumentList arglist = call.getArgumentList();
|
||||
assert arglist != null : "Property call has null arglist";
|
||||
// we assume fget, fset, fdel, doc names
|
||||
final Map<PyExpression, PyNamedParameter> mapping = CallArgumentsMappingImpl.map(call, getResolveContext());
|
||||
for (Map.Entry<PyExpression, PyNamedParameter> entry : mapping.entrySet()) {
|
||||
final PyCallExpression.PyArgumentsMapping mapping = call.mapArguments(getResolveContext());
|
||||
for (Map.Entry<PyExpression, PyNamedParameter> entry : mapping.getMappedParameters().entrySet()) {
|
||||
final String paramName = entry.getValue().getName();
|
||||
PyExpression argument = PyUtil.peelArgument(entry.getKey());
|
||||
checkPropertyCallArgument(paramName, argument, node.getContainingFile());
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.documentation.PyDocumentationSettings;
|
||||
import com.jetbrains.python.editor.PythonDocCommentUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.CallArgumentsMappingImpl;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.refactoring.PyRefactoringUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -64,9 +63,9 @@ public class PyRemoveParameterQuickFix implements LocalQuickFix {
|
||||
if (callExpression instanceof PyCallExpression) {
|
||||
final PyArgumentList argumentList = ((PyCallExpression)callExpression).getArgumentList();
|
||||
if (argumentList != null) {
|
||||
final Map<PyExpression, PyNamedParameter> mapping = CallArgumentsMappingImpl.map((PyCallExpression)callExpression,
|
||||
PyResolveContext.noImplicits());
|
||||
for (Map.Entry<PyExpression, PyNamedParameter> parameterEntry : mapping.entrySet()) {
|
||||
final PyResolveContext resolveContext = PyResolveContext.noImplicits();
|
||||
final PyCallExpression.PyArgumentsMapping mapping = ((PyCallExpression)callExpression).mapArguments(resolveContext);
|
||||
for (Map.Entry<PyExpression, PyNamedParameter> parameterEntry : mapping.getMappedParameters().entrySet()) {
|
||||
if (parameterEntry.getValue().equals(element)) {
|
||||
parameterEntry.getKey().delete();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.jetbrains.python.psi.impl;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.types.PyTupleType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
@@ -55,180 +54,6 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
|
||||
myArgumentList = arglist;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Map<PyExpression, PyNamedParameter> map(@NotNull PyCallExpression callExpression,
|
||||
@NotNull PyResolveContext resolveContext) {
|
||||
return map(callExpression, 0, resolveContext);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Map<PyExpression, PyNamedParameter> map(@NotNull PyCallExpression callExpression,
|
||||
int implicitArgumentOffset,
|
||||
@NotNull PyResolveContext resolveContext) {
|
||||
final Map<PyExpression, PyNamedParameter> results = new LinkedHashMap<PyExpression, PyNamedParameter>();
|
||||
final PyArgumentList argumentList = callExpression.getArgumentList();
|
||||
final PyCallExpression.PyMarkedCallee markedCallee = callExpression.resolveCallee(resolveContext, implicitArgumentOffset);
|
||||
if (markedCallee != null && argumentList != null) {
|
||||
final TypeEvalContext context = resolveContext.getTypeEvalContext();
|
||||
final List<PyParameter> allParameters = PyUtil.getParameters(markedCallee.getCallable(), context);
|
||||
final List<PyParameter> parameters = dropImplicitParameters(allParameters, markedCallee.getImplicitOffset());
|
||||
final List<PyExpression> arguments = Arrays.asList(argumentList.getArguments());
|
||||
|
||||
final List<PyExpression> positionalArguments = filterPositionalArguments(arguments);
|
||||
final List<PyKeywordArgument> keywordArguments = filterKeywordArguments(arguments);
|
||||
final List<PyExpression> variadicPositionalArguments = filterVariadicPositionalArguments(arguments);
|
||||
final List<PyExpression> variadicKeywordArguments = filterVariadicKeywordArguments(arguments);
|
||||
|
||||
boolean seenSingleStar = false;
|
||||
final List<PyParameter> unmappedParameters = new ArrayList<PyParameter>();
|
||||
for (PyParameter parameter : parameters) {
|
||||
if (parameter instanceof PyNamedParameter) {
|
||||
final PyNamedParameter namedParameter = (PyNamedParameter)parameter;
|
||||
final String parameterName = namedParameter.getName();
|
||||
if (namedParameter.isPositionalContainer()) {
|
||||
if (variadicPositionalArguments.size() == 1) {
|
||||
results.put(variadicPositionalArguments.remove(0), namedParameter);
|
||||
}
|
||||
else {
|
||||
positionalArguments.clear();
|
||||
variadicPositionalArguments.clear();
|
||||
}
|
||||
}
|
||||
else if (namedParameter.isKeywordContainer()) {
|
||||
if (variadicKeywordArguments.size() == 1) {
|
||||
results.put(variadicKeywordArguments.remove(0), namedParameter);
|
||||
}
|
||||
else {
|
||||
keywordArguments.clear();
|
||||
variadicKeywordArguments.clear();
|
||||
}
|
||||
}
|
||||
else if (seenSingleStar) {
|
||||
final PyExpression keywordArgument = removeKeywordArgument(keywordArguments, parameterName);
|
||||
if (keywordArgument != null) {
|
||||
results.put(keywordArgument, namedParameter);
|
||||
}
|
||||
else if (variadicKeywordArguments.isEmpty()) {
|
||||
unmappedParameters.add(namedParameter);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!positionalArguments.isEmpty()) {
|
||||
final PyExpression positionalArgument = next(positionalArguments);
|
||||
if (positionalArgument != null) {
|
||||
results.put(positionalArgument, namedParameter);
|
||||
}
|
||||
else {
|
||||
unmappedParameters.add(namedParameter);
|
||||
}
|
||||
}
|
||||
else {
|
||||
final PyKeywordArgument keywordArgument = removeKeywordArgument(keywordArguments, parameterName);
|
||||
if (keywordArgument != null) {
|
||||
results.put(keywordArgument, namedParameter);
|
||||
}
|
||||
else if (variadicPositionalArguments.isEmpty() || variadicKeywordArguments.isEmpty()) {
|
||||
unmappedParameters.add(namedParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (parameter instanceof PyTupleParameter) {
|
||||
unmappedParameters.add(parameter);
|
||||
}
|
||||
else if (parameter instanceof PySingleStarParameter) {
|
||||
seenSingleStar = true;
|
||||
}
|
||||
else {
|
||||
unmappedParameters.add(parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PyKeywordArgument removeKeywordArgument(@NotNull List<PyKeywordArgument> arguments, @Nullable String name) {
|
||||
PyKeywordArgument result = null;
|
||||
for (PyKeywordArgument argument : arguments) {
|
||||
final String keyword = argument.getKeyword();
|
||||
if (keyword != null && keyword.equals(name)) {
|
||||
result = argument;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result != null) {
|
||||
arguments.remove(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PyExpression> filterPositionalArguments(@NotNull List<PyExpression> arguments) {
|
||||
final List<PyExpression> results = new ArrayList<PyExpression>();
|
||||
for (PyExpression argument : arguments) {
|
||||
if (isPositionalArg(argument)) {
|
||||
results.add(argument);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PyKeywordArgument> filterKeywordArguments(@NotNull List<PyExpression> arguments) {
|
||||
final List<PyKeywordArgument> results = new ArrayList<PyKeywordArgument>();
|
||||
for (PyExpression argument : arguments) {
|
||||
if (argument instanceof PyKeywordArgument) {
|
||||
results.add((PyKeywordArgument)argument);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PyExpression> filterVariadicPositionalArguments(@NotNull List<PyExpression> arguments) {
|
||||
final List<PyExpression> results = new ArrayList<PyExpression>();
|
||||
for (PyExpression argument : arguments) {
|
||||
if (argument != null && isVariadicPositionalArgument(argument)) {
|
||||
results.add(argument);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PyExpression> filterVariadicKeywordArguments(@NotNull List<PyExpression> arguments) {
|
||||
final List<PyExpression> results = new ArrayList<PyExpression>();
|
||||
for (PyExpression argument : arguments) {
|
||||
if (argument != null && isVariadicKeywordArgument(argument)) {
|
||||
results.add(argument);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static boolean isVariadicKeywordArgument(@NotNull PyExpression argument) {
|
||||
return argument instanceof PyStarArgument && ((PyStarArgument)argument).isKeyword();
|
||||
}
|
||||
|
||||
private static boolean isVariadicPositionalArgument(@NotNull PyExpression argument) {
|
||||
return argument instanceof PyStarArgument && !((PyStarArgument)argument).isKeyword();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static <T> T next(@NotNull List<T> list) {
|
||||
return list.isEmpty() ? null : list.remove(0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PyParameter> dropImplicitParameters(@NotNull List<PyParameter> parameters, int offset) {
|
||||
final ArrayList<PyParameter> results = new ArrayList<PyParameter>(parameters);
|
||||
for (int i = 0; i < offset && !results.isEmpty(); i++) {
|
||||
results.remove(0);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps arguments of a call to parameters of a callee.
|
||||
* must contain already resolved callee with flags set appropriately.
|
||||
@@ -423,11 +248,11 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
|
||||
// NOTE: ignores the structure of nested-tuple params!
|
||||
if (tuple_par != null) {
|
||||
i = 0;
|
||||
while (i < arguments.length && mapped_args.contains(arguments[i]) && isPositionalArg(arguments[i])) {
|
||||
while (i < arguments.length && mapped_args.contains(arguments[i]) && PyCallExpressionHelper.isPositionalArgument(arguments[i])) {
|
||||
i += 1; // skip first mapped args
|
||||
}
|
||||
if (i < arguments.length && isPositionalArg(arguments[i])) {
|
||||
while (i < arguments.length && !mapped_args.contains(arguments[i]) && isPositionalArg(arguments[i])) {
|
||||
if (i < arguments.length && PyCallExpressionHelper.isPositionalArgument(arguments[i])) {
|
||||
while (i < arguments.length && !mapped_args.contains(arguments[i]) && PyCallExpressionHelper.isPositionalArgument(arguments[i])) {
|
||||
myPlainMappedParams.put(arguments[i], tuple_par);
|
||||
mapped_args.add(arguments[i]);
|
||||
i += 1;
|
||||
@@ -550,10 +375,6 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPositionalArg(PyExpression arg) {
|
||||
return !(arg instanceof PyKeywordArgument) && !(arg instanceof PyStarArgument);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A mapping argument->parameter for non-starred arguments (but includes starred parameters).
|
||||
*/
|
||||
|
||||
@@ -631,4 +631,175 @@ public class PyCallExpressionHelper {
|
||||
final PyExpression callee = expression.getCallee();
|
||||
return (callee != null) && NameResolverTools.isName(callee, namesProviders);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PyCallExpression.PyArgumentsMapping mapArguments(@NotNull PyCallExpression callExpression,
|
||||
@NotNull PyResolveContext resolveContext) {
|
||||
final Map<PyExpression, PyNamedParameter> mappedParameters = new LinkedHashMap<PyExpression, PyNamedParameter>();
|
||||
final PyArgumentList argumentList = callExpression.getArgumentList();
|
||||
final PyCallExpression.PyMarkedCallee markedCallee = callExpression.resolveCallee(resolveContext);
|
||||
if (markedCallee != null && argumentList != null) {
|
||||
final TypeEvalContext context = resolveContext.getTypeEvalContext();
|
||||
final List<PyParameter> allParameters = PyUtil.getParameters(markedCallee.getCallable(), context);
|
||||
final List<PyParameter> parameters = dropImplicitParameters(allParameters, markedCallee.getImplicitOffset());
|
||||
final List<PyExpression> arguments = Arrays.asList(argumentList.getArguments());
|
||||
|
||||
final List<PyExpression> positionalArguments = filterPositionalArguments(arguments);
|
||||
final List<PyKeywordArgument> keywordArguments = filterKeywordArguments(arguments);
|
||||
final List<PyExpression> variadicPositionalArguments = filterVariadicPositionalArguments(arguments);
|
||||
final List<PyExpression> variadicKeywordArguments = filterVariadicKeywordArguments(arguments);
|
||||
|
||||
boolean seenSingleStar = false;
|
||||
final List<PyParameter> unmappedParameters = new ArrayList<PyParameter>();
|
||||
for (PyParameter parameter : parameters) {
|
||||
if (parameter instanceof PyNamedParameter) {
|
||||
final PyNamedParameter namedParameter = (PyNamedParameter)parameter;
|
||||
final String parameterName = namedParameter.getName();
|
||||
if (namedParameter.isPositionalContainer()) {
|
||||
if (variadicPositionalArguments.size() == 1) {
|
||||
mappedParameters.put(variadicPositionalArguments.remove(0), namedParameter);
|
||||
}
|
||||
else {
|
||||
positionalArguments.clear();
|
||||
variadicPositionalArguments.clear();
|
||||
}
|
||||
}
|
||||
else if (namedParameter.isKeywordContainer()) {
|
||||
if (variadicKeywordArguments.size() == 1) {
|
||||
mappedParameters.put(variadicKeywordArguments.remove(0), namedParameter);
|
||||
}
|
||||
else {
|
||||
keywordArguments.clear();
|
||||
variadicKeywordArguments.clear();
|
||||
}
|
||||
}
|
||||
else if (seenSingleStar) {
|
||||
final PyExpression keywordArgument = removeKeywordArgument(keywordArguments, parameterName);
|
||||
if (keywordArgument != null) {
|
||||
mappedParameters.put(keywordArgument, namedParameter);
|
||||
}
|
||||
else if (variadicKeywordArguments.isEmpty()) {
|
||||
unmappedParameters.add(namedParameter);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!positionalArguments.isEmpty()) {
|
||||
final PyExpression positionalArgument = next(positionalArguments);
|
||||
if (positionalArgument != null) {
|
||||
mappedParameters.put(positionalArgument, namedParameter);
|
||||
}
|
||||
else {
|
||||
unmappedParameters.add(namedParameter);
|
||||
}
|
||||
}
|
||||
else {
|
||||
final PyKeywordArgument keywordArgument = removeKeywordArgument(keywordArguments, parameterName);
|
||||
if (keywordArgument != null) {
|
||||
mappedParameters.put(keywordArgument, namedParameter);
|
||||
}
|
||||
else if (variadicPositionalArguments.isEmpty() || variadicKeywordArguments.isEmpty()) {
|
||||
unmappedParameters.add(namedParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (parameter instanceof PyTupleParameter) {
|
||||
unmappedParameters.add(parameter);
|
||||
}
|
||||
else if (parameter instanceof PySingleStarParameter) {
|
||||
seenSingleStar = true;
|
||||
}
|
||||
else {
|
||||
unmappedParameters.add(parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new PyCallExpression.PyArgumentsMapping(markedCallee, mappedParameters);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PyKeywordArgument removeKeywordArgument(@NotNull List<PyKeywordArgument> arguments, @Nullable String name) {
|
||||
PyKeywordArgument result = null;
|
||||
for (PyKeywordArgument argument : arguments) {
|
||||
final String keyword = argument.getKeyword();
|
||||
if (keyword != null && keyword.equals(name)) {
|
||||
result = argument;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result != null) {
|
||||
arguments.remove(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PyExpression> filterPositionalArguments(@NotNull List<PyExpression> arguments) {
|
||||
final List<PyExpression> results = new ArrayList<PyExpression>();
|
||||
for (PyExpression argument : arguments) {
|
||||
if (isPositionalArgument(argument)) {
|
||||
results.add(argument);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PyKeywordArgument> filterKeywordArguments(@NotNull List<PyExpression> arguments) {
|
||||
final List<PyKeywordArgument> results = new ArrayList<PyKeywordArgument>();
|
||||
for (PyExpression argument : arguments) {
|
||||
if (argument instanceof PyKeywordArgument) {
|
||||
results.add((PyKeywordArgument)argument);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PyExpression> filterVariadicPositionalArguments(@NotNull List<PyExpression> arguments) {
|
||||
final List<PyExpression> results = new ArrayList<PyExpression>();
|
||||
for (PyExpression argument : arguments) {
|
||||
if (argument != null && isVariadicPositionalArgument(argument)) {
|
||||
results.add(argument);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PyExpression> filterVariadicKeywordArguments(@NotNull List<PyExpression> arguments) {
|
||||
final List<PyExpression> results = new ArrayList<PyExpression>();
|
||||
for (PyExpression argument : arguments) {
|
||||
if (argument != null && isVariadicKeywordArgument(argument)) {
|
||||
results.add(argument);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static boolean isVariadicKeywordArgument(@NotNull PyExpression argument) {
|
||||
return argument instanceof PyStarArgument && ((PyStarArgument)argument).isKeyword();
|
||||
}
|
||||
|
||||
private static boolean isVariadicPositionalArgument(@NotNull PyExpression argument) {
|
||||
return argument instanceof PyStarArgument && !((PyStarArgument)argument).isKeyword();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static <T> T next(@NotNull List<T> list) {
|
||||
return list.isEmpty() ? null : list.remove(0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PyParameter> dropImplicitParameters(@NotNull List<PyParameter> parameters, int offset) {
|
||||
final ArrayList<PyParameter> results = new ArrayList<PyParameter>(parameters);
|
||||
for (int i = 0; i < offset && !results.isEmpty(); i++) {
|
||||
results.remove(0);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
static boolean isPositionalArgument(@Nullable PyExpression argument) {
|
||||
return !(argument instanceof PyKeywordArgument) && !(argument instanceof PyStarArgument);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +102,12 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
|
||||
return PyCallExpressionHelper.resolveCallee(this, resolveContext, offset);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PyArgumentsMapping mapArguments(@NotNull PyResolveContext resolveContext) {
|
||||
return PyCallExpressionHelper.mapArguments(this, resolveContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCalleeText(@NotNull String... nameCandidates) {
|
||||
return PyCallExpressionHelper.isCalleeText(this, nameCandidates);
|
||||
|
||||
@@ -157,6 +157,12 @@ public class PyDecoratorImpl extends StubBasedPsiElementBase<PyDecoratorStub> im
|
||||
return callee;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PyArgumentsMapping mapArguments(@NotNull PyResolveContext resolveContext) {
|
||||
return PyCallExpressionHelper.mapArguments(this, resolveContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PyCallable resolveCalleeFunction(PyResolveContext resolveContext) {
|
||||
return PyCallExpressionHelper.resolveCalleeFunction(this, resolveContext);
|
||||
|
||||
@@ -269,8 +269,8 @@ public class PyNamedParameterImpl extends PyBaseElementImpl<PyNamedParameterStub
|
||||
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
|
||||
final PyArgumentList argumentList = call.getArgumentList();
|
||||
if (argumentList != null) {
|
||||
final Map<PyExpression, PyNamedParameter> mapping = CallArgumentsMappingImpl.map(call, resolveContext);
|
||||
for (Map.Entry<PyExpression, PyNamedParameter> entry : mapping.entrySet()) {
|
||||
final PyCallExpression.PyArgumentsMapping mapping = call.mapArguments(resolveContext);
|
||||
for (Map.Entry<PyExpression, PyNamedParameter> entry : mapping.getMappedParameters().entrySet()) {
|
||||
if (entry.getValue() == PyNamedParameterImpl.this) {
|
||||
final PyExpression argument = entry.getKey();
|
||||
if (argument != null) {
|
||||
@@ -393,8 +393,8 @@ public class PyNamedParameterImpl extends PyBaseElementImpl<PyNamedParameterStub
|
||||
}
|
||||
}
|
||||
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
|
||||
final Map<PyExpression, PyNamedParameter> mapping = CallArgumentsMappingImpl.map(callExpression, resolveContext);
|
||||
for (Map.Entry<PyExpression, PyNamedParameter> entry : mapping.entrySet()) {
|
||||
final PyCallExpression.PyArgumentsMapping mapping = callExpression.mapArguments(resolveContext);
|
||||
for (Map.Entry<PyExpression, PyNamedParameter> entry : mapping.getMappedParameters().entrySet()) {
|
||||
if (entry.getKey() == element) {
|
||||
return entry.getValue();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.intellij.util.ArrayUtil;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.codeInsight.PyCustomMember;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.CallArgumentsMappingImpl;
|
||||
import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.resolve.RatedResolveResult;
|
||||
@@ -458,8 +457,8 @@ public class PyTypeChecker {
|
||||
final PyArgumentList args = call.getArgumentList();
|
||||
if (args != null) {
|
||||
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
|
||||
final Map<PyExpression, PyNamedParameter> arguments = CallArgumentsMappingImpl.map(call, resolveContext);
|
||||
final PyCallExpression.PyMarkedCallee markedCallee = call.resolveCallee(resolveContext);
|
||||
final PyCallExpression.PyArgumentsMapping mapping = call.mapArguments(resolveContext);
|
||||
final PyCallExpression.PyMarkedCallee markedCallee = mapping.getMarkedCallee();
|
||||
if (markedCallee != null) {
|
||||
final PyCallable callable = markedCallee.getCallable();
|
||||
if (callable instanceof PyFunction) {
|
||||
@@ -474,7 +473,7 @@ public class PyTypeChecker {
|
||||
else {
|
||||
receiver = null;
|
||||
}
|
||||
return new AnalyzeCallResults(callable, receiver, arguments);
|
||||
return new AnalyzeCallResults(callable, receiver, mapping.getMappedParameters());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,6 @@ import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.PythonStringUtil;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.CallArgumentsMappingImpl;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.types.PyNoneType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
@@ -229,10 +228,9 @@ abstract public class IntroduceHandler implements RefactoringActionHandler {
|
||||
final PyCallExpression callExpr = argList.getCallExpression();
|
||||
if (callExpr != null) {
|
||||
final PyResolveContext resolveContext = PyResolveContext.noImplicits();
|
||||
final PyCallExpression.PyMarkedCallee markedCallee = callExpr.resolveCallee(resolveContext);
|
||||
if (markedCallee != null) {
|
||||
final Map<PyExpression, PyNamedParameter> mapping = CallArgumentsMappingImpl.map(callExpr, resolveContext);
|
||||
final PyNamedParameter namedParameter = mapping.get(expression);
|
||||
final PyCallExpression.PyArgumentsMapping mapping = callExpr.mapArguments(resolveContext);
|
||||
if (mapping.getMarkedCallee() != null) {
|
||||
final PyNamedParameter namedParameter = mapping.getMappedParameters().get(expression);
|
||||
if (namedParameter != null) {
|
||||
candidates.add(namedParameter.getName());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user