From f87263e739876c2910de7bf10015703b33e54a5a Mon Sep 17 00:00:00 2001 From: Nick Reid Date: Thu, 7 Nov 2024 04:43:04 +0000 Subject: [PATCH] Report an error on unclosed comments Otherwise formatting succeeds and moves all subsequent code into the comment too. This is especially bad for nested comments, which have a surprising syntax. --- .../com/facebook/ktfmt/format/Tokenizer.kt | 5 ++ .../facebook/ktfmt/format/TokenizerTest.kt | 60 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/core/src/main/java/com/facebook/ktfmt/format/Tokenizer.kt b/core/src/main/java/com/facebook/ktfmt/format/Tokenizer.kt index a3730082..4192c26e 100644 --- a/core/src/main/java/com/facebook/ktfmt/format/Tokenizer.kt +++ b/core/src/main/java/com/facebook/ktfmt/format/Tokenizer.kt @@ -17,6 +17,7 @@ package com.facebook.ktfmt.format import java.util.regex.Pattern +import org.jetbrains.kotlin.com.intellij.openapi.util.text.StringUtil import org.jetbrains.kotlin.com.intellij.psi.PsiComment import org.jetbrains.kotlin.com.intellij.psi.PsiElement import org.jetbrains.kotlin.com.intellij.psi.PsiWhiteSpace @@ -53,6 +54,10 @@ class Tokenizer(private val fileText: String, val file: KtFile) : KtTreeVisitorV val originalText = fileText.substring(startIndex, endIndex) when (element) { is PsiComment -> { + if (element.text.startsWith("/*") && !element.text.endsWith("*/")) { + throw ParseError( + "Unclosed comment", StringUtil.offsetToLineColumn(fileText, element.startOffset)) + } toks.add( KotlinTok( index = index, diff --git a/core/src/test/java/com/facebook/ktfmt/format/TokenizerTest.kt b/core/src/test/java/com/facebook/ktfmt/format/TokenizerTest.kt index e645990f..9d2b7afe 100644 --- a/core/src/test/java/com/facebook/ktfmt/format/TokenizerTest.kt +++ b/core/src/test/java/com/facebook/ktfmt/format/TokenizerTest.kt @@ -17,6 +17,7 @@ package com.facebook.ktfmt.format import com.google.common.truth.Truth.assertThat +import kotlin.test.assertFailsWith import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -218,4 +219,63 @@ class TokenizerTest { 23) .inOrder() } + + @Test + fun `Unclosed comment obvious`() { + assertParseError( + """ + |package a.b + |/* + |class A {} + |""" + .trimMargin(), + "2:1: error: Unclosed comment") + } + + @Test + fun `Unclosed comment too short`() { + assertParseError( + """ + |package a.b + |/*/ + |class A {} + |""" + .trimMargin(), + "2:1: error: Unclosed comment") + } + + @Test + fun `Unclosed comment nested`() { + assertParseError( + """ + |package a.b + |/* /* */ + |class A {} + |""" + .trimMargin(), + "2:1: error: Unclosed comment") + } + + @Test + fun `Unclosed comment nested EOF`() { + // TODO: https://youtrack.jetbrains.com/issue/KT-72887 - This should be an error. + assertParseError( + """ + |package a.b + |class A {} + |/* /* */""" + .trimMargin(), + null) + } + + private fun assertParseError(code: String, message: String?) { + val file = Parser.parse(code) + val tokenizer = Tokenizer(code, file) + if (message == null) { + file.accept(tokenizer) + } else { + val e = assertFailsWith { file.accept(tokenizer) } + assertThat(e).hasMessageThat().isEqualTo(message) + } + } }