public ProblemDescriptorImpl(
      @NotNull PsiElement startElement,
      @NotNull PsiElement endElement,
      String descriptionTemplate,
      LocalQuickFix[] fixes,
      ProblemHighlightType highlightType,
      boolean isAfterEndOfLine,
      @Nullable TextRange rangeInElement,
      final boolean tooltip,
      @Nullable HintAction hintAction,
      boolean onTheFly) {

    super(fixes, descriptionTemplate);
    myShowTooltip = tooltip;
    myHintAction = hintAction;
    PsiFile startContainingFile = startElement.getContainingFile();
    LOG.assertTrue(
        startContainingFile != null && startContainingFile.isValid() || startElement.isValid(),
        startElement);
    PsiFile endContainingFile =
        startElement == endElement ? startContainingFile : endElement.getContainingFile();
    LOG.assertTrue(
        startElement == endElement
            || endContainingFile != null && endContainingFile.isValid()
            || endElement.isValid(),
        endElement);
    assertPhysical(startElement);
    if (startElement != endElement) assertPhysical(endElement);

    final TextRange startElementRange = startElement.getTextRange();
    LOG.assertTrue(startElementRange != null, startElement);
    final TextRange endElementRange = endElement.getTextRange();
    LOG.assertTrue(endElementRange != null, endElement);
    if (startElementRange.getStartOffset() >= endElementRange.getEndOffset()) {
      if (!(startElement instanceof PsiFile && endElement instanceof PsiFile)) {
        LOG.error(
            "Empty PSI elements should not be passed to createDescriptor. Start: "
                + startElement
                + ", end: "
                + endElement);
      }
    }

    myHighlightType = highlightType;
    final Project project =
        startContainingFile == null ? startElement.getProject() : startContainingFile.getProject();
    final SmartPointerManager manager = SmartPointerManager.getInstance(project);
    myStartSmartPointer = manager.createSmartPsiElementPointer(startElement, startContainingFile);
    myEndSmartPointer =
        startElement == endElement
            ? null
            : manager.createSmartPsiElementPointer(endElement, endContainingFile);

    myAfterEndOfLine = isAfterEndOfLine;
    myTextRangeInElement = rangeInElement;
  }
 public int getLineNumber() {
   if (myLineNumber == -1) {
     PsiElement psiElement = getPsiElement();
     if (psiElement == null) return -1;
     if (!psiElement.isValid()) return -1;
     LOG.assertTrue(psiElement.isPhysical());
     PsiFile containingFile = InjectedLanguageUtil.getTopLevelFile(psiElement);
     Document document =
         PsiDocumentManager.getInstance(psiElement.getProject()).getDocument(containingFile);
     if (document == null) return -1;
     TextRange textRange = getTextRange();
     if (textRange == null) return -1;
     textRange =
         InjectedLanguageManager.getInstance(containingFile.getProject())
             .injectedToHost(psiElement, textRange);
     myLineNumber = document.getLineNumber(textRange.getStartOffset()) + 1;
   }
   return myLineNumber;
 }