@Override
  public boolean isValid() {
    if (!super.isValid()) {
      return false;
    }

    PsiFile psiFile = getPsiFile();
    Document document = PsiDocumentManager.getInstance(getProject()).getDocument(psiFile);
    if (document == null) {
      myCachedResult = null;
      return false;
    }

    Boolean cachedResult = myCachedResult;
    if (document.getModificationStamp() == myTimestamp && cachedResult != null) {
      return cachedResult;
    }
    myTimestamp = document.getModificationStamp();

    Segment segment = getSegment();
    boolean isFileOrBinary = isFileOrBinary();
    if (segment == null && !isFileOrBinary) {
      myCachedResult = false;
      return false;
    }

    VirtualFile file = psiFile.getVirtualFile();
    if (isFileOrBinary) {
      myCachedResult = file.isValid();
      return myCachedResult;
    }

    Segment searchOffset;
    if (myAnchor != null) {
      searchOffset = myAnchor.getRange();
      if (searchOffset == null) {
        myCachedResult = false;
        return false;
      }
    }
    else {
      searchOffset = segment;
    }

    int offset = searchOffset.getStartOffset();
    Long data = myFindModel.getUserData(DOCUMENT_TIMESTAMP_KEY);
    if (data == null || data != myTimestamp) {
      data = myTimestamp;
      FindManagerImpl.clearPreviousFindData(myFindModel);
    }
    myFindModel.putUserData(DOCUMENT_TIMESTAMP_KEY, data);
    FindResult result;
    do {
      result = myFindManager.findString(document.getCharsSequence(), offset, myFindModel, file);
      offset = result.getEndOffset() == offset ? offset + 1 : result.getEndOffset();
      if (!result.isStringFound()) {
        myCachedResult = false;
        return false;
      }
    } while (result.getStartOffset() < segment.getStartOffset());

    boolean ret = segment.getStartOffset() == result.getStartOffset() && segment.getEndOffset() == result.getEndOffset();
    myCachedResult = ret;
    return ret;
  }
@Override
  public boolean isValid()