1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
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);
}
}
|