From f786d1e87297514208c1d86fade092066167fbe0 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Sun, 23 Feb 2014 01:55:59 +0100 Subject: [PATCH] IDEA-120066 Auto indent on closing curly brace --- .../editorActions/TypedHandler.java | 32 +++++++++++++---- .../highlighting/BraceMatchingUtil.java | 34 +++++++++++++++++++ .../src/misc/registry.properties | 1 + 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java index 2ced9a6b55b2..044e621edf34 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java @@ -33,10 +33,7 @@ import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.EditorModificationUtil; -import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.actionSystem.TypedActionHandler; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.highlighter.EditorHighlighter; @@ -48,6 +45,7 @@ import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.fileTypes.PlainTextLanguage; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -582,13 +580,35 @@ public class TypedHandler extends TypedActionHandlerBase { final FileType fileType = file.getFileType(); BraceMatcher braceMatcher = BraceMatchingUtil.getBraceMatcher(fileType, iterator); - final boolean isBrace = braceMatcher.isLBraceToken(iterator, chars, fileType) || braceMatcher.isRBraceToken(iterator, chars, fileType); + boolean rBraceToken = braceMatcher.isRBraceToken(iterator, chars, fileType); + final boolean isBrace = braceMatcher.isLBraceToken(iterator, chars, fileType) || rBraceToken; + int lBraceOffset = -1; + + if (Registry.is("typing.rbrace.reformats.block") && + rBraceToken && + braceMatcher.isStructuralBrace(iterator, chars, fileType) && offset > 0) { + lBraceOffset = BraceMatchingUtil.findLeftLParen( + highlighter.createIterator(offset - 1), + braceMatcher.getOppositeBraceTokenType(iterator.getTokenType()), + editor.getDocument().getCharsSequence(), + fileType + ); + } if (element.getNode() != null && isBrace) { + final int finalLBraceOffset = lBraceOffset; ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run(){ try{ - int newOffset = CodeStyleManager.getInstance(project).adjustLineIndent(file, offset); + int newOffset; + if (finalLBraceOffset != -1) { + RangeMarker marker = document.createRangeMarker(offset, offset + 1); + CodeStyleManager.getInstance(project).reformatRange(file, finalLBraceOffset, offset, true); + newOffset = marker.getStartOffset(); + } else { + newOffset = CodeStyleManager.getInstance(project).adjustLineIndent(file, offset); + } + editor.getCaretModel().moveToOffset(newOffset + 1); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); editor.getSelectionModel().removeSelection(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceMatchingUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceMatchingUtil.java index c9d4d88d9529..c3fc814181b3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceMatchingUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceMatchingUtil.java @@ -301,6 +301,40 @@ public class BraceMatchingUtil { return lastLbraceOffset; } + public static int findLeftLParen(HighlighterIterator iterator, + IElementType lparenTokenType, + CharSequence fileText, + FileType fileType) { + int lastLbraceOffset = -1; + + Stack braceStack = new Stack(); + for (; !iterator.atEnd(); iterator.retreat()) { + final IElementType tokenType = iterator.getTokenType(); + + if (isLBraceToken(iterator, fileText, fileType)) { + if (!braceStack.isEmpty()) { + IElementType topToken = braceStack.pop(); + if (!isPairBraces(tokenType, topToken, fileType)) { + break; // unmatched braces + } + } + else { + if (tokenType == lparenTokenType) { + return iterator.getStart(); + } + else { + break; + } + } + } + else if (isRBraceToken(iterator, fileText, fileType)) { + braceStack.push(iterator.getTokenType()); + } + } + + return lastLbraceOffset; + } + // TODO: better name for this method public static int findRightmostRParen(HighlighterIterator iterator, IElementType rparenTokenType, diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index 191555d68323..15451cf444e4 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -365,3 +365,4 @@ ide.open.file.in.temp.project.dir.description=Enables opening file in temp proje editor.allow.multiple.carets=false embed.scene.builder=false +typing.rbrace.reformats.block=true \ No newline at end of file