PY-13180 Pycharm 3.4: Right mouse click on selected text inside unicode string hangs out IDE interface for 20-30 seconds

PY-13983 PyCharm hangs (~100% CPU) when right clicking highlighted text
TODO: Add tests (performance and modification)
This commit is contained in:
Ilya.Kazakevich
2014-10-10 19:35:35 +04:00
parent d66273321e
commit 550975842e
3 changed files with 132 additions and 33 deletions
@@ -1,9 +1,13 @@
package com.jetbrains.python.nameResolver;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiCacheKey;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Function;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -16,6 +20,12 @@ import java.util.List;
* @author Ilya.Kazakevich
*/
public final class NameResolverTools {
/**
* Cache: pair [qualified element name, class name (may be null)] by any psi element.
*/
private static final PsiCacheKey<Pair<String, String>, PyElement> QUALIFIED_AND_CLASS_NAME =
PsiCacheKey.create(NameResolverTools.class.getName(), new QualifiedAndClassNameObtainer(), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
private NameResolverTools() {
}
@@ -45,25 +55,9 @@ public final class NameResolverTools {
* @return true if element's fqn is one of names, provided by provider
*/
public static boolean isName(@NotNull final PyElement element, @NotNull final FQNamesProvider... namesProviders) {
PyElement elementToCheck = element;
final PsiReference reference = element.getReference();
if (reference != null) {
final PsiElement resolvedElement = reference.resolve();
if (resolvedElement instanceof PyElement) {
elementToCheck = (PyElement)resolvedElement;
}
}
String qualifiedName = null;
if (elementToCheck instanceof PyQualifiedNameOwner) {
qualifiedName = ((PyQualifiedNameOwner)elementToCheck).getQualifiedName();
}
String className = null;
if (elementToCheck instanceof PyFunction) {
final PyClass aClass = ((PyFunction)elementToCheck).getContainingClass();
if (aClass != null) {
className = aClass.getQualifiedName();
}
}
final Pair<String, String> qualifiedAndClassName = QUALIFIED_AND_CLASS_NAME.getValue(element);
final String qualifiedName = qualifiedAndClassName.first;
final String className = qualifiedAndClassName.second;
for (final FQNamesProvider provider : namesProviders) {
final List<String> names = Arrays.asList(provider.getNames());
@@ -79,7 +73,8 @@ public final class NameResolverTools {
/**
* Looks for parent call of certain function
* @param anchor element to look parent for
*
* @param anchor element to look parent for
* @param functionName function to find
* @return parent call or null if not found
*/
@@ -111,4 +106,34 @@ public final class NameResolverTools {
return false;
}
}
/**
* Returns pair [qualified name, class name (may be null)] by psi element
*/
private static class QualifiedAndClassNameObtainer implements Function<PyElement, Pair<String, String>> {
@Override
@NotNull
public Pair<String, String> fun(@NotNull final PyElement element) {
PyElement elementToCheck = element;
final PsiReference reference = element.getReference();
if (reference != null) {
final PsiElement resolvedElement = reference.resolve();
if (resolvedElement instanceof PyElement) {
elementToCheck = (PyElement)resolvedElement;
}
}
String qualifiedName = null;
if (elementToCheck instanceof PyQualifiedNameOwner) {
qualifiedName = ((PyQualifiedNameOwner)elementToCheck).getQualifiedName();
}
String className = null;
if (elementToCheck instanceof PyFunction) {
final PyClass aClass = ((PyFunction)elementToCheck).getContainingClass();
if (aClass != null) {
className = aClass.getQualifiedName();
}
}
return Pair.create(qualifiedName, className);
}
}
}