blob: 0b6bd6519edd63aa486cd45a0a8be4e8b8e1a434 [file] [log] [blame]
package com.intellij.dupLocator;
import com.intellij.dupLocator.util.NodeFilter;
import com.intellij.psi.PsiElement;
import com.intellij.dupLocator.iterators.ArrayBackedNodeIterator;
import com.intellij.dupLocator.iterators.FilteringNodeIterator;
import com.intellij.dupLocator.iterators.NodeIterator;
import com.intellij.dupLocator.iterators.SiblingNodeIterator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Eugene.Kudelevsky
*/
public abstract class AbstractMatchingVisitor {
public abstract boolean matchSequentially(NodeIterator nodes, NodeIterator nodes2);
public abstract boolean match(PsiElement element1, PsiElement element2);
protected abstract boolean doMatchInAnyOrder(NodeIterator elements, NodeIterator elements2);
public boolean matchSequentially(@NotNull PsiElement[] elements1, @NotNull PsiElement[] element2) {
return matchSequentially(new FilteringNodeIterator(new ArrayBackedNodeIterator(elements1), getNodeFilter()),
new FilteringNodeIterator(new ArrayBackedNodeIterator(element2), getNodeFilter()));
}
@NotNull
protected abstract NodeFilter getNodeFilter();
public boolean matchOptionally(@Nullable PsiElement element1, @Nullable PsiElement element2) {
return element1 == null && isLeftLooseMatching() ||
element2 == null && isRightLooseMatching() ||
match(element1, element2);
}
public boolean matchSons(final PsiElement el1, final PsiElement el2) {
if (el1 == null || el2 == null) return el1 == el2;
return matchSequentially(el1.getFirstChild(), el2.getFirstChild());
}
public boolean matchSonsOptionally(final PsiElement element, final PsiElement element2) {
if (element == null && isLeftLooseMatching()) {
return true;
}
if (element2 == null && isRightLooseMatching()) {
return true;
}
if (element == null || element2 == null) {
return element == element2;
}
return matchSequentiallyOptionally(element.getFirstChild(), element2.getFirstChild());
}
public final boolean matchSonsInAnyOrder(PsiElement element1, PsiElement element2) {
if (element1 == null && isLeftLooseMatching()) {
return true;
}
if (element2 == null && isRightLooseMatching()) {
return true;
}
if (element1 == null || element2 == null) {
return element1 == element2;
}
PsiElement e = element1.getFirstChild();
PsiElement e2 = element2.getFirstChild();
return (e == null && isLeftLooseMatching()) ||
(e2 == null && isRightLooseMatching()) ||
matchInAnyOrder(new FilteringNodeIterator(new SiblingNodeIterator(e), getNodeFilter()),
new FilteringNodeIterator(new SiblingNodeIterator(e2), getNodeFilter()));
}
public boolean matchOptionally(@NotNull PsiElement[] elements1, @NotNull PsiElement[] elements2) {
return (elements1.length == 0 && isLeftLooseMatching()) ||
(elements2.length == 0 && isRightLooseMatching()) ||
matchSequentially(elements1, elements2);
}
public final boolean matchInAnyOrder(final PsiElement[] elements, final PsiElement[] elements2) {
if (elements == elements2) return true;
return matchInAnyOrder(
new ArrayBackedNodeIterator(elements),
new ArrayBackedNodeIterator(elements2)
);
}
protected boolean isLeftLooseMatching() {
return true;
}
protected boolean isRightLooseMatching() {
return true;
}
public boolean matchSequentially(PsiElement el1, PsiElement el2) {
//if (el1==null || el2==null) return el1 == el2;
return matchSequentially(new FilteringNodeIterator(new SiblingNodeIterator(el1), getNodeFilter()),
new FilteringNodeIterator(new SiblingNodeIterator(el2), getNodeFilter()));
}
public boolean matchSequentiallyOptionally(PsiElement el1, PsiElement el2) {
return (el1 == null && isLeftLooseMatching()) ||
(el2 == null && isRightLooseMatching()) ||
matchSequentially(new FilteringNodeIterator(new SiblingNodeIterator(el1), getNodeFilter()),
new FilteringNodeIterator(new SiblingNodeIterator(el2), getNodeFilter()));
}
public final boolean matchInAnyOrder(final NodeIterator elements, final NodeIterator elements2) {
if ((!elements.hasNext() && isLeftLooseMatching()) ||
(!elements2.hasNext() && isRightLooseMatching()) ||
(!elements.hasNext() && !elements2.hasNext())
) {
return true;
}
return doMatchInAnyOrder(elements, elements2);
}
}