Formatter: support trailing comma in value parameters

#KT-34744
This commit is contained in:
Dmitry Gridin
2019-12-18 21:01:08 +07:00
parent 463728a96a
commit 13ae4a28a8
51 changed files with 1644 additions and 70 deletions
@@ -11,7 +11,10 @@ import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.codeStyle.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
import com.intellij.psi.codeStyle.PackageEntry;
import com.intellij.psi.codeStyle.PackageEntryTable;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -50,6 +53,7 @@ public class KotlinCodeStyleSettings extends CustomCodeStyleSettings {
public int WRAP_EXPRESSION_BODY_FUNCTIONS = 0;
public int WRAP_ELVIS_EXPRESSIONS = 1;
public boolean IF_RPAREN_ON_NEW_LINE = false;
public boolean ALLOW_TRAILING_COMMA = true;
@ReflectionUtil.SkipInEquals
public String CODE_STYLE_DEFAULTS = null;
@@ -19,6 +19,7 @@ import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.KtNodeTypes.*
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
import org.jetbrains.kotlin.idea.formatter.NodeIndentStrategy.Companion.strategy
import org.jetbrains.kotlin.idea.util.getLineCount
import org.jetbrains.kotlin.idea.util.requireNode
import org.jetbrains.kotlin.kdoc.lexer.KDocTokens
import org.jetbrains.kotlin.kdoc.parser.KDocElementTypes
@@ -598,7 +599,14 @@ abstract class KotlinCommonBlock(
parentElementType === SECONDARY_CONSTRUCTOR
) {
val wrap = Wrap.createWrap(commonSettings.METHOD_PARAMETERS_WRAP, false)
return { childElement -> wrap.takeIf { childElement.elementType === VALUE_PARAMETER } }
val withTrailingComma = node.withTrailingComma
return { childElement ->
val childElementType = childElement.elementType
if (withTrailingComma && (childElementType === RPAR || getPrevWithoutWhitespaceAndComments(childElement)?.elementType === LPAR))
Wrap.createWrap(WrapType.ALWAYS, true)
else
wrap.takeIf { childElementType === VALUE_PARAMETER }
}
}
}
@@ -698,6 +706,13 @@ abstract class KotlinCommonBlock(
return ::noWrapping
}
private val ASTNode.withTrailingComma: Boolean
get() = when {
lastChildNode?.let { getPrevWithoutWhitespaceAndComments(it) }?.elementType === COMMA -> true
settings.kotlinCustomSettings.ALLOW_TRAILING_COMMA -> psi?.getLineCount()?.let { it > 1 } == true
else -> false
}
}
private fun ASTNode.isFirstParameter(): Boolean = treePrev?.elementType == LPAR
@@ -271,10 +271,9 @@ fun createSpacingBuilder(settings: CodeStyleSettings, builderUtil: KotlinSpacing
after(DOC_COMMENT).lineBreakInCode()
// =============== Spacing ================
before(COMMA).spaceIf(kotlinCommonSettings.SPACE_BEFORE_COMMA)
before(COMMA).spacesNoLineBreak(if (kotlinCommonSettings.SPACE_BEFORE_COMMA) 1 else 0)
after(COMMA).spaceIf(kotlinCommonSettings.SPACE_AFTER_COMMA)
val spacesAroundAssignment = if (kotlinCommonSettings.SPACE_AROUND_ASSIGNMENT_OPERATORS) 1 else 0
beforeInside(EQ, PROPERTY).spacesNoLineBreak(spacesAroundAssignment)
beforeInside(EQ, FUN).spacing(spacesAroundAssignment, spacesAroundAssignment, 0, false, 0)
@@ -1,11 +1,15 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.util
import com.intellij.formatting.ASTBlock
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
/*
@@ -16,4 +20,20 @@ fun ASTBlock.requireNode() = node ?: error("ASTBlock.getNode() returned null")
/**
* Can be removed with all usages after moving master to 1.3 with new default code style settings.
*/
val isDefaultOfficialCodeStyle by lazy { !KotlinCodeStyleSettings.defaultSettings().CONTINUATION_INDENT_FOR_CHAINED_CALLS }
val isDefaultOfficialCodeStyle by lazy { !KotlinCodeStyleSettings.defaultSettings().CONTINUATION_INDENT_FOR_CHAINED_CALLS }
fun PsiElement.getLineCount(): Int {
val doc = containingFile?.let { file -> file.viewProvider.document ?: PsiDocumentManager.getInstance(project).getDocument(file) }
if (doc != null) {
val spaceRange = textRange ?: TextRange.EMPTY_RANGE
if (spaceRange.endOffset <= doc.textLength) {
val startLine = doc.getLineNumber(spaceRange.startOffset)
val endLine = doc.getLineNumber(spaceRange.endOffset)
return endLine - startLine + 1
}
}
return StringUtil.getLineBreakCount(text ?: "") + 1
}