Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).

### Changed

* Reduced overall number of allocations to improve formatting performance (~6-7%) (https://github.com/facebook/ktfmt/pull/620)

## [0.63]

Expand Down
7 changes: 5 additions & 2 deletions core/src/main/java/com/facebook/ktfmt/format/KotlinInput.kt
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,11 @@ class KotlinInput(private val text: String, file: KtFile) : Input() {
)
}

private fun makePositionToColumnMap(toks: List<KotlinTok>) =
ImmutableMap.copyOf(toks.map { it.position to it.column }.toMap())
private fun makePositionToColumnMap(toks: List<KotlinTok>): ImmutableMap<Int, Int> {
val builder = ImmutableMap.builderWithExpectedSize<Int, Int>(toks.size)
toks.forEach { builder.put(it.position, it.column) }
return builder.build()
}

private fun buildToks(file: KtFile, fileText: String): ImmutableList<KotlinTok> {
val tokenizer = Tokenizer(fileText, file)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1619,7 +1619,7 @@ class KotlinInputAstVisitor(
private fun hasSourceNewlineInLambdaBody(lambdaExpression: KtLambdaExpression): Boolean {
val functionLiteral = lambdaExpression.functionLiteral
for (child in functionLiteral.node.children()) {
if (child.psi is PsiWhiteSpace && child.text.contains('\n')) return true
if (child.psi is PsiWhiteSpace && child.textContains('\n')) return true
}
return false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,12 @@ object RedundantElementManager {
}
)

val result = StringBuilder(code)
val elementsToRemove =
redundantSemicolonDetector.getRedundantSemicolonElements() +
redundantImportDetector.getRedundantImportElements() +
trailingCommaDetector.getTrailingCommaElements()
if (elementsToRemove.isEmpty()) return code
val result = StringBuilder(code)

for (element in elementsToRemove.sortedByDescending(PsiElement::endOffset)) {
// Don't insert extra newlines when the semicolon is already a line terminator
Expand Down Expand Up @@ -108,8 +109,9 @@ object RedundantElementManager {
}
)

val result = StringBuilder(code)
val suggestionElements = trailingCommaSuggestor.getTrailingCommaSuggestions()
if (suggestionElements.isEmpty()) return code
val result = StringBuilder(code)

for (element in suggestionElements.sortedByDescending(PsiElement::endOffset)) {
result.insert(element.endOffset, ',')
Expand All @@ -120,6 +122,6 @@ object RedundantElementManager {

private fun PsiElement?.containsNewline(): Boolean {
if (this !is PsiWhiteSpace) return false
return this.text.contains('\n')
return this.textContains('\n')
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ internal class RedundantSemicolonDetector {

/** returns **true** if this element was an extra comma, **false** otherwise. */
private fun isExtraSemicolon(element: PsiElement): Boolean {
if (element.text != ";") {
if (element !is LeafPsiElement || element.elementType != KtTokens.SEMICOLON) {
return false
}

Expand Down
25 changes: 14 additions & 11 deletions core/src/main/java/com/facebook/ktfmt/format/Tokenizer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,16 @@ class Tokenizer(private val fileText: String, val file: KtFile) : KtTreeVisitorV
}

override fun visitElement(element: PsiElement) {
val startIndex = element.startOffset
val endIndex = element.endOffset
val elementText = element.text
val originalText = fileText.substring(startIndex, endIndex)
// Do not materialize text/text ranges when it's non needed -- e.g. for KtFile, composite
// PsiElement(...) etc.
val elementText by lazy(LazyThreadSafetyMode.NONE) { element.text }
val originalText by
lazy(LazyThreadSafetyMode.NONE) {
fileText.substring(element.startOffset, element.endOffset)
}
when (element) {
is PsiComment -> {
if (element.text.startsWith("/*") && !element.text.endsWith("*/")) {
if (elementText.startsWith("/*") && !elementText.endsWith("*/")) {
throw ParseError(
"Unclosed comment",
StringUtil.offsetToLineColumn(fileText, element.startOffset),
Expand All @@ -87,7 +90,7 @@ class Tokenizer(private val fileText: String, val file: KtFile) : KtTreeVisitorV
index = index,
originalText = originalText,
text = elementText,
position = startIndex,
position = element.startOffset,
column = 0,
isToken = treatAsToken,
kind = KtTokens.EOF,
Expand All @@ -105,7 +108,7 @@ class Tokenizer(private val fileText: String, val file: KtFile) : KtTreeVisitorV
originalText,
),
text = elementText,
position = startIndex,
position = element.startOffset,
column = 0,
isToken = true,
kind = KtTokens.EOF,
Expand All @@ -124,11 +127,11 @@ class Tokenizer(private val fileText: String, val file: KtFile) : KtTreeVisitorV
index = -1,
originalText =
fileText.substring(
startIndex + matcher.start(),
startIndex + matcher.end(),
element.startOffset + matcher.start(),
element.startOffset + matcher.end(),
),
text = text,
position = startIndex + matcher.start(),
position = element.startOffset + matcher.start(),
column = 0,
isToken = false,
kind = KtTokens.EOF,
Expand All @@ -141,7 +144,7 @@ class Tokenizer(private val fileText: String, val file: KtFile) : KtTreeVisitorV
index = index,
originalText = originalText,
text = elementText,
position = startIndex,
position = element.startOffset,
column = 0,
isToken = true,
kind = KtTokens.EOF,
Expand Down
12 changes: 6 additions & 6 deletions core/src/main/java/com/facebook/ktfmt/format/TrailingCommas.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package com.facebook.ktfmt.format
import org.jetbrains.kotlin.com.intellij.psi.PsiComment
import org.jetbrains.kotlin.com.intellij.psi.PsiElement
import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtClassBody
import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression
import org.jetbrains.kotlin.psi.KtElement
Expand Down Expand Up @@ -47,10 +49,9 @@ object TrailingCommas {
}

private fun isTrailingComma(element: PsiElement): Boolean {
if (element.text != ",") {
if (element !is LeafPsiElement || element.elementType != KtTokens.COMMA) {
return false
}

return extractManagedList(element.parent)?.trailingComma == element
}
}
Expand All @@ -77,10 +78,6 @@ object TrailingCommas {
* ```
*/
fun takeElement(element: KtElement) {
if (!element.text.contains("\n")) {
return // Only suggest trailing commas where there is already a line break
}

when (element) {
is KtEnumEntry, // Only suggest on the KtClassBody container
is KtWhenEntry -> return
Expand All @@ -99,6 +96,9 @@ object TrailingCommas {
}

val list = extractManagedList(element) ?: return
if (!element.textContains('\n')) {
return // Only suggest trailing commas where there is already a line break
}
if (list.items.size <= 1) {
return // Never insert commas to single-element lists
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import java.util.regex.Pattern.MULTILINE
object WhitespaceTombstones {
/** See [replaceTrailingWhitespaceWithTombstone]. */
const val SPACE_TOMBSTONE = '\u0003'
private val TRAILING_WHITESPACE_PATTERN = Pattern.compile(" ($)", MULTILINE)

fun String.indexOfWhitespaceTombstone(): Int = this.indexOf(SPACE_TOMBSTONE)

Expand All @@ -32,7 +33,7 @@ object WhitespaceTombstones {
* replace it back to a space.
*/
fun replaceTrailingWhitespaceWithTombstone(s: String): String {
return Pattern.compile(" ($)", MULTILINE).matcher(s).replaceAll("$SPACE_TOMBSTONE$1")
return TRAILING_WHITESPACE_PATTERN.matcher(s).replaceAll("$SPACE_TOMBSTONE$1")
}

/** See [replaceTrailingWhitespaceWithTombstone]. */
Expand Down
Loading