private ThreeState textMatches(ASTNode oldNode, ASTNode newNode) {
    myIndicator.checkCanceled();
    String oldText = TreeUtil.isCollapsedChameleon(oldNode) ? oldNode.getText() : null;
    String newText = TreeUtil.isCollapsedChameleon(newNode) ? newNode.getText() : null;
    if (oldText != null && newText != null) return oldText.equals(newText) ? ThreeState.YES : ThreeState.UNSURE;

    if (oldText != null) {
      return compareTreeToText((TreeElement)newNode, oldText) ? ThreeState.YES : ThreeState.UNSURE;
    }
    if (newText != null) {
      return compareTreeToText((TreeElement)oldNode, newText) ? ThreeState.YES : ThreeState.UNSURE;
    }

    if (oldNode instanceof ForeignLeafPsiElement) {
      return newNode instanceof ForeignLeafPsiElement && oldNode.getText().equals(newNode.getText()) ? ThreeState.YES : ThreeState.NO;
    }

    if (newNode instanceof ForeignLeafPsiElement) return ThreeState.NO;

    if (oldNode instanceof LeafElement) {
      return ((LeafElement)oldNode).textMatches(newNode.getChars()) ? ThreeState.YES : ThreeState.NO;
    }
    if (newNode instanceof LeafElement) {
      return ((LeafElement)newNode).textMatches(oldNode.getChars()) ? ThreeState.YES : ThreeState.NO;
    }

    if (oldNode instanceof PsiErrorElement && newNode instanceof PsiErrorElement) {
      PsiErrorElement e1 = (PsiErrorElement)oldNode;
      PsiErrorElement e2 = (PsiErrorElement)newNode;
      if (!Objects.equals(e1.getErrorDescription(), e2.getErrorDescription())) return ThreeState.NO;
    }

    return ThreeState.UNSURE;
  }
private ThreeState textMatches(ASTNode oldNode, ASTNode newNode)