Skip to content

Commit

Permalink
#291: move comments between imports above import list (#292)
Browse files Browse the repository at this point in the history
Summary:
Fix for #291

Pull Request resolved: #292

Reviewed By: cgrushko

Differential Revision: D34424976

Pulled By: strulovich

fbshipit-source-id: 199b6d6644c4e51b08ed06fd3ab052f3b9339ba5
  • Loading branch information
bethcutler authored and facebook-github-bot committed Feb 23, 2022
1 parent 93c7dd9 commit b3cf13a
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 29 deletions.
31 changes: 15 additions & 16 deletions core/src/main/java/com/facebook/ktfmt/format/Formatter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import com.google.googlejavaformat.java.FormatterException
import com.google.googlejavaformat.java.JavaOutput
import org.jetbrains.kotlin.com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.com.intellij.openapi.util.text.StringUtilRt
import org.jetbrains.kotlin.com.intellij.psi.PsiComment
import org.jetbrains.kotlin.com.intellij.psi.PsiElement
import org.jetbrains.kotlin.com.intellij.psi.PsiElementVisitor
import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace
Expand Down Expand Up @@ -144,22 +145,19 @@ object Formatter {
return code
}

fun findNonImportElement(): PsiElement? {
var element = importList.firstChild
while (element != null) {
if (element !is KtImportDirective && element !is PsiWhiteSpace) {
return element
}
element = element.nextSibling
val commentList = mutableListOf<PsiElement>()
// Find non-import elements; comments are moved, in order, to the top of the import list. Other
// non-import elements throw a ParseError.
var element = importList.firstChild
while (element != null) {
if (element is PsiComment) {
commentList.add(element)
} else if (element !is KtImportDirective && element !is PsiWhiteSpace) {
throw ParseError(
"Imports not contiguous: " + element.text,
StringUtil.offsetToLineColumn(code, element.startOffset))
}
return null
}

val nonImportElement = findNonImportElement()
if (nonImportElement != null) {
throw ParseError(
"Imports not contiguous (perhaps a comment separates them?): " + nonImportElement.text,
StringUtil.offsetToLineColumn(code, nonImportElement.startOffset))
element = element.nextSibling
}
fun canonicalText(importDirective: KtImportDirective) =
importDirective.importedFqName?.asString() +
Expand All @@ -169,10 +167,11 @@ object Formatter {
if (importDirective.isAllUnder) "*" else ""

val sortedImports = importList.imports.sortedBy(::canonicalText).distinctBy(::canonicalText)
val importsWithComments = commentList + sortedImports

return code.replaceRange(
importList.startOffset,
importList.endOffset,
sortedImports.joinToString(separator = "\n") { imprt -> imprt.text } + "\n")
importsWithComments.joinToString(separator = "\n") { imprt -> imprt.text } + "\n")
}
}
39 changes: 26 additions & 13 deletions core/src/test/java/com/facebook/ktfmt/format/FormatterTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1031,24 +1031,37 @@ class FormatterTest {
}

@Test
fun `comments between imports are not allowed`() {
fun `comments between imports are moved above import list`() {
val code =
"""
|package com.facebook.ktfmt
|
|import com.google.common.truth.Subject
|/* add */
|import com.google.common.truth.FailureMetadata as Foo
|/* leading comment */
|import com.example.abc
|/* internal comment 1 */
|import com.example.bcd
|// internal comment 2
|import com.example.Sample
|// trailing comment
|
|val x = Sample(abc, bcd)
|""".trimMargin()

try {
Formatter.format(code)
fail()
} catch (e: ParseError) {
assertThat(e.errorDescription).contains("Imports not contiguous")
assertThat(e.lineColumn.line).isEqualTo(3)
assertThat(e.lineColumn.column).isEqualTo(0)
}
val expected =
"""
|package com.facebook.ktfmt
|
|/* leading comment */
|/* internal comment 1 */
|// internal comment 2
|import com.example.Sample
|import com.example.abc
|import com.example.bcd
|
|// trailing comment
|
|val x = Sample(abc, bcd)
|""".trimMargin()
assertThatFormatting(code).isEqualTo(expected)
}

@Test
Expand Down

0 comments on commit b3cf13a

Please sign in to comment.