Moved code in hopes of better reuse; still not reused.

This commit is contained in:
Dmitry Cheryasov
2008-05-27 04:31:30 +04:00
parent e4a9aacf05
commit 43dcb0cccb
2 changed files with 60 additions and 60 deletions
@@ -60,7 +60,7 @@ public class PyResolveUtil {
PsiElement cur = elt;
do {
if ((processor instanceof ResolveProcessor) && !(((ResolveProcessor)processor).probe(cur))) {
if ((processor instanceof ResolveProcessor) && !(((ResolveProcessor)processor).approve(cur))) {
return null;
}
if (!cur.processDeclarations(processor, ResolveState.initial(), cur == elt ? lastParent : null, elt)) {
@@ -78,14 +78,63 @@ public class PyResolveUtil {
return treeWalkUp(processor, elt.getContext(), elt, place);
}
// NOTE: to be moved to more general scope
/**
* Tries to match two [qualified] reference expression paths; target must be a 'sublist' of source to match.
* E.g., 'a.b.c.d' and 'a.b.c' would match, while 'a.b.c' and 'a.b.c.d' would not. Eqaully, 'a.b.c' and 'a.b.d' would not match.
* If either source or target is null, false is returned.
* @see #unwindRefPath(PyReferenceExpression).
* @param source_path expression path to match (the longer list of qualifiers).
* @param target_path expression path to match against (hopeful sublist of qualifiers of source).
* @return true if source matches target.
*/
public static boolean matchPaths(List<PyReferenceExpression> source_path, List<PyReferenceExpression> target_path) {
// turn qualifiers into lists
if ((source_path == null) || (target_path == null)) return false;
// compare until target is exhausted
Iterator<PyReferenceExpression> source_iter = source_path.iterator();
for (final PyReferenceExpression target_elt : target_path) {
if (source_iter.hasNext()) {
PyReferenceExpression source_elt = source_iter.next();
if (!target_elt.getText().equals(source_elt.getText())) return false;
}
else return false; // source exhausted before target
}
return true;
}
/**
* Unwinds a [multi-level] qualified expression into a path, as seen in source text, i.e. outermost qualifier first.
* If any qualifier happens to be not a referencce expression, or expr is null, null is returned.
* @param expr an experssion to unwind.
* @return path as a list of ref expressions, or null.
*/
@Nullable
public static List<PyReferenceExpression> unwindRefPath(final PyReferenceExpression expr) {
final List<PyReferenceExpression> path = new LinkedList<PyReferenceExpression>();
PyExpression maybe_step;
PyReferenceExpression step = expr;
try {
while (step != null) {
path.add(0, step);
maybe_step = step.getQualifier();
step = (PyReferenceExpression)maybe_step;
}
}
catch (ClassCastException e) {
return null;
}
return path;
}
public static class ResolveProcessor implements PyScopeProcessor {
private String myName;
private PsiElement myResult = null;
private Set<PsiElement> mySeen;
private Set<String> mySeen;
public ResolveProcessor(final String name) {
myName = name;
mySeen = new HashSet<PsiElement>();
mySeen = new HashSet<String>();
}
public PsiElement getResult() {
@@ -149,10 +198,11 @@ public class PyResolveUtil {
* @param element to be analyzed and probably remembered.
* @return true if execute() may be tried with this element; else treeWalkUp and the like should immediately return negative result.
*/
public boolean probe(PsiElement element) {
public boolean approve(PsiElement element) {
if ((element instanceof PyFile) && (ResolveImportUtil.INIT_PY.equals(((PyFile)element).getName()))) {
if (mySeen.contains(element)) return false; // already seen it, may not try again
else mySeen.add(element);
String path = ((PyFile)element).getVirtualFile().getPath(); // TODO: handle possible NPE
if (mySeen.contains(path)) return false; // already seen it, may not try again
else mySeen.add(path);
}
return true;
}
@@ -22,16 +22,14 @@ import com.intellij.psi.ResolveState;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyImportElement;
import com.jetbrains.python.psi.PyReferenceExpression;
import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.PyResolveUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.LinkedList;
import java.util.List;
import java.util.Iterator;
/**
* Created by IntelliJ IDEA.
@@ -78,9 +76,9 @@ public class PyImportElementImpl extends PyElementImpl implements PyImportElemen
PyReferenceExpression place_ref = PsiTreeUtil.getChildOfType(place, PyReferenceExpression.class);
if (place_ref != null) {
// unfold all qualifiers of import and reference and compare them
List<PyReferenceExpression> place_path = unwindRefPath(place_ref);
List<PyReferenceExpression> ref_path = unwindRefPath(importRef);
if (matchPaths(place_path, ref_path)) {
List<PyReferenceExpression> place_path = PyResolveUtil.unwindRefPath(place_ref);
List<PyReferenceExpression> ref_path = PyResolveUtil.unwindRefPath(importRef);
if (PyResolveUtil.matchPaths(place_path, ref_path)) {
assert ref_path != null; // extraneous, but makes npe inspection happy
for (PyReferenceExpression rex: ref_path) { // the thing the processor is looking for must be somewhere here
final PsiElement elt = rex.resolve();
@@ -96,52 +94,4 @@ public class PyImportElementImpl extends PyElementImpl implements PyImportElemen
return true;
}
// NOTE: to be moved to more general scope
/**
* Tries to match two [qualified] reference expression paths; target must be a 'sublist' of source to match.
* E.g., 'a.b.c.d' and 'a.b.c' would match, while 'a.b.c' and 'a.b.c.d' would not. Eqaully, 'a.b.c' and 'a.b.d' would not match.
* If either source or target is null, false is returned.
* @see #unwindRefPath(PyReferenceExpression).
* @param source_path expression path to match (the longer list of qualifiers).
* @param target_path expression path to match against (hopeful sublist of qualifiers of source).
* @return true if source matches target.
*/
public static boolean matchPaths(List<PyReferenceExpression> source_path, List<PyReferenceExpression> target_path) {
// turn qualifiers into lists
if ((source_path == null) || (target_path == null)) return false;
// compare until target is exhausted
Iterator<PyReferenceExpression> source_iter = source_path.iterator();
for (final PyReferenceExpression target_elt : target_path) {
if (source_iter.hasNext()) {
PyReferenceExpression source_elt = source_iter.next();
if (!target_elt.getText().equals(source_elt.getText())) return false;
}
else return false; // source exhausted before target
}
return true;
}
/**
* Unwinds a [multi-level] qualified expression into a path, as seen in source text, i.e. outermost qualifier first.
* If any qualifier happens to be not a referencce expression, or expr is null, null is returned.
* @param expr an experssion to unwind.
* @return path as a list of ref expressions, or null.
*/
@Nullable
protected static List<PyReferenceExpression> unwindRefPath(final PyReferenceExpression expr) {
final List<PyReferenceExpression> path = new LinkedList<PyReferenceExpression>();
PyExpression maybe_step;
PyReferenceExpression step = expr;
try {
while (step != null) {
path.add(0, step);
maybe_step = step.getQualifier();
step = (PyReferenceExpression)maybe_step;
}
}
catch (ClassCastException e) {
return null;
}
return path;
}
}