mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-07 13:39:36 +07:00
PY-26881 Use stubs for function in find usages if it exists
(cherry picked from commit 060c164c3f01a857561d5d0341a186464419e845) IJ-MR-17639 GitOrigin-RevId: 88141ea74ff22fb022056c8d6d7f70222a3f9b74
This commit is contained in:
committed by
intellij-monorepo-bot
parent
056ac17679
commit
0210695327
@@ -1127,3 +1127,9 @@ INSP.relative.import.relative.import.outside.package=Relative import outside of
|
||||
|
||||
debugger.cleaning.signature.cache=Cleaning the Cache of Dynamically Collected Types
|
||||
ANN.patterns.repeated.star.pattern=Repeated star pattern
|
||||
|
||||
# PyElementPresentation
|
||||
element.presentation.location.string.in.class={0} in {1}
|
||||
element.presentation.location.string.in.class.stub={0} in {1} stub
|
||||
element.presentation.location.string.module={0}
|
||||
element.presentation.location.string.module.stub={0} stub
|
||||
|
||||
@@ -19,9 +19,14 @@ import com.intellij.find.findUsages.FindUsagesHandlerBase;
|
||||
import com.intellij.find.findUsages.FindUsagesOptions;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.psi.PyElement;
|
||||
import com.jetbrains.python.pyi.PyiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Important note: please update PyFindUsagesHandlerFactory#proxy on any changes here.
|
||||
*/
|
||||
@@ -41,4 +46,44 @@ public abstract class PyFindUsagesHandler extends FindUsagesHandlerBase {
|
||||
public boolean isSearchForTextOccurrencesAvailable(@NotNull PsiElement psiElement, boolean isSingleFile) {
|
||||
return super.isSearchForTextOccurrencesAvailable(psiElement, isSingleFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement @NotNull [] getPrimaryElements() {
|
||||
List<PsiElement> result = new ArrayList<>();
|
||||
result.add(myPsiElement);
|
||||
|
||||
completePrimaryElementsWithStubAndOriginalElements(result);
|
||||
|
||||
return result.toArray(PsiElement.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
protected void completePrimaryElementsWithStubAndOriginalElements(@NotNull List<PsiElement> result) {
|
||||
List<PsiElement> additionalElements = new ArrayList<>();
|
||||
for (PsiElement element: result) {
|
||||
PsiElement stubElement = tryGetStubElement(element);
|
||||
if (stubElement != null) {
|
||||
additionalElements.add(stubElement);
|
||||
}
|
||||
|
||||
PsiElement originalElement = tryGetOriginalElement(element);
|
||||
if (originalElement != null) {
|
||||
additionalElements.add(originalElement);
|
||||
}
|
||||
}
|
||||
result.addAll(additionalElements);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static PsiElement tryGetStubElement(@Nullable PsiElement element) {
|
||||
if (!(element instanceof PyElement)) return null;
|
||||
PsiElement result = PyiUtil.getPythonStub((PyElement)element);
|
||||
return result != element ? result : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static PsiElement tryGetOriginalElement(@Nullable PsiElement element) {
|
||||
if (!(element instanceof PyElement)) return null;
|
||||
PsiElement result = PyiUtil.getOriginalElement((PyElement)element);
|
||||
return result != element ? result : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jetbrains.python.findUsages;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -43,6 +44,16 @@ public class PyFunctionFindUsagesHandler extends PyFindUsagesHandler {
|
||||
|
||||
@Override
|
||||
public PsiElement @NotNull [] getPrimaryElements() {
|
||||
return myAllElements != null ? myAllElements.toArray(PsiElement.EMPTY_ARRAY) : super.getPrimaryElements();
|
||||
List<PsiElement> result = new ArrayList<>();
|
||||
if (myAllElements != null) {
|
||||
result.addAll(myAllElements);
|
||||
}
|
||||
else {
|
||||
result.add(myPsiElement);
|
||||
}
|
||||
|
||||
completePrimaryElementsWithStubAndOriginalElements(result);
|
||||
|
||||
return result.toArray(PsiElement.EMPTY_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,16 @@ import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyElement;
|
||||
import com.jetbrains.python.psi.PyPossibleClassMember;
|
||||
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
|
||||
import com.jetbrains.python.pyi.PyiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author vlan
|
||||
@@ -53,8 +57,29 @@ public class PyElementPresentation implements ColoredItemPresentation {
|
||||
@Nullable
|
||||
@Override
|
||||
public String getLocationString() {
|
||||
String packageForFile = getPackageForFile(myElement.getContainingFile());
|
||||
return packageForFile != null ? String.format("(%s)", packageForFile) : null;
|
||||
PsiFile containingFile = myElement.getContainingFile();
|
||||
|
||||
String packageForFile = getPackageForFile(containingFile);
|
||||
if (packageForFile == null) return null;
|
||||
|
||||
boolean isPyiFile = containingFile instanceof PyiFile;
|
||||
|
||||
PyClass containingClass = myElement instanceof PyPossibleClassMember ? ((PyPossibleClassMember)myElement).getContainingClass() : null;
|
||||
if (containingClass != null) {
|
||||
if (isPyiFile) {
|
||||
return PyPsiBundle.message("element.presentation.location.string.in.class.stub", containingClass.getName(), packageForFile);
|
||||
}
|
||||
else {
|
||||
return PyPsiBundle.message("element.presentation.location.string.in.class", containingClass.getName(), packageForFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (isPyiFile) {
|
||||
return PyPsiBundle.message("element.presentation.location.string.module", packageForFile);
|
||||
}
|
||||
else {
|
||||
return PyPsiBundle.message("element.presentation.location.string.module.stub", packageForFile);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -33,7 +33,6 @@ import com.jetbrains.python.psi.stubs.PyClassStub;
|
||||
import com.jetbrains.python.psi.stubs.PyFunctionStub;
|
||||
import com.jetbrains.python.psi.stubs.PyTargetExpressionStub;
|
||||
import com.jetbrains.python.psi.types.*;
|
||||
import com.jetbrains.python.pyi.PyiFile;
|
||||
import com.jetbrains.python.sdk.PythonSdkUtil;
|
||||
import icons.PythonPsiApiIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -298,19 +297,6 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements
|
||||
public String getPresentableText() {
|
||||
return notNullize(getName(), PyNames.UNNAMED_ELEMENT) + getParameterList().getPresentableText(true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getLocationString() {
|
||||
final PyClass containingClass = getContainingClass();
|
||||
final PsiFile containingFile = getContainingFile();
|
||||
final String packageForFile = getPackageForFile(containingFile);
|
||||
if (containingClass != null && packageForFile != null) {
|
||||
final String fileInfoStr = containingFile instanceof PyiFile ? packageForFile + " stub" : packageForFile;
|
||||
return String.format("(%s in %s)", containingClass.getName(), fileInfoStr);
|
||||
}
|
||||
return super.getLocationString();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -653,18 +653,7 @@ public class PyTargetExpressionImpl extends PyBaseElementImpl<PyTargetExpression
|
||||
|
||||
@Override
|
||||
public ItemPresentation getPresentation() {
|
||||
return new PyElementPresentation(this) {
|
||||
@Nullable
|
||||
@Override
|
||||
public String getLocationString() {
|
||||
final PyClass containingClass = getContainingClass();
|
||||
final String packageForFile = getPackageForFile(getContainingFile());
|
||||
if (containingClass != null && packageForFile != null) {
|
||||
return String.format("(%s in %s)", containingClass.getName(), packageForFile);
|
||||
}
|
||||
return super.getLocationString();
|
||||
}
|
||||
};
|
||||
return new PyElementPresentation(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
from parent import Parent
|
||||
class Child(Parent):
|
||||
FO<caret>O = 'bar'
|
||||
@@ -0,0 +1,2 @@
|
||||
class Parent(object):
|
||||
FOO = 'foo'
|
||||
@@ -0,0 +1,2 @@
|
||||
class Parent(object):
|
||||
FOO: str
|
||||
@@ -0,0 +1,3 @@
|
||||
from parent import Parent
|
||||
class Child(Parent):
|
||||
FOO = 'bar'
|
||||
@@ -0,0 +1,2 @@
|
||||
class Parent(object):
|
||||
FO<caret>O = 'foo'
|
||||
@@ -0,0 +1,2 @@
|
||||
class Parent(object):
|
||||
FOO: str
|
||||
3
python/testData/findUsages/ClassHasPyiStub/child.py
Normal file
3
python/testData/findUsages/ClassHasPyiStub/child.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from parent import Parent
|
||||
class Child(Parent):
|
||||
pass
|
||||
2
python/testData/findUsages/ClassHasPyiStub/parent.py
Normal file
2
python/testData/findUsages/ClassHasPyiStub/parent.py
Normal file
@@ -0,0 +1,2 @@
|
||||
class Pare<caret>nt(object):
|
||||
pass
|
||||
2
python/testData/findUsages/ClassHasPyiStub/parent.pyi
Normal file
2
python/testData/findUsages/ClassHasPyiStub/parent.pyi
Normal file
@@ -0,0 +1,2 @@
|
||||
class Parent(object):
|
||||
pass
|
||||
3
python/testData/findUsages/FunctionHasPyiStub/file.py
Normal file
3
python/testData/findUsages/FunctionHasPyiStub/file.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from lib import foo
|
||||
|
||||
foo()
|
||||
2
python/testData/findUsages/FunctionHasPyiStub/lib.py
Normal file
2
python/testData/findUsages/FunctionHasPyiStub/lib.py
Normal file
@@ -0,0 +1,2 @@
|
||||
def fo<caret>o():
|
||||
print("42")
|
||||
1
python/testData/findUsages/FunctionHasPyiStub/lib.pyi
Normal file
1
python/testData/findUsages/FunctionHasPyiStub/lib.pyi
Normal file
@@ -0,0 +1 @@
|
||||
def foo(): ...
|
||||
@@ -199,6 +199,30 @@ public class PyFindUsagesTest extends PyTestCase {
|
||||
.size());
|
||||
}
|
||||
|
||||
// PY-26881
|
||||
public void testFunctionHasPyiStub() {
|
||||
final Collection<UsageInfo> usages = findMultiFileUsages("lib.py");
|
||||
assertEquals(2, usages.size());
|
||||
}
|
||||
|
||||
// PY-26881
|
||||
public void testClassHasPyiStub() {
|
||||
final Collection<UsageInfo> usages = findMultiFileUsages("parent.py");
|
||||
assertEquals(2, usages.size());
|
||||
}
|
||||
|
||||
// PY-26881
|
||||
public void testClassAttributeHasPyiStub() {
|
||||
final Collection<UsageInfo> usages = findMultiFileUsages("parent.py");
|
||||
assertEquals(3, usages.size());
|
||||
}
|
||||
|
||||
// PY-26881
|
||||
public void testChildClassAttributeHasPyiStub() {
|
||||
final Collection<UsageInfo> usages = findMultiFileUsages("child.py");
|
||||
assertEquals(2, usages.size());
|
||||
}
|
||||
|
||||
private Collection<UsageInfo> findMultiFileUsages(String filename) {
|
||||
final String testName = getTestName(false);
|
||||
myFixture.copyDirectoryToProject("findUsages/" + testName, "");
|
||||
|
||||
Reference in New Issue
Block a user