private static boolean isAppropriatePlace(Editor editor, PsiFile file) {
    FileViewProvider provider = file.getViewProvider();
    int offset = editor.getCaretModel().getOffset();

    final PsiElement elementAtCaret;
    if (offset < editor.getDocument().getTextLength()) {
      elementAtCaret = provider.findElementAt(offset);
    }
    else {
      elementAtCaret = provider.findElementAt(editor.getDocument().getTextLength() - 1);
    }

    PsiElement element = elementAtCaret;
    while (element instanceof PsiWhiteSpace || element != null && containsOnlyWhiteSpaces(element.getText())) {
      element = element.getPrevSibling();
    }

    if (element == null) {
      return false;
    }
    ASTNode astNode = BasicJavaAstTreeUtil.toNode(element);
    if (BasicJavaAstTreeUtil.is(astNode, BASIC_DOC_PARAMETER_REF)) {
      astNode = astNode.getTreeParent();
    }

    if (BasicJavaAstTreeUtil.is(astNode, BASIC_DOC_TAG, BASIC_DOC_SNIPPET_TAG, BASIC_DOC_INLINE_TAG) &&
        "param".equals(BasicJavaAstTreeUtil.getTagName(astNode)) &&
        isTypeParamBracketClosedAfterParamTag(astNode, offset)) {
      return false;
    }


    // The contents of inline tags is not HTML, so the paired tag completion isn't appropriate there.
    if (BasicJavaAstTreeUtil.is(astNode, BASIC_DOC_INLINE_TAG, BASIC_DOC_SNIPPET_TAG) ||
        BasicJavaAstTreeUtil.getParentOfType(astNode, ParentAwareTokenSet.create(BASIC_DOC_INLINE_TAG, BASIC_DOC_SNIPPET_TAG)) != null) {
      return false;
    }

    ASTNode node = element.getNode();
    return node != null
           && (JavaDocTokenType.ALL_JAVADOC_TOKENS.contains(node.getElementType())
               || BASIC_ALL_JAVADOC_ELEMENTS.contains(node.getElementType()));
  }
private static boolean isAppropriatePlace(Editor editor, PsiFile file)