use of com.intellij.structuralsearch.impl.matcher.iterators.HierarchyNodeIterator in project intellij-community by JetBrains.
the class JavaMatchingVisitor method compareClasses.
private boolean compareClasses(final PsiClass clazz, final PsiClass clazz2) {
final PsiClass saveClazz = this.myClazz;
final MatchContext.MatchedElementsListener oldListener = myMatchingVisitor.getMatchContext().getMatchedElementsListener();
this.myClazz = clazz2;
final CompiledPattern pattern = myMatchingVisitor.getMatchContext().getPattern();
assert pattern instanceof JavaCompiledPattern;
final JavaCompiledPattern javaPattern = (JavaCompiledPattern) pattern;
MatchContext.MatchedElementsListener listener = new MatchContext.MatchedElementsListener() {
private Set<PsiElement> myMatchedElements;
@Override
public void matchedElements(Collection<PsiElement> matchedElements) {
if (matchedElements == null)
return;
if (myMatchedElements == null) {
myMatchedElements = new HashSet<>(matchedElements);
} else {
myMatchedElements.addAll(matchedElements);
}
}
@Override
public void commitUnmatched() {
final List<PsiMember> members = PsiTreeUtil.getChildrenOfTypeAsList(clazz2, PsiMember.class);
final List<PsiMember> unmatchedElements = ContainerUtil.filter(members, a -> myMatchedElements == null || !myMatchedElements.contains(a));
MatchingHandler unmatchedSubstitutionHandler = null;
for (PsiElement element = clazz.getFirstChild(); element != null; element = element.getNextSibling()) {
if (element instanceof PsiTypeElement && element.getNextSibling() instanceof PsiErrorElement) {
unmatchedSubstitutionHandler = pattern.getHandler(element);
break;
}
}
if (unmatchedSubstitutionHandler instanceof SubstitutionHandler) {
final SubstitutionHandler handler = (SubstitutionHandler) unmatchedSubstitutionHandler;
for (PsiMember element : unmatchedElements) {
handler.handle(element, myMatchingVisitor.getMatchContext());
}
} else {
clazz2.putUserData(GlobalMatchingVisitor.UNMATCHED_ELEMENTS_KEY, unmatchedElements);
}
}
};
myMatchingVisitor.getMatchContext().setMatchedElementsListener(listener);
boolean result = false;
try {
final boolean templateIsInterface = clazz.isInterface();
if (templateIsInterface != clazz2.isInterface())
return false;
if (templateIsInterface && clazz.isAnnotationType() && !clazz2.isAnnotationType())
return false;
if (clazz.isEnum() && !clazz2.isEnum())
return false;
if (!matchInAnyOrder(clazz.getExtendsList(), clazz2.getExtendsList())) {
return false;
}
// check if implements is in extended classes implements
final PsiReferenceList implementsList = clazz.getImplementsList();
if (implementsList != null) {
if (!matchInAnyOrder(implementsList, clazz2.getImplementsList())) {
final PsiReferenceList anotherExtendsList = clazz2.getExtendsList();
final PsiJavaCodeReferenceElement[] referenceElements = implementsList.getReferenceElements();
boolean accepted = false;
if (referenceElements.length > 0 && anotherExtendsList != null) {
final HierarchyNodeIterator iterator = new HierarchyNodeIterator(clazz2, true, true, false);
accepted = myMatchingVisitor.matchInAnyOrder(new ArrayBackedNodeIterator(referenceElements), iterator);
}
if (!accepted)
return false;
}
}
final PsiField[] fields = clazz.getFields();
if (fields.length > 0) {
final PsiField[] fields2 = javaPattern.isRequestsSuperFields() ? clazz2.getAllFields() : clazz2.getFields();
if (!myMatchingVisitor.matchInAnyOrder(fields, fields2)) {
return false;
}
}
final PsiMethod[] methods = clazz.getMethods();
if (methods.length > 0) {
final PsiMethod[] methods2 = javaPattern.isRequestsSuperMethods() ? clazz2.getAllMethods() : clazz2.getMethods();
if (!myMatchingVisitor.matchInAnyOrder(methods, methods2)) {
return false;
}
}
final PsiClass[] nestedClasses = clazz.getInnerClasses();
if (nestedClasses.length > 0) {
final PsiClass[] nestedClasses2 = javaPattern.isRequestsSuperInners() ? clazz2.getAllInnerClasses() : clazz2.getInnerClasses();
if (!myMatchingVisitor.matchInAnyOrder(nestedClasses, nestedClasses2)) {
return false;
}
}
final PsiClassInitializer[] initializers = clazz.getInitializers();
if (initializers.length > 0) {
final PsiClassInitializer[] initializers2 = clazz2.getInitializers();
if (!myMatchingVisitor.matchInAnyOrder(initializers, initializers2)) {
return false;
}
}
result = true;
return true;
} finally {
if (result)
listener.commitUnmatched();
this.myClazz = saveClazz;
myMatchingVisitor.getMatchContext().setMatchedElementsListener(oldListener);
}
}
use of com.intellij.structuralsearch.impl.matcher.iterators.HierarchyNodeIterator in project intellij-community by JetBrains.
the class JavaMatchingVisitor method checkMatchWithinHierarchy.
private boolean checkMatchWithinHierarchy(PsiElement el2, SubstitutionHandler handler, PsiElement context) {
boolean includeInterfaces = true;
boolean includeClasses = true;
final PsiElement contextParent = context.getParent();
if (contextParent instanceof PsiReferenceList) {
final PsiElement grandParentContext = contextParent.getParent();
if (grandParentContext instanceof PsiClass) {
final PsiClass psiClass = (PsiClass) grandParentContext;
if (contextParent == psiClass.getExtendsList()) {
includeInterfaces = psiClass.isInterface();
} else if (contextParent == psiClass.getImplementsList()) {
includeClasses = false;
}
}
}
// is type2 is (strict) subtype of type
final NodeIterator node = new HierarchyNodeIterator(el2, includeClasses, includeInterfaces);
if (handler.isStrictSubtype()) {
node.advance();
}
final boolean notPredicate = handler.getPredicate() instanceof NotPredicate;
while (node.hasNext() && !handler.validate(node.current(), 0, -1, myMatchingVisitor.getMatchContext())) {
if (notPredicate)
return false;
node.advance();
}
if (node.hasNext()) {
handler.addResult(el2, 0, -1, myMatchingVisitor.getMatchContext());
return true;
} else {
return false;
}
}
Aggregations