private boolean matchPattern(@Nullable final PsiElement pattern,
                                      @Nullable final PsiElement candidate,
                                      @NotNull final SimpleMatch match) {
    ProgressManager.checkCanceled();
    if (pattern == null || candidate == null) return pattern == candidate;
    final PsiElement[] children1 = PsiEquivalenceUtil.getFilteredChildren(pattern, null, true);
    final PsiElement[] children2 = PsiEquivalenceUtil.getFilteredChildren(candidate, null, true);
    final PsiElement patternParent = pattern.getParent();
    final PsiElement candidateParent = candidate.getParent();
    if (patternParent == null || candidateParent == null) return false;
    if (pattern.getUserData(PARAMETER) != null && patternParent.getClass() == candidateParent.getClass()) {
      if (myOutputVariables.contains(pattern.getText())) {
        if(match.getChangedOutput() == null) {
          match.changeOutput(candidate.getText());
        }
      }
      return changeParameter(pattern.getText(), candidate.getText(), match);
    }
    if (children1.length != children2.length) return false;

    for (int i = 0; i < children1.length; i++) {
      final PsiElement child1 = children1[i];
      final PsiElement child2 = children2[i];
      if (!matchPattern(child1, child2, match)) return false;
    }

    if (children1.length == 0) {
      if (pattern.getUserData(PARAMETER) != null && patternParent.getClass() == candidateParent.getClass()) {
        if (myOutputVariables.contains(pattern.getText())) {
          match.changeOutput(candidate.getText());
        }
        return changeParameter(pattern.getText(), candidate.getText(), match);
      }
      if (myOutputVariables.contains(pattern.getText())) {
        match.changeOutput(candidate.getText());
        return true;
      }
      if (isVariable(pattern) && isVariable(candidate)) {
        if (!myOriginalToDuplicateLocalVariable.containsKey(pattern.getText())) {
          myOriginalToDuplicateLocalVariable.put(pattern.getText(), candidate.getText());
          return true;
        }
        return myOriginalToDuplicateLocalVariable.get(pattern.getText()).equals(candidate.getText());
      }
      if (!pattern.textMatches(candidate)) {
        return false;
      }
    }

    return true;
  }
private boolean matchPattern(@Nullable final PsiElement pattern,
                                      @Nullable final PsiElement candidate,
                                      @NotNull final SimpleMatch match)