@Override
  protected boolean handleQuestionMark(Project project, Editor editor, PsiFile file, int offsetBefore) {
    if (offsetBefore == 0) return false;
    HighlighterIterator it = editor.getHighlighter().createIterator(offsetBefore);
    if (it.atEnd()) return false;
    IElementType curToken = it.getTokenType();
    if (JavaTypingTokenSets.UNWANTED_TOKEN_AT_QUESTION.contains(curToken)) return false;
    int nesting = 0;
    while (true) {
      it.retreat();
      if (it.atEnd()) return false;
      curToken = it.getTokenType();
      if (curToken == JavaTokenType.LPARENTH || curToken == JavaTokenType.LBRACKET || curToken == JavaTokenType.LBRACE) {
        nesting--;
        if (nesting < 0) return false;
      }
      else if (curToken == JavaTokenType.RPARENTH || curToken == JavaTokenType.RBRACKET || curToken == JavaTokenType.RBRACE) {
        nesting++;
      }
      else if (nesting == 0) {
        if (JavaTypingTokenSets.UNWANTED_TOKEN_BEFORE_QUESTION.contains(curToken)) return false;
        if (JavaTypingTokenSets.WANTED_TOKEN_BEFORE_QUESTION.contains(curToken)) break;
      }
    }

    Document doc = editor.getDocument();
    doc.insertString(offsetBefore, "?");
    editor.getCaretModel().moveToOffset(offsetBefore + 1);
    PsiDocumentManager.getInstance(project).commitDocument(doc);
    PsiElement element = file.findElementAt(offsetBefore);
    if (!PsiUtil.isJavaToken(element, JavaTokenType.QUEST)) return true;
    PsiConditionalExpression cond = ObjectUtils.tryCast(element.getParent(), PsiConditionalExpression.class);
    if (cond == null || cond.getThenExpression() != null || cond.getElseExpression() != null) return true;
    PsiExpression condition = cond.getCondition();
    if (PsiUtilCore.hasErrorElementChild(condition)) return true;
    // intVal+bool? => intVal+(bool?)
    if (condition instanceof PsiPolyadicExpression && !PsiTypes.booleanType().equals(condition.getType())) {
      PsiExpression lastOperand = ArrayUtil.getLastElement(((PsiPolyadicExpression)condition).getOperands());
      if (lastOperand != null && PsiTypes.booleanType().equals(lastOperand.getType())) {
        int openingOffset = lastOperand.getTextRange().getStartOffset();
        int closingOffset = cond.getTextRange().getEndOffset();
        wrapWithParentheses(file, doc, openingOffset, closingOffset);
      }
    }
    return true;
  }
@Override
  protected boolean handleQuestionMark(Project project, Editor editor, PsiFile file, int offsetBefore)