mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-21180 Slightly boost resolving imports in projects like Tensorflow by caching findCanonicalImportName()
This commit is contained in:
@@ -846,20 +846,19 @@ public class PyUtil {
|
||||
});
|
||||
}
|
||||
|
||||
public static <T, P> T getParameterizedCachedValue(@NotNull PsiElement element, @NotNull P param, @NotNull NotNullFunction<P, T> f) {
|
||||
final Map<P, T> cache = CachedValuesManager.getCachedValue(element, new CachedValueProvider<Map<P, T>>() {
|
||||
private static final Object NULL_VALUE = new Object();
|
||||
public static <T, P> T getParameterizedCachedValue(@NotNull PsiElement element, @Nullable P param, @NotNull NullableFunction<P, T> f) {
|
||||
final Map<P, Object> cache = CachedValuesManager.getCachedValue(element, new CachedValueProvider<Map<P, Object>>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<Map<P, T>> compute() {
|
||||
public Result<Map<P, Object>> compute() {
|
||||
// TODO should be concurrent map instead
|
||||
return Result.create(Maps.newHashMap(), PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
});
|
||||
T result = cache.get(param);
|
||||
if (result == null) {
|
||||
result = f.fun(param);
|
||||
cache.put(param, result);
|
||||
}
|
||||
return result;
|
||||
final Object wrapped = cache.computeIfAbsent(param, p -> ObjectUtils.notNull(f.fun(param), NULL_VALUE));
|
||||
//noinspection unchecked
|
||||
return (T)ObjectUtils.nullizeByCondition(wrapped, NULL_VALUE::equals);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,10 +27,7 @@ import com.intellij.psi.util.QualifiedName;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyElement;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -114,49 +111,51 @@ public class QualifiedNameFinder {
|
||||
*/
|
||||
@Nullable
|
||||
public static QualifiedName findCanonicalImportPath(@NotNull PsiElement symbol, @Nullable PsiElement foothold) {
|
||||
PsiFileSystemItem srcfile = symbol instanceof PsiFileSystemItem ? (PsiFileSystemItem)symbol : symbol.getContainingFile();
|
||||
if (srcfile == null) {
|
||||
return null;
|
||||
}
|
||||
VirtualFile virtualFile = srcfile.getVirtualFile();
|
||||
if (virtualFile == null) {
|
||||
return null;
|
||||
}
|
||||
if (srcfile instanceof PsiFile && symbol instanceof PsiNamedElement && !(symbol instanceof PsiFileSystemItem)) {
|
||||
PsiElement toplevel = symbol;
|
||||
if (symbol instanceof PyFunction) {
|
||||
final PyClass containingClass = ((PyFunction)symbol).getContainingClass();
|
||||
if (containingClass != null) {
|
||||
toplevel = containingClass;
|
||||
}
|
||||
return PyUtil.getParameterizedCachedValue(symbol, foothold, param -> {
|
||||
PsiFileSystemItem srcfile = symbol instanceof PsiFileSystemItem ? (PsiFileSystemItem)symbol : symbol.getContainingFile();
|
||||
if (srcfile == null) {
|
||||
return null;
|
||||
}
|
||||
PsiDirectory dir = ((PsiFile)srcfile).getContainingDirectory();
|
||||
while (dir != null) {
|
||||
PsiFile initPy = dir.findFile(PyNames.INIT_DOT_PY);
|
||||
if (initPy == null) {
|
||||
break;
|
||||
}
|
||||
if (initPy instanceof PyFile) {
|
||||
//noinspection ConstantConditions
|
||||
final List<RatedResolveResult> resolved = ((PyFile)initPy).multiResolveName(((PsiNamedElement)toplevel).getName());
|
||||
final PsiElement finalTopLevel = toplevel;
|
||||
if (resolved.stream().anyMatch(r -> r.getElement() == finalTopLevel)) {
|
||||
virtualFile = dir.getVirtualFile();
|
||||
VirtualFile virtualFile = srcfile.getVirtualFile();
|
||||
if (virtualFile == null) {
|
||||
return null;
|
||||
}
|
||||
if (srcfile instanceof PsiFile && symbol instanceof PsiNamedElement && !(symbol instanceof PsiFileSystemItem)) {
|
||||
PsiElement toplevel = symbol;
|
||||
if (symbol instanceof PyFunction) {
|
||||
final PyClass containingClass = ((PyFunction)symbol).getContainingClass();
|
||||
if (containingClass != null) {
|
||||
toplevel = containingClass;
|
||||
}
|
||||
}
|
||||
dir = dir.getParentDirectory();
|
||||
}
|
||||
}
|
||||
final QualifiedName qname = findShortestImportableQName(foothold != null ? foothold : symbol, virtualFile);
|
||||
if (qname != null) {
|
||||
for (PyCanonicalPathProvider provider : Extensions.getExtensions(PyCanonicalPathProvider.EP_NAME)) {
|
||||
final QualifiedName restored = provider.getCanonicalPath(qname, foothold);
|
||||
if (restored != null) {
|
||||
return restored;
|
||||
PsiDirectory dir = ((PsiFile)srcfile).getContainingDirectory();
|
||||
while (dir != null) {
|
||||
PsiFile initPy = dir.findFile(PyNames.INIT_DOT_PY);
|
||||
if (initPy == null) {
|
||||
break;
|
||||
}
|
||||
if (initPy instanceof PyFile) {
|
||||
//noinspection ConstantConditions
|
||||
final List<RatedResolveResult> resolved = ((PyFile)initPy).multiResolveName(((PsiNamedElement)toplevel).getName());
|
||||
final PsiElement finalTopLevel = toplevel;
|
||||
if (resolved.stream().anyMatch(r -> r.getElement() == finalTopLevel)) {
|
||||
virtualFile = dir.getVirtualFile();
|
||||
}
|
||||
}
|
||||
dir = dir.getParentDirectory();
|
||||
}
|
||||
}
|
||||
}
|
||||
return qname;
|
||||
final QualifiedName qname = findShortestImportableQName(param != null ? param : symbol, virtualFile);
|
||||
if (qname != null) {
|
||||
for (PyCanonicalPathProvider provider : Extensions.getExtensions(PyCanonicalPathProvider.EP_NAME)) {
|
||||
final QualifiedName restored = provider.getCanonicalPath(qname, param);
|
||||
if (restored != null) {
|
||||
return restored;
|
||||
}
|
||||
}
|
||||
}
|
||||
return qname;
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
Reference in New Issue
Block a user