mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Move commonly used overload-related functions to PyiUtil.
This commit is contained in:
committed by
Semyon Proshev
parent
947930f6c9
commit
fde57da527
@@ -26,7 +26,7 @@ import com.jetbrains.python.psi.PyFile
|
||||
import com.jetbrains.python.psi.PyFunction
|
||||
import com.jetbrains.python.psi.PyUtil
|
||||
import com.jetbrains.python.pyi.PyiFile
|
||||
import com.jetbrains.python.pyi.PyiTypeProvider
|
||||
import com.jetbrains.python.pyi.PyiUtil
|
||||
import java.util.*
|
||||
|
||||
class PyOverloadsInspection : PyInspection() {
|
||||
@@ -64,9 +64,9 @@ class PyOverloadsInspection : PyInspection() {
|
||||
}
|
||||
|
||||
private fun processSameNameFunctions(owner: ScopeOwner, functions: List<PyFunction>) {
|
||||
if (functions.find { PyiTypeProvider.isOverload(it, myTypeEvalContext) } == null) return
|
||||
if (functions.find { PyiUtil.isOverload(it, myTypeEvalContext) } == null) return
|
||||
|
||||
val implementation = functions.lastOrNull { !PyiTypeProvider.isOverload(it, myTypeEvalContext) }
|
||||
val implementation = functions.lastOrNull { !PyiUtil.isOverload(it, myTypeEvalContext) }
|
||||
|
||||
if (implementation == null) {
|
||||
functions
|
||||
@@ -101,7 +101,7 @@ class PyOverloadsInspection : PyInspection() {
|
||||
|
||||
private fun isIncompatibleOverload(implementation: PyFunction, overload: PyFunction): Boolean {
|
||||
return implementation != overload &&
|
||||
PyiTypeProvider.isOverload(overload, myTypeEvalContext) &&
|
||||
PyiUtil.isOverload(overload, myTypeEvalContext) &&
|
||||
!PyUtil.isSignatureCompatibleTo(implementation, overload, myTypeEvalContext)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.inspections.quickfix.PyRenameElementQuickFix;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.pyi.PyiTypeProvider;
|
||||
import com.jetbrains.python.pyi.PyiUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -138,7 +138,7 @@ public class PyRedeclarationInspection extends PyInspection {
|
||||
readElementRef.set(originalElement);
|
||||
}
|
||||
if (rwInstruction.getAccess().isWriteAccess() && originalElement != element) {
|
||||
if (element instanceof PyCallable && isOverload(originalElement)) {
|
||||
if (PyiUtil.isOverload(originalElement, myTypeEvalContext)) {
|
||||
return ControlFlowUtil.Operation.NEXT;
|
||||
}
|
||||
else {
|
||||
@@ -167,10 +167,6 @@ public class PyRedeclarationInspection extends PyInspection {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isOverload(@NotNull PsiElement element) {
|
||||
return element instanceof PyCallable && PyiTypeProvider.isOverload((PyCallable)element, myTypeEvalContext);
|
||||
}
|
||||
|
||||
private static boolean suggestRename(@NotNull PsiNameIdentifierOwner element, @NotNull PsiElement originalElement) {
|
||||
// Target expressions in the same scope are treated as the same variable
|
||||
if ((element instanceof PyTargetExpression) && originalElement instanceof PyTargetExpression) {
|
||||
|
||||
@@ -46,7 +46,7 @@ import com.jetbrains.python.psi.impl.PyImportStatementNavigator;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.search.PyOverridingMethodsSearch;
|
||||
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
|
||||
import com.jetbrains.python.pyi.PyiTypeProvider;
|
||||
import com.jetbrains.python.pyi.PyiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -79,7 +79,7 @@ public class PyUnusedLocalInspectionVisitor extends PyInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitPyFunction(final PyFunction node) {
|
||||
if (!PyiTypeProvider.isOverload(node, myTypeEvalContext)) {
|
||||
if (!PyiUtil.isOverload(node, myTypeEvalContext)) {
|
||||
processScope(node);
|
||||
}
|
||||
}
|
||||
@@ -451,12 +451,14 @@ public class PyUnusedLocalInspectionVisitor extends PyInspectionVisitor {
|
||||
}
|
||||
|
||||
private static class ReplaceWithWildCard implements LocalQuickFix {
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return PyBundle.message("INSP.unused.locals.replace.with.wildcard");
|
||||
}
|
||||
|
||||
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement psiElement = descriptor.getPsiElement();
|
||||
final PyFile pyFile = (PyFile) PyElementGenerator.getInstance(psiElement.getProject()).createDummyFile(LanguageLevel.getDefault(),
|
||||
"for _ in tuples:\n pass"
|
||||
|
||||
@@ -30,7 +30,7 @@ import com.jetbrains.python.psi.PyParameter;
|
||||
import com.jetbrains.python.psi.PyStringLiteralExpression;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import com.jetbrains.python.pyi.PyiTypeProvider;
|
||||
import com.jetbrains.python.pyi.PyiUtil;
|
||||
import com.jetbrains.python.refactoring.PyRefactoringUtil;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -79,7 +79,7 @@ public class PyRemoveParameterQuickFix implements LocalQuickFix {
|
||||
|
||||
if (parameterName != null) {
|
||||
StreamEx
|
||||
.of(PyiTypeProvider.getOverloads(function, myContext))
|
||||
.of(PyiUtil.getOverloads(function, myContext))
|
||||
.map(overload -> overload.getParameterList().getParameters())
|
||||
.map(parameters -> ContainerUtil.find(parameters, overloadParameter -> parameterName.equals(overloadParameter.getName())))
|
||||
.nonNull()
|
||||
|
||||
@@ -32,7 +32,7 @@ import com.jetbrains.python.psi.resolve.QualifiedRatedResolveResult;
|
||||
import com.jetbrains.python.psi.resolve.QualifiedResolveResult;
|
||||
import com.jetbrains.python.psi.resolve.RatedResolveResult;
|
||||
import com.jetbrains.python.psi.types.*;
|
||||
import com.jetbrains.python.pyi.PyiTypeProvider;
|
||||
import com.jetbrains.python.pyi.PyiUtil;
|
||||
import com.jetbrains.python.toolbox.Maybe;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -859,7 +859,7 @@ public class PyCallExpressionHelper {
|
||||
boolean containsImplementations = false;
|
||||
|
||||
for (PyCallExpression.PyRatedMarkedCallee callee : callees) {
|
||||
final boolean overload = PyiTypeProvider.isOverload(callee.getElement(), context);
|
||||
final boolean overload = PyiUtil.isOverload(callee.getElement(), context);
|
||||
containsOverloads |= overload;
|
||||
containsImplementations |= !overload;
|
||||
|
||||
@@ -876,7 +876,7 @@ public class PyCallExpressionHelper {
|
||||
return callees.stream();
|
||||
}
|
||||
|
||||
return callees.stream().filter(callee -> PyiTypeProvider.isOverload(callee.getElement(), context));
|
||||
return callees.stream().filter(callee -> PyiUtil.isOverload(callee.getElement(), context));
|
||||
}
|
||||
|
||||
public static class ArgumentMappingResults {
|
||||
|
||||
@@ -54,14 +54,14 @@ import com.jetbrains.python.psi.stubs.PyFileStub;
|
||||
import com.jetbrains.python.psi.types.PyModuleType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import com.jetbrains.python.pyi.PyiTypeProvider;
|
||||
import one.util.streamex.StreamEx;
|
||||
import com.jetbrains.python.pyi.PyiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
|
||||
protected PyType myType;
|
||||
@@ -183,7 +183,10 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
|
||||
}
|
||||
}
|
||||
|
||||
return containsOverloads(resultList, typeEvalContext) ? moveOverloadsBack(resultList, typeEvalContext) : resultList;
|
||||
final Function<RatedResolveResult, PsiElement> mapper = RatedResolveResult::getElement;
|
||||
return PyiUtil.containsOverloads(resultList, mapper, typeEvalContext)
|
||||
? PyiUtil.moveOverloadsBack(resultList, mapper, typeEvalContext)
|
||||
: resultList;
|
||||
}
|
||||
|
||||
synchronized (myNameDefinerNegativeCache) {
|
||||
@@ -195,34 +198,6 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
|
||||
public long getModificationStamp() {
|
||||
return myModificationStamp;
|
||||
}
|
||||
|
||||
private boolean containsOverloads(@NotNull List<RatedResolveResult> resolveResults, @NotNull TypeEvalContext context) {
|
||||
return StreamEx
|
||||
.of(resolveResults)
|
||||
.map(RatedResolveResult::getElement)
|
||||
.anyMatch(element -> element instanceof PyCallable && PyiTypeProvider.isOverload((PyCallable)element, context));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<RatedResolveResult> moveOverloadsBack(@NotNull List<RatedResolveResult> resolveResults, @NotNull TypeEvalContext context) {
|
||||
return StreamEx
|
||||
.of(resolveResults)
|
||||
.sorted(
|
||||
(r1, r2) -> {
|
||||
final PsiElement e1 = r1.getElement();
|
||||
final PsiElement e2 = r2.getElement();
|
||||
if (e1 instanceof PyCallable && e2 instanceof PyCallable) {
|
||||
final boolean firstIsOverload = PyiTypeProvider.isOverload((PyCallable)e1, context);
|
||||
final boolean secondIsOverload = PyiTypeProvider.isOverload((PyCallable)e2, context);
|
||||
|
||||
return Boolean.compare(firstIsOverload, secondIsOverload);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
public PyFileImpl(FileViewProvider viewProvider) {
|
||||
|
||||
@@ -45,7 +45,6 @@ import com.jetbrains.python.psi.resolve.*;
|
||||
import com.jetbrains.python.psi.types.PyModuleType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import com.jetbrains.python.pyi.PyiTypeProvider;
|
||||
import com.jetbrains.python.pyi.PyiUtil;
|
||||
import com.jetbrains.python.refactoring.PyDefUseUtil;
|
||||
import one.util.streamex.StreamEx;
|
||||
@@ -275,9 +274,9 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
|
||||
if (ContainerUtil.exists(latestDefs, result -> result.getElement() instanceof PyCallable)) {
|
||||
return StreamEx
|
||||
.of(processor.getResults().keySet())
|
||||
.select(PyCallable.class)
|
||||
.filter(callable -> PyiTypeProvider.isOverload(callable, typeEvalContext))
|
||||
.map(callable -> new RatedResolveResult(getRate(callable, typeEvalContext), callable))
|
||||
.nonNull()
|
||||
.filter(element -> PyiUtil.isOverload(element, typeEvalContext))
|
||||
.map(element -> new RatedResolveResult(getRate(element, typeEvalContext), element))
|
||||
.prepend(latestDefs)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@@ -44,15 +44,14 @@ import com.jetbrains.python.psi.resolve.CompletionVariantsProcessor;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveProcessor;
|
||||
import com.jetbrains.python.psi.resolve.RatedResolveResult;
|
||||
import com.jetbrains.python.pyi.PyiTypeProvider;
|
||||
import com.jetbrains.python.pyi.PyiUtil;
|
||||
import com.jetbrains.python.toolbox.Maybe;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.jetbrains.python.psi.PyUtil.as;
|
||||
import static com.jetbrains.python.psi.resolve.PyResolveImportUtil.fromFoothold;
|
||||
@@ -555,44 +554,20 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
|
||||
@Nullable PyExpression location,
|
||||
@NotNull TypeEvalContext context) {
|
||||
final PyResolveProcessor processor = new PyResolveProcessor(name);
|
||||
final Stream<PsiElement> result;
|
||||
final Collection<PsiElement> result;
|
||||
|
||||
if (!isDefinition && !cls.processInstanceLevelDeclarations(processor, location)) {
|
||||
result = processor.getElements().stream();
|
||||
result = processor.getElements();
|
||||
}
|
||||
else {
|
||||
cls.processClassLevelDeclarations(processor);
|
||||
final Collection<PsiElement> elements = processor.getElements();
|
||||
result = containsOverloads(elements, context) ? moveOverloadsBack(elements, context) : elements.stream();
|
||||
result = PyiUtil.containsOverloads(elements, Function.identity(), context)
|
||||
? PyiUtil.moveOverloadsBack(elements, Function.identity(), context)
|
||||
: elements;
|
||||
}
|
||||
|
||||
return StreamEx
|
||||
.of(result)
|
||||
.map(element -> new RatedResolveResult(RatedResolveResult.RATE_NORMAL, element))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private static boolean containsOverloads(@NotNull Collection<PsiElement> elements, @NotNull TypeEvalContext context) {
|
||||
return ContainerUtil.exists(elements,
|
||||
element -> element instanceof PyCallable && PyiTypeProvider.isOverload((PyCallable)element, context));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Stream<PsiElement> moveOverloadsBack(@NotNull Collection<PsiElement> elements, @NotNull TypeEvalContext context) {
|
||||
return elements
|
||||
.stream()
|
||||
.sorted(
|
||||
(e1, e2) -> {
|
||||
if (e1 instanceof PyCallable && e2 instanceof PyCallable) {
|
||||
final boolean firstIsOverload = PyiTypeProvider.isOverload((PyCallable)e1, context);
|
||||
final boolean secondIsOverload = PyiTypeProvider.isOverload((PyCallable)e2, context);
|
||||
|
||||
return Boolean.compare(firstIsOverload, secondIsOverload);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
);
|
||||
return ContainerUtil.map(result, element -> new RatedResolveResult(RatedResolveResult.RATE_NORMAL, element));
|
||||
}
|
||||
|
||||
private static Key<Set<PyClassType>> CTX_VISITED = Key.create("PyClassType.Visited");
|
||||
|
||||
@@ -15,12 +15,8 @@
|
||||
*/
|
||||
package com.jetbrains.python.pyi;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.Processor;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyCallExpressionHelper;
|
||||
import com.jetbrains.python.psi.types.*;
|
||||
@@ -72,14 +68,14 @@ public class PyiTypeProvider extends PyTypeProviderBase {
|
||||
final PsiElement pythonStub = PyiUtil.getPythonStub(callable);
|
||||
if (pythonStub instanceof PyFunction) {
|
||||
final PyFunction functionStub = (PyFunction)pythonStub;
|
||||
if (isOverload(functionStub, context)) {
|
||||
if (PyiUtil.isOverload(functionStub, context)) {
|
||||
return getOverloadType(functionStub, context);
|
||||
}
|
||||
return new PyFunctionTypeImpl(functionStub);
|
||||
}
|
||||
else if (callable.getContainingFile() instanceof PyiFile && callable instanceof PyFunction) {
|
||||
final PyFunction functionStub = (PyFunction)callable;
|
||||
if (isOverload(functionStub, context)) {
|
||||
if (PyiUtil.isOverload(functionStub, context)) {
|
||||
return getOverloadType(functionStub, context);
|
||||
}
|
||||
}
|
||||
@@ -107,8 +103,8 @@ public class PyiTypeProvider extends PyTypeProviderBase {
|
||||
private static Ref<PyType> getOverloadedCallType(@NotNull PyFunction function,
|
||||
@NotNull PyCallSiteExpression callSite,
|
||||
@NotNull TypeEvalContext context) {
|
||||
if (isOverload(function, context)) {
|
||||
final List<PyFunction> overloads = getOverloads(function, context);
|
||||
if (PyiUtil.isOverload(function, context)) {
|
||||
final List<PyFunction> overloads = PyiUtil.getOverloads(function, context);
|
||||
final List<PyType> allReturnTypes = new ArrayList<>();
|
||||
final List<PyType> matchedReturnTypes = new ArrayList<>();
|
||||
|
||||
@@ -151,7 +147,7 @@ public class PyiTypeProvider extends PyTypeProviderBase {
|
||||
|
||||
@Nullable
|
||||
private static PyType getOverloadType(@NotNull PyFunction function, @NotNull final TypeEvalContext context) {
|
||||
final List<PyFunction> overloads = getOverloads(function, context);
|
||||
final List<PyFunction> overloads = PyiUtil.getOverloads(function, context);
|
||||
if (!overloads.isEmpty()) {
|
||||
final List<PyType> overloadTypes = new ArrayList<>();
|
||||
for (PyFunction overload : overloads) {
|
||||
@@ -162,46 +158,6 @@ public class PyiTypeProvider extends PyTypeProviderBase {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<PyFunction> getOverloads(@NotNull PyFunction function, @NotNull TypeEvalContext context) {
|
||||
final ScopeOwner owner = ScopeUtil.getScopeOwner(function);
|
||||
final String name = function.getName();
|
||||
final List<PyFunction> overloads = new ArrayList<>();
|
||||
final Processor<PyFunction> overloadsProcessor = f -> {
|
||||
if (name != null && name.equals(f.getName()) && isOverload(f, context)) {
|
||||
overloads.add(f);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (owner instanceof PyClass) {
|
||||
final PyClass cls = (PyClass)owner;
|
||||
if (name != null) {
|
||||
cls.visitMethods(overloadsProcessor, false, context);
|
||||
}
|
||||
}
|
||||
else if (owner instanceof PyFile) {
|
||||
final PyFile file = (PyFile)owner;
|
||||
for (PyFunction f : file.getTopLevelFunctions()) {
|
||||
if (!overloadsProcessor.process(f)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return overloads;
|
||||
}
|
||||
|
||||
public static boolean isOverload(@NotNull PyCallable callable, @NotNull TypeEvalContext context) {
|
||||
if (callable instanceof PyDecoratable) {
|
||||
final PyDecoratable decorated = (PyDecoratable)callable;
|
||||
final ImmutableSet<PyKnownDecoratorUtil.KnownDecorator> decorators =
|
||||
ImmutableSet.copyOf(PyKnownDecoratorUtil.getKnownDecorators(decorated, context));
|
||||
if (decorators.contains(PyKnownDecoratorUtil.KnownDecorator.TYPING_OVERLOAD)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PyCallExpressionHelper.ArgumentMappingResults mapArguments(@NotNull PyCallSiteExpression callSite,
|
||||
@NotNull PyFunction function,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,8 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.QualifiedName;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
@@ -26,10 +28,14 @@ import com.jetbrains.python.psi.resolve.*;
|
||||
import com.jetbrains.python.psi.types.PyClassLikeType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @author vlan
|
||||
@@ -69,6 +75,57 @@ public class PyiUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<PyFunction> getOverloads(@NotNull PyFunction function, @NotNull TypeEvalContext context) {
|
||||
final ScopeOwner owner = ScopeUtil.getScopeOwner(function);
|
||||
final String name = function.getName();
|
||||
final List<PyFunction> overloads = new ArrayList<>();
|
||||
final Processor<PyFunction> overloadsProcessor = f -> {
|
||||
if (name != null && name.equals(f.getName()) && isOverload(f, context)) {
|
||||
overloads.add(f);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (owner instanceof PyClass) {
|
||||
final PyClass cls = (PyClass)owner;
|
||||
if (name != null) {
|
||||
cls.visitMethods(overloadsProcessor, false, context);
|
||||
}
|
||||
}
|
||||
else if (owner instanceof PyFile) {
|
||||
final PyFile file = (PyFile)owner;
|
||||
for (PyFunction f : file.getTopLevelFunctions()) {
|
||||
if (!overloadsProcessor.process(f)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return overloads;
|
||||
}
|
||||
|
||||
public static boolean isOverload(@NotNull PsiElement element, @NotNull TypeEvalContext context) {
|
||||
final PyKnownDecoratorUtil.KnownDecorator overload = PyKnownDecoratorUtil.KnownDecorator.TYPING_OVERLOAD;
|
||||
|
||||
return element instanceof PyFunction &&
|
||||
PyKnownDecoratorUtil.getKnownDecorators((PyFunction)element, context).contains(overload);
|
||||
}
|
||||
|
||||
public static <T> boolean containsOverloads(@NotNull Collection<T> elements,
|
||||
@NotNull Function<? super T, PsiElement> mapper,
|
||||
@NotNull TypeEvalContext context) {
|
||||
return ContainerUtil.exists(elements, element -> isOverload(mapper.apply(element), context));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T> List<T> moveOverloadsBack(@NotNull Collection<T> elements,
|
||||
@NotNull Function<? super T, PsiElement> mapper,
|
||||
@NotNull TypeEvalContext context) {
|
||||
return StreamEx
|
||||
.of(elements)
|
||||
.sorted((e1, e2) -> Boolean.compare(isOverload(mapper.apply(e1), context), isOverload(mapper.apply(e2), context)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PyiFile getPythonStubFile(@NotNull PyFile file) {
|
||||
final QualifiedName name = QualifiedNameFinder.findCanonicalImportPath(file, file);
|
||||
|
||||
@@ -25,7 +25,7 @@ import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import com.jetbrains.python.pyi.PyiTypeProvider;
|
||||
import com.jetbrains.python.pyi.PyiUtil;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -377,7 +377,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
final PyFunction foo = assertResolvesTo(PyFunction.class, "foo");
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), myFixture.getFile());
|
||||
|
||||
PyiTypeProvider
|
||||
PyiUtil
|
||||
.getOverloads(foo, context)
|
||||
.forEach(
|
||||
overload -> {
|
||||
@@ -396,7 +396,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
() -> {
|
||||
final PyFunction foo = assertResolvesTo(PyFunction.class, "foo");
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), myFixture.getFile());
|
||||
assertFalse(PyiTypeProvider.isOverload(foo, context));
|
||||
assertFalse(PyiUtil.isOverload(foo, context));
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -409,14 +409,14 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
() -> {
|
||||
final PyFunction foo = assertResolvesTo(PyFunction.class, "foo");
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), myFixture.getFile());
|
||||
assertFalse(PyiTypeProvider.isOverload(foo, context));
|
||||
assertFalse(PyiUtil.isOverload(foo, context));
|
||||
|
||||
final PyClass pyClass = foo.getContainingClass();
|
||||
assertNotNull(pyClass);
|
||||
|
||||
pyClass.visitMethods(
|
||||
function -> {
|
||||
assertTrue(PyiTypeProvider.isOverload(function, context) || function == foo || PyPsiUtils.isBefore(foo, function));
|
||||
assertTrue(PyiUtil.isOverload(function, context) || function == foo || PyPsiUtils.isBefore(foo, function));
|
||||
return true;
|
||||
},
|
||||
false,
|
||||
@@ -435,7 +435,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
final PyFunction foo = assertResolvesTo(PyFunction.class, "foo");
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), myFixture.getFile());
|
||||
|
||||
PyiTypeProvider
|
||||
PyiUtil
|
||||
.getOverloads(foo, context)
|
||||
.forEach(
|
||||
overload -> {
|
||||
@@ -454,7 +454,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
() -> {
|
||||
final PyFunction foo = assertResolvesTo(PyFunction.class, "foo");
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), myFixture.getFile());
|
||||
assertFalse(PyiTypeProvider.isOverload(foo, context));
|
||||
assertFalse(PyiUtil.isOverload(foo, context));
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -467,7 +467,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
() -> {
|
||||
final PyFunction foo = assertResolvesTo(PyFunction.class, "foo");
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), myFixture.getFile());
|
||||
assertTrue(PyiTypeProvider.isOverload(foo, context));
|
||||
assertTrue(PyiUtil.isOverload(foo, context));
|
||||
|
||||
((PyFile)foo.getContainingFile())
|
||||
.getTopLevelFunctions()
|
||||
@@ -488,7 +488,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
final PyFunction foo = assertResolvesTo(PyFunction.class, "foo");
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), myFixture.getFile());
|
||||
|
||||
PyiTypeProvider
|
||||
PyiUtil
|
||||
.getOverloads(foo, context)
|
||||
.forEach(
|
||||
overload -> {
|
||||
@@ -508,7 +508,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
() -> {
|
||||
final PyFunction foo = assertResolvesTo(PyFunction.class, "foo");
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), myFixture.getFile());
|
||||
assertFalse(PyiTypeProvider.isOverload(foo, context));
|
||||
assertFalse(PyiUtil.isOverload(foo, context));
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -522,14 +522,14 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
() -> {
|
||||
final PyFunction foo = assertResolvesTo(PyFunction.class, "foo");
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), myFixture.getFile());
|
||||
assertFalse(PyiTypeProvider.isOverload(foo, context));
|
||||
assertFalse(PyiUtil.isOverload(foo, context));
|
||||
|
||||
final PyClass pyClass = foo.getContainingClass();
|
||||
assertNotNull(pyClass);
|
||||
|
||||
pyClass.visitMethods(
|
||||
function -> {
|
||||
assertTrue(PyiTypeProvider.isOverload(function, context) || function == foo || PyPsiUtils.isBefore(foo, function));
|
||||
assertTrue(PyiUtil.isOverload(function, context) || function == foo || PyPsiUtils.isBefore(foo, function));
|
||||
return true;
|
||||
},
|
||||
false,
|
||||
@@ -549,7 +549,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
final PyFunction foo = assertResolvesTo(PyFunction.class, "foo");
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), myFixture.getFile());
|
||||
|
||||
PyiTypeProvider
|
||||
PyiUtil
|
||||
.getOverloads(foo, context)
|
||||
.forEach(
|
||||
overload -> {
|
||||
@@ -569,7 +569,7 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
() -> {
|
||||
final PyFunction foo = assertResolvesTo(PyFunction.class, "foo");
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), myFixture.getFile());
|
||||
assertFalse(PyiTypeProvider.isOverload(foo, context));
|
||||
assertFalse(PyiUtil.isOverload(foo, context));
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -583,12 +583,12 @@ public class Py3ResolveTest extends PyResolveTestCase {
|
||||
() -> {
|
||||
final PyFunction foo = assertResolvesTo(PyFunction.class, "foo");
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), myFixture.getFile());
|
||||
assertFalse(PyiTypeProvider.isOverload(foo, context));
|
||||
assertFalse(PyiUtil.isOverload(foo, context));
|
||||
|
||||
((PyFile)foo.getContainingFile())
|
||||
.getTopLevelFunctions()
|
||||
.forEach(
|
||||
function -> assertTrue(PyiTypeProvider.isOverload(function, context) || function == foo || PyPsiUtils.isBefore(function, foo))
|
||||
function -> assertTrue(PyiUtil.isOverload(function, context) || function == foo || PyPsiUtils.isBefore(function, foo))
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user