mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-12579 "url" function is not processed correctly when imported as alias
This commit is contained in:
@@ -2,11 +2,15 @@ package com.jetbrains.python.nameResolver;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.jetbrains.python.psi.PyElement;
|
||||
import com.jetbrains.python.psi.PyQualifiedNameOwner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Ilya.Kazakevich
|
||||
*/
|
||||
@@ -18,11 +22,11 @@ public final class NameResolverTools {
|
||||
/**
|
||||
* Checks if FQ element name is one of provided names
|
||||
*
|
||||
* @param element element to check
|
||||
* @param namesProvider some enum that has one or more names
|
||||
* @param element element to check
|
||||
* @param namesProviders some enum that has one or more names
|
||||
* @return true if element's fqn is one of names, provided by provider
|
||||
*/
|
||||
public static boolean isName(@NotNull final PyElement element, @NotNull final FQNamesProvider namesProvider) {
|
||||
public static boolean isName(@NotNull final PyElement element, @NotNull final FQNamesProvider... namesProviders) {
|
||||
PyElement elementToCheck = element;
|
||||
final PsiReference reference = element.getReference();
|
||||
if (reference != null) {
|
||||
@@ -33,8 +37,22 @@ public final class NameResolverTools {
|
||||
}
|
||||
if (elementToCheck instanceof PyQualifiedNameOwner) {
|
||||
final String qualifiedName = ((PyQualifiedNameOwner)elementToCheck).getQualifiedName();
|
||||
return ArrayUtil.contains(qualifiedName, namesProvider.getNames());
|
||||
return getNames(namesProviders).contains(qualifiedName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns set of names all providers provide
|
||||
* @param providers providers to check
|
||||
* @return set of names
|
||||
*/
|
||||
@NotNull
|
||||
private static Collection<String> getNames(@NotNull final FQNamesProvider... providers) {
|
||||
final Set<String> result = new HashSet<String>();
|
||||
for (final FQNamesProvider provider : providers) {
|
||||
result.addAll(Arrays.asList(provider.getNames()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,10 +115,10 @@ public interface PyCallExpression extends PyExpression {
|
||||
/**
|
||||
* Checks if the qualified name of the callee matches any of the specified names provided by provider.
|
||||
* @see com.jetbrains.python.nameResolver
|
||||
* @param name provider that provides one or more names to check
|
||||
* @param name providers that provides one or more names to check
|
||||
* @return true if matches, false otherwise
|
||||
*/
|
||||
boolean isCallee(@NotNull FQNamesProvider name);
|
||||
boolean isCallee(@NotNull FQNamesProvider... name);
|
||||
|
||||
/**
|
||||
* Couples function with a flag describing the way it is called.
|
||||
|
||||
@@ -47,7 +47,8 @@ public class PyCallExpressionHelper {
|
||||
/**
|
||||
* TODO: Copy/Paste with {@link com.jetbrains.python.psi.PyArgumentList#addArgument(com.jetbrains.python.psi.PyExpression)}
|
||||
* Adds an argument to the end of argument list.
|
||||
* @param us the arg list
|
||||
*
|
||||
* @param us the arg list
|
||||
* @param expression what to add
|
||||
*/
|
||||
public static void addArgument(PyCallExpression us, PyExpression expression) {
|
||||
@@ -60,7 +61,7 @@ public class PyCallExpressionHelper {
|
||||
* Tries to interpret a call as a call to built-in {@code classmethod} or {@code staticmethod}.
|
||||
*
|
||||
* @param redefiningCall the possible call, generally a result of chasing a chain of assignments
|
||||
* @param us any in-project PSI element, used to determine SDK and ultimately builtins module used to check the wrapping functions
|
||||
* @param us any in-project PSI element, used to determine SDK and ultimately builtins module used to check the wrapping functions
|
||||
* @return a pair of wrapper name and wrapped function; for {@code staticmethod(foo)} it would be ("staticmethod", foo).
|
||||
*/
|
||||
@Nullable
|
||||
@@ -117,8 +118,8 @@ public class PyCallExpressionHelper {
|
||||
return (PyClass)resolved;
|
||||
}
|
||||
else if (resolved instanceof PyFunction) {
|
||||
final PyFunction pyFunction = (PyFunction) resolved;
|
||||
return pyFunction.getContainingClass();
|
||||
final PyFunction pyFunction = (PyFunction)resolved;
|
||||
return pyFunction.getContainingClass();
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -148,11 +149,11 @@ public class PyCallExpressionHelper {
|
||||
}
|
||||
}
|
||||
if (resolved instanceof Callable) {
|
||||
return (Callable) resolved;
|
||||
return (Callable)resolved;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Nullable
|
||||
public static PyCallExpression.PyMarkedCallee resolveCallee(PyCallExpression us, PyResolveContext resolveContext) {
|
||||
@@ -211,19 +212,19 @@ public class PyCallExpressionHelper {
|
||||
}
|
||||
if (resolved instanceof Callable) {
|
||||
PyFunction.Modifier modifier = resolved instanceof PyFunction
|
||||
? ((PyFunction)resolved).getModifier()
|
||||
: null;
|
||||
? ((PyFunction)resolved).getModifier()
|
||||
: null;
|
||||
if (modifier == null && wrappedModifier != null) {
|
||||
modifier = wrappedModifier;
|
||||
}
|
||||
boolean isByInstance = isConstructorCall || isQualifiedByInstance((Callable)resolved, qualifiers, context)
|
||||
|| resolved instanceof PyBoundFunction;
|
||||
PyExpression lastQualifier = qualifiers != null && qualifiers.isEmpty() ? null : qualifiers.get(qualifiers.size()-1);
|
||||
PyExpression lastQualifier = qualifiers != null && qualifiers.isEmpty() ? null : qualifiers.get(qualifiers.size() - 1);
|
||||
boolean isByClass = lastQualifier == null ? false : isQualifiedByClass((Callable)resolved, lastQualifier, context);
|
||||
final Callable callable = (Callable)resolved;
|
||||
|
||||
implicitOffset += getImplicitArgumentCount(callable, modifier, isConstructorCall, isByInstance, isByClass);
|
||||
implicitOffset = implicitOffset < 0? 0: implicitOffset; // wrong source can trigger strange behaviour
|
||||
implicitOffset = implicitOffset < 0 ? 0 : implicitOffset; // wrong source can trigger strange behaviour
|
||||
return new PyCallExpression.PyMarkedCallee(callable, modifier, implicitOffset,
|
||||
resolveResult != null ? resolveResult.isImplicit() : false);
|
||||
}
|
||||
@@ -256,11 +257,11 @@ public class PyCallExpressionHelper {
|
||||
/**
|
||||
* Finds how many arguments are implicit in a given call.
|
||||
*
|
||||
* @param callable resolved method which is being called; non-methods immediately return 0.
|
||||
* @param flags set of flags for the call
|
||||
* @param isByInstance true if the call is known to be by instance (not by class).
|
||||
* @param callable resolved method which is being called; non-methods immediately return 0.
|
||||
* @param flags set of flags for the call
|
||||
* @param isByInstance true if the call is known to be by instance (not by class).
|
||||
* @return a non-negative number of parameters that are implicit to this call. E.g. for a typical method call 1 is returned
|
||||
* because one parameter ('self') is implicit.
|
||||
* because one parameter ('self') is implicit.
|
||||
*/
|
||||
private static int getImplicitArgumentCount(
|
||||
Callable callable,
|
||||
@@ -451,7 +452,7 @@ public class PyCallExpressionHelper {
|
||||
}
|
||||
final PyType providedType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(target, context, call);
|
||||
if (providedType instanceof PyCallableType) {
|
||||
return ((PyCallableType) providedType).getCallType(context, (PyReferenceExpression)callee);
|
||||
return ((PyCallableType)providedType).getCallType(context, (PyReferenceExpression)callee);
|
||||
}
|
||||
if (target instanceof Callable) {
|
||||
final Callable callable = (Callable)target;
|
||||
@@ -571,13 +572,14 @@ public class PyCallExpressionHelper {
|
||||
|
||||
/**
|
||||
* Checks if expression callee's name matches one of names, provided by appropriate {@link com.jetbrains.python.nameResolver.FQNamesProvider}
|
||||
* @see com.jetbrains.python.nameResolver
|
||||
* @param expression call expression
|
||||
* @param namesProvider name provider to check name against
|
||||
*
|
||||
* @param expression call expression
|
||||
* @param namesProviders name providers to check name against
|
||||
* @return true if matches
|
||||
* @see com.jetbrains.python.nameResolver
|
||||
*/
|
||||
public static boolean isCallee(@NotNull final PyCallExpression expression, @NotNull final FQNamesProvider namesProvider) {
|
||||
public static boolean isCallee(@NotNull final PyCallExpression expression, @NotNull final FQNamesProvider... namesProviders) {
|
||||
final PyExpression callee = expression.getCallee();
|
||||
return (callee != null) && NameResolverTools.isName(callee, namesProvider);
|
||||
return (callee != null) && NameResolverTools.isName(callee, namesProviders);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCallee(@NotNull final FQNamesProvider name) {
|
||||
public boolean isCallee(@NotNull final FQNamesProvider... name) {
|
||||
return PyCallExpressionHelper.isCallee(this, name);
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ public class PyDecoratorImpl extends StubBasedPsiElementBase<PyDecoratorStub> im
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCallee(@NotNull final FQNamesProvider name) {
|
||||
public boolean isCallee(@NotNull final FQNamesProvider... name) {
|
||||
return PyCallExpressionHelper.isCallee(this, name);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user