NodeIndentStrategy: J2K and cleanup
This commit is contained in:
@@ -17,7 +17,6 @@
|
|||||||
package org.jetbrains.kotlin.idea.formatter
|
package org.jetbrains.kotlin.idea.formatter
|
||||||
|
|
||||||
import com.intellij.formatting.*
|
import com.intellij.formatting.*
|
||||||
import com.intellij.formatting.ChildAttributes.DELEGATE_TO_NEXT_CHILD
|
|
||||||
import com.intellij.lang.ASTNode
|
import com.intellij.lang.ASTNode
|
||||||
import com.intellij.psi.TokenType
|
import com.intellij.psi.TokenType
|
||||||
import com.intellij.psi.codeStyle.CodeStyleSettings
|
import com.intellij.psi.codeStyle.CodeStyleSettings
|
||||||
@@ -26,7 +25,7 @@ import com.intellij.psi.tree.TokenSet
|
|||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
|
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
|
||||||
import org.jetbrains.kotlin.idea.formatter.NodeIndentStrategy.strategy
|
import org.jetbrains.kotlin.idea.formatter.NodeIndentStrategy.Companion.strategy
|
||||||
import org.jetbrains.kotlin.kdoc.lexer.KDocTokens
|
import org.jetbrains.kotlin.kdoc.lexer.KDocTokens
|
||||||
import org.jetbrains.kotlin.kdoc.parser.KDocElementTypes
|
import org.jetbrains.kotlin.kdoc.parser.KDocElementTypes
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
@@ -330,21 +329,21 @@ abstract class KotlinCommonBlock(
|
|||||||
|
|
||||||
private val INDENT_RULES = arrayOf<NodeIndentStrategy>(
|
private val INDENT_RULES = arrayOf<NodeIndentStrategy>(
|
||||||
strategy("No indent for braces in blocks")
|
strategy("No indent for braces in blocks")
|
||||||
.`in`(KtNodeTypes.BLOCK, KtNodeTypes.CLASS_BODY, KtNodeTypes.FUNCTION_LITERAL)
|
.within(KtNodeTypes.BLOCK, KtNodeTypes.CLASS_BODY, KtNodeTypes.FUNCTION_LITERAL)
|
||||||
.forType(RBRACE, LBRACE)
|
.forType(RBRACE, LBRACE)
|
||||||
.set(Indent.getNoneIndent()),
|
.set(Indent.getNoneIndent()),
|
||||||
|
|
||||||
strategy("Indent for block content")
|
strategy("Indent for block content")
|
||||||
.`in`(KtNodeTypes.BLOCK, KtNodeTypes.CLASS_BODY, KtNodeTypes.FUNCTION_LITERAL)
|
.within(KtNodeTypes.BLOCK, KtNodeTypes.CLASS_BODY, KtNodeTypes.FUNCTION_LITERAL)
|
||||||
.notForType(RBRACE, LBRACE, KtNodeTypes.BLOCK)
|
.notForType(RBRACE, LBRACE, KtNodeTypes.BLOCK)
|
||||||
.set(Indent.getNormalIndent(false)),
|
.set(Indent.getNormalIndent(false)),
|
||||||
|
|
||||||
strategy("Indent for property accessors")
|
strategy("Indent for property accessors")
|
||||||
.`in`(KtNodeTypes.PROPERTY).forType(KtNodeTypes.PROPERTY_ACCESSOR)
|
.within(KtNodeTypes.PROPERTY).forType(KtNodeTypes.PROPERTY_ACCESSOR)
|
||||||
.set(Indent.getNormalIndent()),
|
.set(Indent.getNormalIndent()),
|
||||||
|
|
||||||
strategy("For a single statement in 'for'")
|
strategy("For a single statement in 'for'")
|
||||||
.`in`(KtNodeTypes.BODY).notForType(KtNodeTypes.BLOCK)
|
.within(KtNodeTypes.BODY).notForType(KtNodeTypes.BLOCK)
|
||||||
.set(Indent.getNormalIndent()),
|
.set(Indent.getNormalIndent()),
|
||||||
|
|
||||||
strategy("For the entry in when")
|
strategy("For the entry in when")
|
||||||
@@ -352,51 +351,51 @@ private val INDENT_RULES = arrayOf<NodeIndentStrategy>(
|
|||||||
.set(Indent.getNormalIndent()),
|
.set(Indent.getNormalIndent()),
|
||||||
|
|
||||||
strategy("For single statement in THEN and ELSE")
|
strategy("For single statement in THEN and ELSE")
|
||||||
.`in`(KtNodeTypes.THEN, KtNodeTypes.ELSE).notForType(KtNodeTypes.BLOCK)
|
.within(KtNodeTypes.THEN, KtNodeTypes.ELSE).notForType(KtNodeTypes.BLOCK)
|
||||||
.set(Indent.getNormalIndent()),
|
.set(Indent.getNormalIndent()),
|
||||||
|
|
||||||
strategy("Indent for parts")
|
strategy("Indent for parts")
|
||||||
.`in`(KtNodeTypes.PROPERTY, KtNodeTypes.FUN, KtNodeTypes.DESTRUCTURING_DECLARATION, KtNodeTypes.SECONDARY_CONSTRUCTOR)
|
.within(KtNodeTypes.PROPERTY, KtNodeTypes.FUN, KtNodeTypes.DESTRUCTURING_DECLARATION, KtNodeTypes.SECONDARY_CONSTRUCTOR)
|
||||||
.notForType(KtNodeTypes.BLOCK, FUN_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, CONSTRUCTOR_KEYWORD)
|
.notForType(KtNodeTypes.BLOCK, FUN_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, CONSTRUCTOR_KEYWORD)
|
||||||
.set(Indent.getContinuationWithoutFirstIndent()),
|
.set(Indent.getContinuationWithoutFirstIndent()),
|
||||||
|
|
||||||
strategy("Chained calls")
|
strategy("Chained calls")
|
||||||
.`in`(KtNodeTypes.DOT_QUALIFIED_EXPRESSION, KtNodeTypes.SAFE_ACCESS_EXPRESSION)
|
.within(KtNodeTypes.DOT_QUALIFIED_EXPRESSION, KtNodeTypes.SAFE_ACCESS_EXPRESSION)
|
||||||
.set(Indent.getContinuationWithoutFirstIndent(false)),
|
.set(Indent.getContinuationWithoutFirstIndent(false)),
|
||||||
|
|
||||||
strategy("Colon of delegation list")
|
strategy("Colon of delegation list")
|
||||||
.`in`(KtNodeTypes.CLASS, KtNodeTypes.OBJECT_DECLARATION)
|
.within(KtNodeTypes.CLASS, KtNodeTypes.OBJECT_DECLARATION)
|
||||||
.forType(KtTokens.COLON)
|
.forType(KtTokens.COLON)
|
||||||
.set(Indent.getNormalIndent(false)),
|
.set(Indent.getNormalIndent(false)),
|
||||||
|
|
||||||
strategy("Delegation list")
|
strategy("Delegation list")
|
||||||
.`in`(KtNodeTypes.SUPER_TYPE_LIST, KtNodeTypes.INITIALIZER_LIST)
|
.within(KtNodeTypes.SUPER_TYPE_LIST, KtNodeTypes.INITIALIZER_LIST)
|
||||||
.set(Indent.getContinuationIndent(false)),
|
.set(Indent.getContinuationIndent(false)),
|
||||||
|
|
||||||
strategy("Indices")
|
strategy("Indices")
|
||||||
.`in`(KtNodeTypes.INDICES)
|
.within(KtNodeTypes.INDICES)
|
||||||
.set(Indent.getContinuationIndent(false)),
|
.set(Indent.getContinuationIndent(false)),
|
||||||
|
|
||||||
strategy("Binary expressions")
|
strategy("Binary expressions")
|
||||||
.`in`(BINARY_EXPRESSIONS)
|
.within(BINARY_EXPRESSIONS)
|
||||||
.set(Indent.getContinuationWithoutFirstIndent(false)),
|
.set(Indent.getContinuationWithoutFirstIndent(false)),
|
||||||
|
|
||||||
strategy("Parenthesized expression")
|
strategy("Parenthesized expression")
|
||||||
.`in`(KtNodeTypes.PARENTHESIZED)
|
.within(KtNodeTypes.PARENTHESIZED)
|
||||||
.set(Indent.getContinuationWithoutFirstIndent(false)),
|
.set(Indent.getContinuationWithoutFirstIndent(false)),
|
||||||
|
|
||||||
strategy("Round Brackets around conditions")
|
strategy("Round Brackets around conditions")
|
||||||
.forType(LPAR, RPAR)
|
.forType(LPAR, RPAR)
|
||||||
.`in`(KtNodeTypes.IF, KtNodeTypes.WHEN_ENTRY, KtNodeTypes.WHILE, KtNodeTypes.DO_WHILE)
|
.within(KtNodeTypes.IF, KtNodeTypes.WHEN_ENTRY, KtNodeTypes.WHILE, KtNodeTypes.DO_WHILE)
|
||||||
.set(Indent.getContinuationWithoutFirstIndent(true)),
|
.set(Indent.getContinuationWithoutFirstIndent(true)),
|
||||||
|
|
||||||
strategy("KDoc comment indent")
|
strategy("KDoc comment indent")
|
||||||
.`in`(KDOC_CONTENT)
|
.within(KDOC_CONTENT)
|
||||||
.forType(KDocTokens.LEADING_ASTERISK, KDocTokens.END)
|
.forType(KDocTokens.LEADING_ASTERISK, KDocTokens.END)
|
||||||
.set(Indent.getSpaceIndent(KDOC_COMMENT_INDENT)),
|
.set(Indent.getSpaceIndent(KDOC_COMMENT_INDENT)),
|
||||||
|
|
||||||
strategy("Block in when entry")
|
strategy("Block in when entry")
|
||||||
.`in`(KtNodeTypes.WHEN_ENTRY)
|
.within(KtNodeTypes.WHEN_ENTRY)
|
||||||
.notForType(KtNodeTypes.BLOCK, KtNodeTypes.WHEN_CONDITION_EXPRESSION, KtNodeTypes.WHEN_CONDITION_IN_RANGE, KtNodeTypes.WHEN_CONDITION_IS_PATTERN, ELSE_KEYWORD, ARROW)
|
.notForType(KtNodeTypes.BLOCK, KtNodeTypes.WHEN_CONDITION_EXPRESSION, KtNodeTypes.WHEN_CONDITION_IN_RANGE, KtNodeTypes.WHEN_CONDITION_IS_PATTERN, ELSE_KEYWORD, ARROW)
|
||||||
.set(Indent.getNormalIndent()))
|
.set(Indent.getNormalIndent()))
|
||||||
|
|
||||||
|
|||||||
@@ -14,151 +14,130 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.formatter;
|
package org.jetbrains.kotlin.idea.formatter
|
||||||
|
|
||||||
import com.intellij.formatting.Indent;
|
import com.intellij.formatting.Indent
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType
|
||||||
import com.intellij.psi.tree.TokenSet;
|
import com.intellij.psi.tree.TokenSet
|
||||||
import org.jetbrains.annotations.NotNull;
|
import java.util.*
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
abstract class NodeIndentStrategy {
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@SuppressWarnings("UnusedDeclaration")
|
abstract fun getIndent(node: ASTNode): Indent?
|
||||||
public abstract class NodeIndentStrategy {
|
|
||||||
public static NodeIndentStrategy constIndent(Indent indent) {
|
|
||||||
return new ConstIndentStrategy(indent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PositionStrategy strategy(@Nullable String debugInfo) {
|
class ConstIndentStrategy(private val indent: Indent) : NodeIndentStrategy() {
|
||||||
return new PositionStrategy(debugInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
override fun getIndent(node: ASTNode): Indent? {
|
||||||
public abstract Indent getIndent(@NotNull ASTNode node);
|
return indent
|
||||||
|
|
||||||
public static class ConstIndentStrategy extends NodeIndentStrategy {
|
|
||||||
private final Indent indent;
|
|
||||||
|
|
||||||
public ConstIndentStrategy(Indent indent) {
|
|
||||||
this.indent = indent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public Indent getIndent(@NotNull ASTNode node) {
|
|
||||||
return indent;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PositionStrategy extends NodeIndentStrategy {
|
class PositionStrategy(private val debugInfo: String?) : NodeIndentStrategy() {
|
||||||
private Indent defaultIndent = Indent.getNoneIndent();
|
private var defaultIndent = Indent.getNoneIndent()
|
||||||
|
|
||||||
private final List<IElementType> in = new ArrayList<IElementType>();
|
private val within = ArrayList<IElementType>()
|
||||||
private final List<IElementType> notIn = new ArrayList<IElementType>();
|
private val notIn = ArrayList<IElementType>()
|
||||||
private final List<IElementType> forElement = new ArrayList<IElementType>();
|
private val forElement = ArrayList<IElementType>()
|
||||||
private final List<IElementType> notForElement = new ArrayList<IElementType>();
|
private val notForElement = ArrayList<IElementType>()
|
||||||
|
|
||||||
private final String debugInfo;
|
override fun toString(): String {
|
||||||
|
return "PositionStrategy " + (debugInfo ?: "No debug info")
|
||||||
public PositionStrategy(@Nullable String debugInfo) {
|
|
||||||
this.debugInfo = debugInfo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
fun set(indent: Indent): PositionStrategy {
|
||||||
public String toString() {
|
defaultIndent = indent
|
||||||
return "PositionStrategy " + (debugInfo != null ? debugInfo : "No debug info");
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
public PositionStrategy set(Indent indent) {
|
fun within(parents: TokenSet): PositionStrategy {
|
||||||
defaultIndent = indent;
|
val types = parents.types
|
||||||
return this;
|
if (types.isEmpty()) {
|
||||||
}
|
throw IllegalArgumentException("Empty token set is unexpected")
|
||||||
|
|
||||||
public PositionStrategy in(@NotNull TokenSet parents) {
|
|
||||||
IElementType[] types = parents.getTypes();
|
|
||||||
if (types.length == 0) {
|
|
||||||
throw new IllegalArgumentException("Empty token set is unexpected");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fillTypes(in, types[0], Arrays.copyOfRange(types, 1, types.length));
|
fillTypes(within, types[0], Arrays.copyOfRange(types, 1, types.size))
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
public PositionStrategy in(@NotNull IElementType parentType, @NotNull IElementType... orParentTypes) {
|
fun within(parentType: IElementType, vararg orParentTypes: IElementType): PositionStrategy {
|
||||||
fillTypes(in, parentType, orParentTypes);
|
fillTypes(within, parentType, orParentTypes)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
public PositionStrategy notIn(@NotNull IElementType parentType, @NotNull IElementType... orParentTypes) {
|
fun notWithin(parentType: IElementType, vararg orParentTypes: IElementType): PositionStrategy {
|
||||||
fillTypes(notIn, parentType, orParentTypes);
|
fillTypes(notIn, parentType, orParentTypes)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
public PositionStrategy inAny() {
|
fun withinAny(): PositionStrategy {
|
||||||
in.clear();
|
within.clear()
|
||||||
notIn.clear();
|
notIn.clear()
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
public PositionStrategy forType(@NotNull IElementType elementType, @NotNull IElementType... otherTypes) {
|
fun forType(elementType: IElementType, vararg otherTypes: IElementType): PositionStrategy {
|
||||||
fillTypes(forElement, elementType, otherTypes);
|
fillTypes(forElement, elementType, otherTypes)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
public PositionStrategy notForType(@NotNull IElementType elementType, @NotNull IElementType... otherTypes) {
|
fun notForType(elementType: IElementType, vararg otherTypes: IElementType): PositionStrategy {
|
||||||
fillTypes(notForElement, elementType, otherTypes);
|
fillTypes(notForElement, elementType, otherTypes)
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
public PositionStrategy forAny() {
|
fun forAny(): PositionStrategy {
|
||||||
forElement.clear();
|
forElement.clear()
|
||||||
notForElement.clear();
|
notForElement.clear()
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
override fun getIndent(node: ASTNode): Indent? {
|
||||||
@Override
|
|
||||||
public Indent getIndent(@NotNull ASTNode node) {
|
|
||||||
if (!forElement.isEmpty()) {
|
if (!forElement.isEmpty()) {
|
||||||
if (!forElement.contains(node.getElementType())) {
|
if (!forElement.contains(node.elementType)) {
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notForElement.contains(node.getElementType())) {
|
if (notForElement.contains(node.elementType)) {
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNode parent = node.getTreeParent();
|
val parent = node.treeParent
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
if (!in.isEmpty()) {
|
if (!within.isEmpty()) {
|
||||||
if (!in.contains(parent.getElementType())) {
|
if (!within.contains(parent.elementType)) {
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notIn.contains(parent.getElementType())) {
|
if (notIn.contains(parent.elementType)) {
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!in.isEmpty()) {
|
if (!within.isEmpty()) {
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return defaultIndent;
|
return defaultIndent
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fillTypes(List<IElementType> resultCollection, IElementType singleType, IElementType[] otherTypes) {
|
private fun fillTypes(resultCollection: MutableList<IElementType>, singleType: IElementType, otherTypes: Array<out IElementType>) {
|
||||||
resultCollection.clear();
|
resultCollection.clear()
|
||||||
resultCollection.add(singleType);
|
resultCollection.add(singleType)
|
||||||
Collections.addAll(resultCollection, otherTypes);
|
Collections.addAll(resultCollection, *otherTypes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun constIndent(indent: Indent): NodeIndentStrategy {
|
||||||
|
return ConstIndentStrategy(indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun strategy(debugInfo: String?): PositionStrategy {
|
||||||
|
return PositionStrategy(debugInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user