[grazie] IJPL-248141 Unpaired symbol ) false positive

Merge-request: IJ-MR-216423
Merged-by: Ilia Permiashkin <ilia.permiashkin@jetbrains.com>

GitOrigin-RevId: 34e3d027c18b657a3e4287a4fe265e166cc025a0
This commit is contained in:
Ilia Permiashkin
2026-07-31 12:47:29 +00:00
committed by intellij-monorepo-bot
parent 0cab72c795
commit 4e226b6901
4 changed files with 81 additions and 13 deletions
@@ -511,4 +511,9 @@ public class TextExtractionTest extends BasePlatformTestCase {
public static TextContent extractText(String fileName, String fileText, int offset, Project project) {
return TextExtractor.findTextAt(createFile(fileName, fileText, project), offset, TextContent.TextDomain.ALL);
}
public static Set<TextContent> extractAllTexts(String fileName, String fileText, Project project) {
PsiFile file = createFile(fileName, fileText, project);
return TextExtractor.findAllTextContents(file.getViewProvider(), TextContent.TextDomain.ALL);
}
}
@@ -5,16 +5,13 @@ import com.intellij.grazie.GrazieTestBase
import com.intellij.grazie.jlanguage.Lang
import com.intellij.grazie.text.TextContent
import com.intellij.grazie.text.TextContentTest
import com.intellij.grazie.text.TextExtractionTest
import com.intellij.grazie.text.TextExtractor
import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
class KotlinGrazieSupportTest28 : GrazieTestBase() {
override fun getProjectDescriptor(): LightProjectDescriptor {
return KotlinWithJdkAndRuntimeLightProjectDescriptor.getInstance()
}
override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.getInstance()
override val additionalEnabledRules: Set<String> = setOf("UPPERCASE_SENTENCE_START")
@@ -88,4 +85,59 @@ class KotlinGrazieSupportTest28 : GrazieTestBase() {
)
myFixture.checkHighlighting()
}
fun `test code-like fragments are not extracted`() {
val texts = TextExtractionTest.extractAllTexts("a.kt", $$"""
/**
* The Markdown lexer folds a nested list item's leading indentation into its `LIST_BULLET`/`LIST_NUMBER` token
* (e.g. `" - "`), so a list / list-item block would otherwise start inside the line's indentation. Trim that
* leading whitespace here so the block starts at its real content; otherwise offset-based consumers such as
* indent auto-detection (`FormatterBasedLineIndentInfoBuilder`) undercount the indent of nested list lines.
*
* With code fence:
* ```
* fun String.helloWorld() {
* println("Hello World, $this")
* }
* ```
* With indentation:
*
* fun String.helloWorld() {
* println("Hello World, $this")
* }
*
* With tilde:
* ~~~
* fun String.helloWorld() {
* println("Hello World, $this")
* }
* ~~~
*
* With backticks:
* `fun main() { println("Hello, Kotlin") }`
*/
fun main() {}
""".trimIndent(), project)
assertEquals(1, texts.size)
assertEquals(texts.first().toString(), """
The Markdown lexer folds a nested list item's leading indentation into its / token
(e.g. ), so a list / list-item block would otherwise start inside the line's indentation. Trim that
leading whitespace here so the block starts at its real content; otherwise offset-based consumers such as
indent auto-detection () undercount the indent of nested list lines.
With code fence:
With indentation:
With tilde:
With backticks:
""".trimIndent())
}
}
@@ -28,13 +28,15 @@ import org.jetbrains.kotlin.psi.psiUtil.isSingleQuoted
import java.util.regex.Pattern
internal class KotlinTextExtractor : TextExtractor() {
private val kdocBuilder = TextContentBuilder.FromPsi
.withUnknown { e -> e.elementType == KDocTokens.MARKDOWN_LINK && e.text.startsWith("[") }
.excluding { e -> e.elementType == KDocTokens.MARKDOWN_LINK && !e.text.startsWith("[") }
.excluding { e -> val elementType = e.elementType
elementType == LEADING_ASTERISK || elementType == CODE_BLOCK_TEXT || elementType == CODE_SPAN_TEXT
}
.removingIndents(" \t").removingLineSuffixes(" \t")
private val kdocBuilder = TextContentBuilder.FromPsi
.withUnknown { e -> e.elementType == KDocTokens.MARKDOWN_LINK && e.text.startsWith("[") }
.excluding { e -> e.elementType == KDocTokens.MARKDOWN_LINK && !e.text.startsWith("[") }
.excluding { e ->
val elementType = e.elementType
elementType == LEADING_ASTERISK || elementType == CODE_BLOCK_TEXT
}
.withUnknown { e -> e.elementType == CODE_SPAN_TEXT }
.removingIndents(" \t").removingLineSuffixes(" \t")
public override fun buildTextContents(root: PsiElement, allowedDomains: Set<TextContent.TextDomain>): List<TextContent> {
if (InjectedLanguageManager.getInstance(root.project).shouldInspectionsBeLenient(root)) {
@@ -76,7 +78,7 @@ internal class KotlinTextExtractor : TextExtractor() {
return null
}
private val codeFragments = Pattern.compile("(?s)```.+?```|`.+?`")
private val codeFragments = Pattern.compile("(?s)```.+?```|~~~.+?~~~|``")
private val markdownHeading = Pattern.compile("^[ \\t]*#{1,6}[ \\t]+[^\\n]*?(\\n|$)", Pattern.MULTILINE)
private fun TextContent.removeCode(): TextContent? =
@@ -66,6 +66,15 @@ class ForMultiLanguageSupport {
// Das <TYPO descr="Typo: In word 'daert'">daert</TYPO> geschätzt fünf <STYLE_SUGGESTION descr="MANNSTUNDE">Mannstunden</STYLE_SUGGESTION>.
}
/**
* The Markdown lexer folds a nested list item's leading indentation into its `LIST_BULLET`/`LIST_NUMBER` token
* (e.g. `" - "`), so a list / list-item block would otherwise start inside the line's indentation. Trim that
* leading whitespace here so the block starts at its real content; otherwise offset-based consumers such as
* indent auto-detection (`ForMultiLanguageSupport`) undercount the indent of nested list lines.
*/
fun ff() {}
/**
* Returns `an true` if expression is part of when condition expression that looks like
* ```