CPP-12350 Implement calculation of indentation in line from the information of the lexer

* SO inside indent calculation
* line-wide comment as indent anchor
* indent in pure blocks
* improvements in shared indent calculator for enclosed statements
This commit is contained in:
Alexey Utkin
2018-04-24 15:14:22 +03:00
parent 776b754fde
commit 10271291eb
4 changed files with 78 additions and 3 deletions
@@ -26,10 +26,11 @@ import com.intellij.psi.TokenType;
import com.intellij.psi.impl.source.codeStyle.SemanticEditorPosition;
import com.intellij.psi.impl.source.codeStyle.lineIndent.JavaLikeLangLineIndentProvider;
import com.intellij.psi.tree.IElementType;
import java.util.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import static com.intellij.formatting.Indent.Type.CONTINUATION;
import static com.intellij.psi.impl.source.codeStyle.lineIndent.JavaLikeLangLineIndentProvider.JavaLikeElement.*;
@@ -51,6 +52,7 @@ public class JavaLineIndentProvider extends JavaLikeLangLineIndentProvider {
SYNTAX_MAP.put(JavaTokenType.CASE_KEYWORD, SwitchCase);
SYNTAX_MAP.put(JavaTokenType.DEFAULT_KEYWORD, SwitchDefault);
SYNTAX_MAP.put(JavaTokenType.IF_KEYWORD, IfKeyword);
SYNTAX_MAP.put(JavaTokenType.WHILE_KEYWORD, IfKeyword);
SYNTAX_MAP.put(JavaTokenType.ELSE_KEYWORD, ElseKeyword);
SYNTAX_MAP.put(JavaTokenType.FOR_KEYWORD, ForKeyword);
SYNTAX_MAP.put(JavaTokenType.DO_KEYWORD, DoKeyword);
@@ -215,6 +215,55 @@ public class JavaEnterActionTest extends AbstractEnterActionTestCase {
") {}");
}
public void testEnter_AfterStatementWithoutBlock() throws IOException {
doTextTest("java",
"class T {\n" +
" void test() {\n" +
" if (true)\n" +
" while (true) <caret>\n" +
" }\n" +
"}\n",
"class T {\n" +
" void test() {\n" +
" if (true)\n" +
" while (true) \n" +
" <caret>\n" +
" }\n" +
"}\n");
doTextTest("java",
"class T {\n" +
" void test() {\n" +
" if (true)\n" +
" while (true) {<caret>\n" +
" }\n" +
"}\n",
"class T {\n" +
" void test() {\n" +
" if (true)\n" +
" while (true) {\n" +
" <caret>\n" +
" }\n" +
" }\n" +
"}\n");
doTextTest("java",
"class T {\n" +
" void test() {\n" +
" if (true)\n" +
" try {<caret>\n" +
" }\n" +
"}\n",
"class T {\n" +
" void test() {\n" +
" if (true)\n" +
" try {\n" +
" <caret>\n" +
" }\n" +
" }\n" +
"}\n");
}
public void testEnter_AfterStatementWithLabel() throws IOException {
// as prev
doTextTest("java",
@@ -30,6 +30,8 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import static java.lang.Integer.min;
/**
* @author Rustam Vishnyakov
*/
@@ -305,7 +307,11 @@ public class SemanticEditorPosition {
@Override
public String toString() {
return myIterator.getTokenType().toString();
return myIterator.atEnd()
? "atEnd"
: myIterator.getTokenType().toString()
+ "=>"
+ getChars().subSequence(getStartOffset(), min(getStartOffset() + 255, getChars().length()));
}
public SemanticEditorPosition copy() {
@@ -287,6 +287,9 @@ public abstract class JavaLikeLangLineIndentProvider implements LineIndentProvid
position.moveBeforeParentheses(ArrayOpeningBracket, ArrayClosingBracket);
continue;
}
else if (isStartOfStatementWithOptionalBlock(position)) {
return position.getStartOffset();
}
else if (position.isAtAnyOf(Semicolon,
BlockOpeningBrace,
BlockComment,
@@ -294,7 +297,7 @@ public abstract class JavaLikeLangLineIndentProvider implements LineIndentProvid
LeftParenthesis,
LanguageStartDelimiter) ||
(position.getLanguage() != Language.ANY) && !position.isAtLanguage(currLanguage)) {
SemanticEditorPosition statementStart = getPosition(position.getEditor(), position.getStartOffset());
SemanticEditorPosition statementStart = position.copy();
statementStart = statementStart.after().afterOptionalMix(Whitespace, LineComment);
if (!isIndentProvider(statementStart, ignoreLabels)) {
final SemanticEditorPosition maybeColon = statementStart.afterOptionalMix(Whitespace, BlockComment).after();
@@ -315,6 +318,21 @@ public abstract class JavaLikeLangLineIndentProvider implements LineIndentProvid
return 0;
}
/**
* Returns {@code true} if the {@code position} starts the statement that <i>can</i> have a code block.
* In C-kile languages it is one of {@code if, else, for, while, do, try}.
*
* @param position
*/
protected boolean isStartOfStatementWithOptionalBlock(@NotNull SemanticEditorPosition position) {
return position.isAtAnyOf(
ElseKeyword,
IfKeyword,
ForKeyword,
TryKeyword,
DoKeyword);
}
private static boolean atBlockStartAndNeedBlockIndent(@NotNull SemanticEditorPosition position) {
return position.isAt(BlockOpeningBrace);
}