Refactored isTopLevel() function for Python

This commit is contained in:
Andrey Vlasovskikh
2012-04-28 19:30:43 +04:00
parent c34c480a0c
commit 2453928d87
9 changed files with 24 additions and 43 deletions
@@ -7,11 +7,9 @@ import com.intellij.psi.PsiReference;
import com.intellij.psi.ResolveResult;
import com.intellij.psi.util.PsiTreeUtil;
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.PyImportStatementNavigator;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -151,7 +149,7 @@ public class PyCodeFragmentBuilder extends PyRecursiveElementVisitor {
}
}
if (modificationSeen) {
if (!isTopLevel(element)) {
if (!PyPsiUtils.isTopLevel(element)) {
inElements.add(name);
}
break;
@@ -162,10 +160,6 @@ public class PyCodeFragmentBuilder extends PyRecursiveElementVisitor {
}
}
private static boolean isTopLevel(@NotNull PyElement element) {
return ScopeUtil.getScopeOwner(element) instanceof PyFile;
}
private void processDeclaration(final PyElement element) {
final Position position = CodeFragmentUtil.getPosition(element, startOffset, endOffset);
final String name = element.getName();
@@ -22,6 +22,7 @@ import com.jetbrains.python.codeInsight.imports.AddImportHelper;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyElement;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
import com.jetbrains.python.psi.stubs.PyFunctionNameIndex;
import org.jetbrains.annotations.NotNull;
@@ -49,7 +50,7 @@ public class PyClassNameCompletionContributor extends CompletionContributor {
private static Condition<PyFunction> TOPLEVEL_FUNCTION = new Condition<PyFunction>() {
@Override
public boolean value(PyFunction pyFunction) {
return pyFunction.isTopLevel();
return PyPsiUtils.isTopLevel(pyFunction);
}
};
@@ -26,6 +26,7 @@ import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyFileImpl;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.resolve.CollectProcessor;
import com.jetbrains.python.psi.resolve.PyResolveUtil;
@@ -131,7 +132,7 @@ public class PythonReferenceImporter implements ReferenceImporter {
}
if (symbols.size() > 0) {
for (PsiElement symbol : symbols) {
if (isTopLevel(symbol)) { // we only want top-level symbols
if (isIndexableTopLevel(symbol)) { // we only want top-level symbols
PsiFileSystemItem srcfile = symbol instanceof PsiFileSystemItem ? ((PsiFileSystemItem)symbol).getParent() : symbol.getContainingFile();
if (srcfile != null && srcfile != existing_import_file && srcfile != node.getContainingFile() &&
(ImportFromExistingAction.isRoot(project, srcfile) || PyNames.isIdentifier(FileUtil.getNameWithoutExtension(srcfile.getName()))) &&
@@ -215,15 +216,12 @@ public class PythonReferenceImporter implements ReferenceImporter {
return result;
}
private static boolean isTopLevel(PsiElement symbol) {
private static boolean isIndexableTopLevel(PsiElement symbol) {
if (symbol instanceof PsiFileSystemItem) {
return true;
}
if (symbol instanceof PyClass) {
return ((PyClass)symbol).isTopLevel();
}
if (symbol instanceof PyFunction) {
return ((PyFunction)symbol).isTopLevel();
if (symbol instanceof PyClass || symbol instanceof PyFunction) {
return PyPsiUtils.isTopLevel(symbol);
}
// only top-level target expressions are included in VariableNameIndex
return symbol instanceof PyTargetExpression;
@@ -150,13 +150,6 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine
@Nullable
String getQualifiedName();
/**
* Returns true if the class is a top-level class (its parent is its containing file).
*
* @return true if the class is top-level, false otherwise.
*/
boolean isTopLevel();
/**
* Returns the list of names in the class' __slots__ attribute, or null if the class
* does not define such an attribute.
@@ -43,13 +43,6 @@ extends
@Nullable
PyClass getContainingClass();
/**
* Returns true if the function is a top-level class (its parent is its containing file).
*
* @return true if the function is top-level, false otherwise.
*/
boolean isTopLevel();
@Nullable
PyType getReturnTypeFromDocString();
@@ -227,10 +227,6 @@ public class PyClassImpl extends PyPresentableElementImpl<PyClassStub> implement
return name;
}
public boolean isTopLevel() {
return getParentByStub() instanceof PsiFile;
}
@Override
public List<String> getSlots() {
List<String> slots = getOwnSlots();
@@ -145,10 +145,6 @@ public class PyFunctionImpl extends PyPresentableElementImpl<PyFunctionStub> imp
return getStubOrPsiChild(PyElementTypes.DECORATOR_LIST); // PsiTreeUtil.getChildOfType(this, PyDecoratorList.class);
}
public boolean isTopLevel() {
return getParentByStub() instanceof PsiFile;
}
@Nullable
@Override
public PyType getReturnType(@NotNull TypeEvalContext context, @Nullable PyQualifiedExpression callSite) {
@@ -13,6 +13,7 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -318,6 +319,19 @@ public class PyPsiUtils {
return -1;
}
public static boolean isTopLevel(@NotNull PsiElement element) {
if (element instanceof StubBasedPsiElement) {
final StubElement stub = ((StubBasedPsiElement)element).getStub();
if (stub != null) {
final StubElement parentStub = stub.getParentStub();
if (parentStub != null) {
return parentStub.getPsi() instanceof PsiFile;
}
}
}
return ScopeUtil.getScopeOwner(element) instanceof PsiFile;
}
private static abstract class TopLevelVisitor extends PyRecursiveElementVisitor {
public void visitPyElement(final PyElement node) {
super.visitPyElement(node);
@@ -18,6 +18,7 @@ import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -71,7 +72,7 @@ public class PyMoveClassOrFunctionDelegate extends MoveHandlerDelegate {
@Nullable Editor editor) {
final PsiNamedElement e = getElementToMove(element);
if (e instanceof PyClass || e instanceof PyFunction) {
if (isTopLevel(e)) {
if (PyPsiUtils.isTopLevel(e)) {
doMove(project, new PsiElement[] {e}, null, null);
}
else {
@@ -88,9 +89,4 @@ public class PyMoveClassOrFunctionDelegate extends MoveHandlerDelegate {
final ScopeOwner owner = (element instanceof ScopeOwner) ? (ScopeOwner)element : ScopeUtil.getScopeOwner(element);
return (owner instanceof PsiNamedElement) ? (PsiNamedElement)owner : null;
}
private static boolean isTopLevel(@NotNull PsiElement element) {
return (element instanceof PyFunction && ((PyFunction)element).isTopLevel()) ||
(element instanceof PyClass && ((PyClass)element).isTopLevel());
}
}