diff --git a/resources/META-INF/ErlangPlugin.xml b/resources/META-INF/ErlangPlugin.xml index 0444c6684..5494040cf 100644 --- a/resources/META-INF/ErlangPlugin.xml +++ b/resources/META-INF/ErlangPlugin.xml @@ -94,6 +94,7 @@ + psiFile.getTextLength()) { + return false; + } + + PsiElement element = psiFile.findElementAt(offset); + + // If element is null or whitespace, check the element at position -1 + if (element == null || element instanceof PsiWhiteSpace) { + element = psiFile.findElementAt(offset - 1); + } + + // If still null after checking previous element, return false + if (element == null) { + return false; + } + + ErlangClauseBody clauseBody = PsiTreeUtil.getParentOfType(element, ErlangClauseBody.class, false); + + if (clauseBody == null) return false; + + TemplateManager templateManager = TemplateManager.getInstance(project); + Template template = createTerminatorTemplate(templateManager); + + moveCaretToEndOfLine(editor); + templateManager.startTemplate(editor, template); + + return true; + } + + private static void moveCaretToEndOfLine(Editor editor) { + LogicalPosition logicalPosition = editor.getCaretModel().getLogicalPosition(); + int lineNumber = logicalPosition.line; + int lineEndOffset = editor.getDocument().getLineEndOffset(lineNumber); + editor.getCaretModel().moveToOffset(lineEndOffset); + } + + private static Template createTerminatorTemplate(TemplateManager templateManager) { + Template template = templateManager.createTemplate("", ""); + template.addVariable("terminator", new TerminatorExpressionNode(), true); + return template; + } + + private static class TerminatorExpressionNode extends Expression { + @Override + public Result calculateResult(ExpressionContext context) { + return new TextResult(","); + } + + @Override + public Result calculateQuickResult(ExpressionContext context) { + return calculateResult(context); + } + + @Override + public LookupElement[] calculateLookupItems(ExpressionContext context) { + return new LookupElement[]{ + LookupElementBuilder.create(","), + LookupElementBuilder.create(";"), + LookupElementBuilder.create("."), + }; + } + } +} \ No newline at end of file diff --git a/tests/org/intellij/erlang/typing/ErlangSmartEnterClauseProcessorTest.java b/tests/org/intellij/erlang/typing/ErlangSmartEnterClauseProcessorTest.java index 931426d13..413895789 100644 --- a/tests/org/intellij/erlang/typing/ErlangSmartEnterClauseProcessorTest.java +++ b/tests/org/intellij/erlang/typing/ErlangSmartEnterClauseProcessorTest.java @@ -18,7 +18,15 @@ import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessor; import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessors; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupEx; +import com.intellij.codeInsight.lookup.LookupManager; +import com.intellij.codeInsight.template.impl.TemplateManagerImpl; import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.util.containers.ContainerUtil; + +import java.util.List; + import org.intellij.erlang.ErlangLanguage; import org.intellij.erlang.utils.ErlangLightPlatformCodeInsightFixtureTestCase; import org.jetbrains.annotations.NotNull; @@ -76,13 +84,67 @@ public void testCaseClause() { _ ->"""); } - private void doTest(@NotNull String before, @NotNull String after) { + public void testTerminatorProcessor() { + doTest( + "foo() ->", + "foo() ->,", + ",", ";", "." + ); + } + + public void testTerminatorProcessorWithExistingContent() { + doTest( + "foo() -> bar()", + "foo() -> bar(),", + ",", ";", "." + ); + } + + public void testTerminatorProcessorInCaseClause() { + doTest( + """ + case X of + 1 -> one + end""", + """ + case X of + 1 -> one + end""" + ); + } + + public void testTerminatorProcessorInFunction() { + doTest( + """ + foo() -> + bar() + baz().""", + """ + foo() -> + bar(), + baz().""", + ",", ";", "." + ); + } + + private void doTest(@NotNull String before, @NotNull String after, String... popupStrings) { + if (popupStrings.length > 0) { + TemplateManagerImpl.setTemplateTesting(getTestRootDisposable()); + } myFixture.configureByText("a.erl", before); WriteCommandAction.writeCommandAction(getProject()).run(() -> { for (SmartEnterProcessor processor : SmartEnterProcessors.INSTANCE.forKey(ErlangLanguage.INSTANCE)) { - processor.process(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile()); + if (processor.process(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile())) break; } }); + + if (popupStrings.length > 0) { + LookupEx lookup = LookupManager.getActiveLookup(myFixture.getEditor()); + assertNotNull("Lookup should be shown", lookup); + List lookupStrings = ContainerUtil.map(lookup.getItems(), LookupElement::getLookupString); + assertContainsElements(lookupStrings, popupStrings); + } + myFixture.checkResult(after); } }