IDEA-120066 Auto indent on closing curly brace

This commit is contained in:
Maxim.Mossienko
2014-02-23 01:55:59 +01:00
parent 7f105db931
commit f786d1e872
3 changed files with 61 additions and 6 deletions
@@ -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();
@@ -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<IElementType> braceStack = new Stack<IElementType>();
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,
@@ -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