private List<PsiElement> _process(final Matcher matcher, final boolean resolve) {
    final XmlTag root = matcher.getRoot();
    if (root == null || myHistory.contains(root)) {
      return Collections.emptyList();
    }
    myHistory.add(root);
    final List<PsiElement> found = new ArrayList<>();

    try {
      if (matcher.isRecursive()) {
        root.accept(new XmlRecursiveElementVisitor() {
          @Override
          public void visitXmlTag(@NotNull XmlTag tag) {
            final Matcher.Result match = matcher.match(tag);
            if (match != null) {
              if (match.chain != null) {
                found.addAll(_process(match.chain, resolve));
              }
              else {
                assert match.result != null;
                found.add(match.result);
                if (resolve) throw Stop.DONE;
              }
            }
            super.visitXmlTag(tag);
          }
        });
      }
      else {
        root.acceptChildren(new XmlElementVisitor() {

          @Override
          public void visitXmlTag(@NotNull XmlTag tag) {
            final Matcher.Result match = matcher.match(tag);
            if (match != null) {
              if (match.chain != null) {
                found.addAll(_process(match.chain, resolve));
              }
              else {
                assert match.result != null;
                found.add(match.result);
                if (resolve) throw Stop.DONE;
              }
            }
          }
        });
      }
    }
    catch (Stop e) {
      /* processing stopped */
    }
    return found;
  }
private List<PsiElement> _process(final Matcher matcher, final boolean resolve)