From 201f8d3d4970d7e4f038215fa28b4bed9c448458 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 8 Aug 2013 11:41:09 +0200 Subject: [PATCH] teach PyFileEvaluator to keep track of declarations; get rid of old code for parsing aug assignments and 'extend' calls --- .../jetbrains/python/psi/impl/PyPsiUtils.java | 46 +--------------- .../python/psi/impl/PyFileEvaluator.java | 54 +++++++++++++++---- 2 files changed, 46 insertions(+), 54 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java b/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java index 1ff9777b7684..bc0c4c15ced0 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java +++ b/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java @@ -1,6 +1,5 @@ package com.jetbrains.python.psi.impl; -import com.google.common.collect.Lists; import com.intellij.extapi.psi.ASTDelegatePsiElement; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; @@ -18,7 +17,6 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Array; import java.util.ArrayList; -import java.util.Collection; import java.util.List; /** @@ -324,7 +322,7 @@ public class PyPsiUtils { return result; } - private static void sequenceToList(List result, PyExpression value) { + public static void sequenceToList(List result, PyExpression value) { value = flattenParens(value); if (value instanceof PySequenceExpression) { result.addAll(ContainerUtil.newArrayList(((PySequenceExpression)value).getElements())); @@ -362,48 +360,6 @@ public class PyPsiUtils { return element.getTextOffset() <= element2.getTextOffset(); } - public static Collection getAugAssignments(final @NotNull PyFile file, final @NotNull String name) { - final List result = Lists.newArrayList(); - file.accept(new TopLevelVisitor() { - @Override - protected void checkAddElement(PsiElement node) { - if (node instanceof PyAugAssignmentStatement) { - PyAugAssignmentStatement augAss = (PyAugAssignmentStatement)node; - if (name.equals(augAss.getTarget().getName())) { - sequenceToList(result, augAss.getValue()); - } - } - } - }); - return result; - } - - public static Collection getCallArguments(final @NotNull PyFile file, - final @NotNull String name, - final @NotNull String callName) { - final List result = Lists.newArrayList(); - file.accept(new TopLevelVisitor() { - @Override - protected void checkAddElement(PsiElement node) { - if (node instanceof PyCallExpression) { - PyCallExpression call = (PyCallExpression)node; - if (call.getCallee() instanceof PyReferenceExpression) { - PyReferenceExpression ref = (PyReferenceExpression)call.getCallee(); - if (callName.equals(ref.getName())) { - PyExpression ex = ref.getQualifier(); - if (name.equals(ex.getName())) { - for (PyExpression expr : call.getArguments()) { - sequenceToList(result, expr); - } - } - } - } - } - } - }); - return result; - } - private static abstract class TopLevelVisitor extends PyRecursiveElementVisitor { public void visitPyElement(final PyElement node) { super.visitPyElement(node); diff --git a/python/src/com/jetbrains/python/psi/impl/PyFileEvaluator.java b/python/src/com/jetbrains/python/psi/impl/PyFileEvaluator.java index 2f77eae24a2c..479d515d4fe2 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFileEvaluator.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFileEvaluator.java @@ -14,7 +14,9 @@ import java.util.*; */ public class PyFileEvaluator { private final Map myNamespace = new HashMap(); + private final Map> myDeclarations = new HashMap>(); private final Set myVisitedFiles; + private final Set myDeclarationsToTrack = new HashSet(); private String myCurrentFilePath; public PyFileEvaluator() { @@ -25,6 +27,10 @@ public class PyFileEvaluator { myVisitedFiles = visitedFiles; } + public void trackDeclarations(String attrName) { + myDeclarationsToTrack.add(attrName); + } + public void evaluate(PyFile file) { VirtualFile vFile = file.getVirtualFile(); myCurrentFilePath = vFile != null ? vFile.getPath() : null; @@ -40,17 +46,29 @@ public class PyFileEvaluator { String name = expression.getName(); PyExpression value = ((PyTargetExpression)expression).findAssignedValue(); myNamespace.put(name, createEvaluator().evaluate(value)); + if (myDeclarationsToTrack.contains(name)) { + List declarations = new ArrayList(); + PyPsiUtils.sequenceToList(declarations, value); + myDeclarations.put(name, declarations); + } } } @Override public void visitPyAugAssignmentStatement(PyAugAssignmentStatement node) { PyExpression target = node.getTarget(); - if (target instanceof PyReferenceExpression && ((PyReferenceExpression)target).getQualifier() == null && target.getName() != null) { - Object currentValue = myNamespace.get(target.getName()); + String name = target.getName(); + if (target instanceof PyReferenceExpression && ((PyReferenceExpression)target).getQualifier() == null && name != null) { + Object currentValue = myNamespace.get(name); if (currentValue != null) { Object rhs = createEvaluator().evaluate(node.getValue()); - myNamespace.put(target.getName(), PyEvaluator.concatenate(currentValue, rhs)); + myNamespace.put(name, PyEvaluator.concatenate(currentValue, rhs)); + } + if (myDeclarationsToTrack.contains(name)) { + List declarations = myDeclarations.get(name); + if (declarations != null) { + PyPsiUtils.sequenceToList(declarations, node.getValue()); + } } } } @@ -70,12 +88,7 @@ public class PyFileEvaluator { if (qualifier instanceof PyReferenceExpression) { PyReferenceExpression qualifierRef = (PyReferenceExpression)qualifier; if (qualifierRef.getQualifier() == null) { - String nameBeingExtended = qualifierRef.getReferencedName(); - Object value = myNamespace.get(nameBeingExtended); - if (value instanceof List) { - Object arg = createEvaluator().evaluate(node.getArguments()[0]); - myNamespace.put(nameBeingExtended, PyEvaluator.concatenate(value, arg)); - } + processExtendCall(node, qualifierRef.getReferencedName()); } } } @@ -108,6 +121,23 @@ public class PyFileEvaluator { }); } + private void processExtendCall(PyCallExpression node, String nameBeingExtended) { + PyExpression arg = node.getArguments()[0]; + + Object value = myNamespace.get(nameBeingExtended); + if (value instanceof List) { + Object argValue = createEvaluator().evaluate(arg); + myNamespace.put(nameBeingExtended, PyEvaluator.concatenate(value, argValue)); + } + + if (myDeclarationsToTrack.contains(nameBeingExtended)) { + List declarations = myDeclarations.get(nameBeingExtended); + if (declarations != null) { + PyPsiUtils.sequenceToList(declarations, arg); + } + } + } + private PyEvaluator createEvaluator() { return new PyPathEvaluator(myCurrentFilePath); } @@ -149,4 +179,10 @@ public class PyFileEvaluator { public Set getVisitedFiles() { return myVisitedFiles; } + + @NotNull + public List getDeclarations(String name) { + List expressions = myDeclarations.get(name); + return expressions != null ? expressions : Collections.emptyList(); + } }