Support line indent calculation after case/default

This commit is contained in:
Rustam Vishnyakov
2016-05-27 13:38:05 +03:00
parent fc948a98a7
commit 972a88c297
3 changed files with 52 additions and 26 deletions
@@ -26,19 +26,24 @@ import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.intellij.psi.impl.source.codeStyle.JavaLikeLangLineIndentProvider.JavaLikeElement.*;
/**
* @author Rustam Vishnyakov
*/
public class JavaLineIndentProvider extends JavaLikeLangLineIndentProvider {
private final static HashMap<IElementType, SemanticEditorPosition.SyntaxElement> SYNTAX_MAP = new HashMap<>();
static {
SYNTAX_MAP.put(TokenType.WHITE_SPACE, JavaLikeElement.Whitespace);
SYNTAX_MAP.put(JavaTokenType.SEMICOLON, JavaLikeElement.Semicolon);
SYNTAX_MAP.put(JavaTokenType.LBRACE, JavaLikeElement.BlockOpeningBrace);
SYNTAX_MAP.put(JavaTokenType.RBRACE, JavaLikeElement.BlockClosingBrace);
SYNTAX_MAP.put(JavaTokenType.LBRACKET, JavaLikeElement.ArrayOpeningBracket);
SYNTAX_MAP.put(JavaTokenType.RPARENTH, JavaLikeElement.RightParenthesis);
SYNTAX_MAP.put(JavaTokenType.LPARENTH, JavaLikeElement.LeftParenthesis);
SYNTAX_MAP.put(TokenType.WHITE_SPACE, Whitespace);
SYNTAX_MAP.put(JavaTokenType.SEMICOLON, Semicolon);
SYNTAX_MAP.put(JavaTokenType.LBRACE, BlockOpeningBrace);
SYNTAX_MAP.put(JavaTokenType.RBRACE, BlockClosingBrace);
SYNTAX_MAP.put(JavaTokenType.LBRACKET, ArrayOpeningBracket);
SYNTAX_MAP.put(JavaTokenType.RPARENTH, RightParenthesis);
SYNTAX_MAP.put(JavaTokenType.LPARENTH, LeftParenthesis);
SYNTAX_MAP.put(JavaTokenType.COLON, Colon);
SYNTAX_MAP.put(JavaTokenType.CASE_KEYWORD, SwitchCase);
SYNTAX_MAP.put(JavaTokenType.DEFAULT_KEYWORD, SwitchDefault);
}
@Nullable
@@ -34,6 +34,7 @@ import org.jetbrains.annotations.Nullable;
import static com.intellij.formatting.Indent.Type;
import static com.intellij.formatting.Indent.Type.*;
import static com.intellij.psi.impl.source.codeStyle.JavaLikeLangLineIndentProvider.JavaLikeElement.*;
/**
* A base class Java-like language line indent provider. If JavaLikeLangLineIndentProvider is unable to calculate
@@ -41,14 +42,17 @@ import static com.intellij.formatting.Indent.Type.*;
*/
public abstract class JavaLikeLangLineIndentProvider extends FormatterBasedLineIndentProvider {
protected enum JavaLikeElement implements SyntaxElement {
public enum JavaLikeElement implements SyntaxElement {
Whitespace,
Semicolon,
BlockOpeningBrace,
BlockClosingBrace,
ArrayOpeningBracket,
RightParenthesis,
LeftParenthesis
LeftParenthesis,
Colon,
SwitchCase,
SwitchDefault
}
@Nullable
@@ -66,25 +70,30 @@ public abstract class JavaLikeLangLineIndentProvider extends FormatterBasedLineI
if (offset > 0) {
offset--;
if (getPosition(editor, offset).matchesRule(
position -> position.isAt(JavaLikeElement.Whitespace) &&
position -> position.isAt(Whitespace) &&
position.isAtMultiline())) {
if (getPosition(editor, offset).matchesRule(
position -> position
.before()
.beforeOptional(JavaLikeElement.Semicolon)
.beforeOptional(JavaLikeElement.Whitespace)
.isAt(JavaLikeElement.BlockClosingBrace))) {
return createIndentData(getBlockIndentType(project, language), JavaLikeElement.BlockClosingBrace);
.beforeOptional(Semicolon)
.beforeOptional(Whitespace)
.isAt(BlockClosingBrace))) {
return createIndentData(getBlockIndentType(project, language), BlockClosingBrace);
}
else if (getPosition(editor, offset).matchesRule(
position -> position.before().isAt(JavaLikeElement.ArrayOpeningBracket)
position -> position.before().isAt(ArrayOpeningBracket)
)) {
return createIndentData(CONTINUATION, JavaLikeElement.ArrayOpeningBracket);
return createIndentData(CONTINUATION, ArrayOpeningBracket);
}
else if (getPosition(editor, offset).matchesRule(
position -> position.before().isAt(JavaLikeElement.BlockOpeningBrace)
position -> position.before().isAt(BlockOpeningBrace)
)) {
return createIndentData(getIndentTypeInBlock(project, language), JavaLikeElement.BlockOpeningBrace);
return createIndentData(getIndentTypeInBlock(project, language), BlockOpeningBrace);
}
else if (getPosition(editor, offset).matchesRule(
position -> position.before().isAt(Colon) && position.isAfterOnSameLine(SwitchCase, SwitchDefault)
)) {
return createIndentData(NORMAL, SwitchCase);
}
}
}
@@ -152,7 +161,7 @@ public abstract class JavaLikeLangLineIndentProvider extends FormatterBasedLineI
@NotNull CharSequence docChars,
@NotNull SyntaxElement afterElement,
int offset) {
if (JavaLikeElement.BlockOpeningBrace.equals(afterElement) && !isOnSeparateLine(editor, afterElement, offset)) {
if (BlockOpeningBrace.equals(afterElement) && !isOnSeparateLine(editor, afterElement, offset)) {
return findStatementStart(editor, afterElement, offset);
}
return CharArrayUtil.shiftBackward(docChars, offset, " \t\n\r");
@@ -161,10 +170,10 @@ public abstract class JavaLikeLangLineIndentProvider extends FormatterBasedLineI
private boolean isOnSeparateLine(@NotNull Editor editor, @NotNull SyntaxElement element, int offset) {
SemanticEditorPosition position = getPosition(editor, offset);
position.beforeOptional(JavaLikeElement.Whitespace);
position.beforeOptional(Whitespace);
if (position.isAt(element)) {
position.before();
if (position.isAtEnd() || position.isAt(JavaLikeElement.Whitespace) && position.isAtMultiline()) return true;
if (position.isAtEnd() || position.isAt(Whitespace) && position.isAtMultiline()) return true;
}
return false;
}
@@ -173,14 +182,14 @@ public abstract class JavaLikeLangLineIndentProvider extends FormatterBasedLineI
private int findStatementStart(@NotNull Editor editor, @NotNull SyntaxElement afterElement, int offset) {
SemanticEditorPosition position = getPosition(editor, offset);
position
.beforeOptional(JavaLikeElement.Whitespace)
.beforeOptional(Whitespace)
.beforeOptional(afterElement)
.beforeOptional(JavaLikeElement.Whitespace);
if (position.isAt(JavaLikeElement.RightParenthesis)) {
position.beforeParentheses(JavaLikeElement.LeftParenthesis, JavaLikeElement.RightParenthesis);
.beforeOptional(Whitespace);
if (position.isAt(RightParenthesis)) {
position.beforeParentheses(LeftParenthesis, RightParenthesis);
}
while (!position.isAtEnd()) {
if (position.isAt(JavaLikeElement.Whitespace) && position.isAtMultiline()) {
if (position.isAt(Whitespace) && position.isAtMultiline()) {
return position.after().getStartOffset();
}
position.before();
@@ -81,6 +81,18 @@ public abstract class SemanticEditorPosition {
return this;
}
public boolean isAfterOnSameLine(@NotNull SyntaxElement... syntaxElements) {
myIterator.retreat();
while (!myIterator.atEnd() && !isAtMultiline()) {
SyntaxElement currElement = map(myIterator.getTokenType());
for (SyntaxElement element : syntaxElements) {
if (element.equals(currElement)) return true;
}
myIterator.retreat();
}
return false;
}
public boolean isAt(@NotNull SyntaxElement syntaxElement) {
return !myIterator.atEnd() && syntaxElement.equals(map(myIterator.getTokenType()));
}