void (@NotNull Editor editor, @Nullable ASTNode astNode) { PsiElement psiElement = BasicJavaAstTreeUtil.toPsi(astNode); if (astNode == null || psiElement == null) { return; } if ( BasicJavaAstTreeUtil.is(astNode, BASIC_EXPRESSION_STATEMENT) || BasicJavaAstTreeUtil.is(astNode, BASIC_DECLARATION_STATEMENT) || isImportStatementBase(psiElement) || BasicJavaAstTreeUtil.is(astNode, BASIC_DO_WHILE_STATEMENT) || BasicJavaAstTreeUtil.is(astNode, BASIC_RETURN_STATEMENT) || BasicJavaAstTreeUtil.is(astNode, BASIC_THROW_STATEMENT) || BasicJavaAstTreeUtil.is(astNode, BASIC_BREAK_STATEMENT) || BasicJavaAstTreeUtil.is(astNode, BASIC_CONTINUE_STATEMENT) || BasicJavaAstTreeUtil.is(astNode, BASIC_YIELD_STATEMENT) || BasicJavaAstTreeUtil.is(astNode, BASIC_ASSERT_STATEMENT) || BasicJavaAstTreeUtil.is(astNode, BASIC_PACKAGE_STATEMENT) || isStandaloneField(psiElement) || BasicJavaAstTreeUtil.is(astNode, BASIC_METHOD) && BasicJavaAstTreeUtil.getCodeBlock(astNode) == null && !isMethodShouldHaveBody(psiElement) || BasicJavaAstTreeUtil.is(astNode, BASIC_REQUIRES_STATEMENT) || BasicJavaAstTreeUtil.is(astNode, BASIC_OPENS_STATEMENT) || BasicJavaAstTreeUtil.is(astNode, BASIC_EXPORTS_STATEMENT) || BasicJavaAstTreeUtil.is(astNode, BASIC_USES_STATEMENT) || BasicJavaAstTreeUtil.is(astNode, BASIC_PROVIDES_STATEMENT)) { String text = astNode.getText(); int tailLength = 0; ASTNode leaf = TreeUtil.findLastLeaf(astNode); while (leaf != null && BASIC_JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(leaf.getElementType())) { tailLength += leaf.getTextLength(); leaf = TreeUtil.prevLeaf(leaf); } if (leaf == null) { return; } if (tailLength > 0) { text = text.substring(0, text.length() - tailLength); } int insertionOffset = leaf.getTextRange().getEndOffset(); Document doc = editor.getDocument(); if (BasicJavaAstTreeUtil.is(astNode, BASIC_FIELD) && (BasicJavaAstTreeUtil.hasModifierProperty(astNode, JavaTokenType.ABSTRACT_KEYWORD))) { // abstract rarely seem to be field. It is rather incomplete method. doc.insertString(insertionOffset, "()"); insertionOffset += "()".length(); } // Like: // assert x instanceof Type // String s = "hello"; // Here, String is parsed as name of the pattern variable, and we have an assignment, instead of declaration ASTNode error = astNode.getLastChildNode(); if (BasicJavaAstTreeUtil.is(error, TokenType.ERROR_ELEMENT) && BasicJavaAstTreeUtil.is(error.getTreePrev(), BASIC_INSTANCE_OF_EXPRESSION) && BasicJavaAstTreeUtil.is(error.getTreePrev().getLastChildNode(), BASIC_TYPE_TEST_PATTERN)) { ASTNode variable = BasicJavaAstTreeUtil.getPatternVariable(error.getTreePrev().getLastChildNode()); PsiElement skipWhitespacesForward = PsiTreeUtil.skipWhitespacesForward(psiElement); ASTNode assignmentExpr = BasicJavaAstTreeUtil.getExpression(BasicJavaAstTreeUtil.toNode(skipWhitespacesForward)); if (variable != null && BasicJavaAstTreeUtil.is(BasicJavaAstTreeUtil.toNode(skipWhitespacesForward), BASIC_EXPRESSION_STATEMENT) && BasicJavaAstTreeUtil.is(assignmentExpr, BASIC_ASSIGNMENT_EXPRESSION) && JavaTokenType.EQ.equals(BasicJavaAstTreeUtil.getAssignmentOperationTokenType(assignmentExpr))) { ASTNode identifier = BasicJavaAstTreeUtil.getNameIdentifier(variable); if (identifier != null && BasicJavaAstTreeUtil.toPsi(identifier.getTreePrev()) instanceof PsiWhiteSpace ws && ws.getText().contains("\n") && editor.getCaretModel().getOffset() < identifier.getTextRange().getStartOffset()) { insertionOffset = ws.getTextRange().getStartOffset(); } } } if (!StringUtil.endsWithChar(text, ';')) { ASTNode parent = astNode.getTreeParent(); String toInsert = ";"; if (BasicJavaAstTreeUtil.is(parent, BASIC_FOR_STATEMENT)) { if (BasicJavaAstTreeUtil.getForUpdate(parent) == astNode) { return; } if (getSpaceAfterSemicolon(psiElement)) { toInsert += " "; } } doc.insertString(insertionOffset, toInsert); } } }