mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Moved code in hopes of better reuse; still not reused.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user