Trigger Smart Enter in Scratch File

Answered

I'm trying to programmatically trigger a “smart enter” in a scratch file. That is, I have some Java code in a scratch file that contains an opening “{” without the closing “}”. I would like to lean on IntelliJ's auto-formatting/closing code to add the closing bracket automatically, but I can't get it to trigger. I've tried using EnterHandler, EnterAction, and SmartEnter, but none do the trick.

Below is my best attempt, but still, no dice:

import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterAction
import com.intellij.ide.DataManager
import com.intellij.ide.scratch.ScratchRootType
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.editor.actionSystem.CaretSpecificDataContext
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.testFramework.LightVirtualFile
import com.intellij.testFramework.fixtures.BasePlatformTestCase

class TriggerSmartEnterTest : BasePlatformTestCase() {

    fun `test smart enter`() {
        //make scratch file
        val code = """
                public class Test {
                    public void test() {
                }
                """.trimIndent()
        val lang = com.intellij.lang.Language.findLanguageByID("JAVA")!!
        val virtualFile = LightVirtualFile("Test.java", lang, code)
        val scratchFile = ScratchRootType.getInstance().createScratchFile(
            project,
            virtualFile.name,
            lang,
            code
        )!!
        val document = FileDocumentManager.getInstance().getDocument(scratchFile)!!
        val scratchEditor = EditorFactory.getInstance().createEditor(document, project)

        WriteCommandAction.runWriteCommandAction(scratchEditor.project) {
            //move caret to after test() {
            scratchEditor.caretModel.moveToOffset(code.indexOfLast { it == '{' } + 1)

            //try to trigger smart enter
            val dataContext = CaretSpecificDataContext.create(
                DataManager.getInstance().getDataContext(scratchEditor.contentComponent),
                scratchEditor.caretModel.currentCaret
            )
            SmartEnterAction().actionPerformed(scratchEditor, dataContext)

            //should add closing brace
            val expectedText = """
                public class Test {
                    public void test() {
                            
                    }
                }
                """.trimIndent()
            assertEquals(expectedText, document.text)
        }
    }
}
0
4 comments

Hi,

It seems to be working in scratch files for me. Make sure “Settings | Editor | General | Smart Keys | Enter | Insert pair ‘}’” is enabled.

Regarding the test, make sure CodeInsightSettings.getInstance().INSERT_BRACE_ON_ENTER is true. If it doesn't help, i suggest debugging SmartEnterAction – maybe the context is insufficient.

If it doesn't solve the issue, please clarify the case. What are you trying to implement and why it is needed?

0

I'm trying to programmatically trigger “smart enter” so manually going into a scratch file and pressing enter is not the functionality I'm looking for. The test above accurately recreates the issue I'm experiencing, and debugging SmartEnterAction is what I've been trying to do, but I'm getting stuck at JavaLikeLangLineIndentProvider.getIndent() as there seems to be an issue with how the test code above handles offsets. If I use that test code, changing the offset doesn't change what “getPosition(editor, offset)” returns, whereas if I manually hit enter, it does. I'm sure it's related to the context, I'm hoping someone can explain what context data I'm missing.

I'm trying to auto-complete LLM-generated code that forgot to add the closing brace. Instead of writing code to detect if the closing braces are missing, I'd like to lean on the existing “smart enter” functionality, which does precisely that.

CodeInsightSettings.getInstance().INSERT_BRACE_ON_ENTER does evaluate to true.

0

Hi,

I'm confused. I understand that you experience different behavior in the test (it doesn't work) and in the IDE (it works correctly).

If this is the case, I don't see what can be the issue cause here, but I suggest simplifying to delegate work to the testing framework:

fun `test smart enter`() {
  myFixture.configureByText("Test.java", """
      public class Test {
        public void test() {<caret>
      }
      """.trimIndent())
  myFixture.performEditorAction(IdeActions.ACTION_EDITOR_COMPLETE_STATEMENT)
  myFixture.checkResult("""
      public class Test {
          public void test() {
                  
          }
      }
      """.trimIndent())
}

If this is not what you mean, please explain what doesn't work in the IDE (also provide production code), with clear steps and expected/actual results.

0

Thank you,  Karol. After looking into ACTION_EDITOR_COMPLETE_STATEMENT I was able to get the smart enter to trigger correctly. I'm using the following code:

val actionManager = EditorActionManager.getInstance()
val actionHandler = actionManager.getActionHandler(
  IdeActions.ACTION_EDITOR_COMPLETE_STATEMENT
)
actionHandler.execute(
  editor,
  DataManager.getInstance().dataContext
)

 

0

Please sign in to leave a comment.