ThreeState (@NotNull ASTNode oldNode, @NotNull LighterASTNode newNode) { ProgressIndicatorProvider.checkCanceled(); boolean oldIsErrorElement = oldNode instanceof PsiErrorElement; boolean newIsErrorElement = newNode.getTokenType() == TokenType.ERROR_ELEMENT; if (oldIsErrorElement != newIsErrorElement) return ThreeState.NO; if (oldIsErrorElement) { PsiErrorElement e1 = (PsiErrorElement)oldNode; return Objects.equals(e1.getErrorDescription(), getErrorMessage(newNode)) ? ThreeState.UNSURE : ThreeState.NO; } ThreeState customResult = customCompare(oldNode, newNode); if (customResult != ThreeState.UNSURE) { return customResult; } if (newNode instanceof Token) { IElementType type = newNode.getTokenType(); Token token = (Token)newNode; if (oldNode instanceof ForeignLeafPsiElement) { return type instanceof ForeignLeafType && ((ForeignLeafType)type).getValue().equals(oldNode.getText()) ? ThreeState.YES : ThreeState.NO; } if (oldNode instanceof LeafElement) { if (type instanceof ForeignLeafType) return ThreeState.NO; return ((LeafElement)oldNode).textMatches(token.getText()) ? ThreeState.YES : ThreeState.NO; } if (type instanceof ILightLazyParseableElementType) { if (((TreeElement)oldNode).textMatches(token.getText())) { return PsiDocumentManagerBase.isFullReparseInProgress() ? ThreeState.UNSURE : ThreeState.YES; } return TreeUtil.isCollapsedChameleon(oldNode) ? ThreeState.NO // do not dive into collapsed nodes : ThreeState.UNSURE; } if (oldNode.getElementType() instanceof ILazyParseableElementType && type instanceof ILazyParseableElementType || oldNode.getElementType() instanceof ICustomParsingType && type instanceof ICustomParsingType) { return ((TreeElement)oldNode).textMatches(token.getText()) ? ThreeState.YES : ThreeState.NO; } } return ThreeState.UNSURE; }