diff --git a/changelog.xml b/changelog.xml
index d15076a..5eec44e 100644
--- a/changelog.xml
+++ b/changelog.xml
@@ -16,6 +16,9 @@
Add support for strikethrough as in [GitHub Flavored Markdown](https://github.github.com/gfm/#strikethrough-extension-)
+
+ Always check selected text when running [`_ltex.checkDocument`](https://valentjn.github.io/ltex/ltex-ls/server-usage.html#_ltexcheckdocument-server), even non-comment parts of programs
+
diff --git a/src/main/kotlin/org/bsplines/ltexls/server/DocumentChecker.kt b/src/main/kotlin/org/bsplines/ltexls/server/DocumentChecker.kt
index 31b26c0..732cc68 100644
--- a/src/main/kotlin/org/bsplines/ltexls/server/DocumentChecker.kt
+++ b/src/main/kotlin/org/bsplines/ltexls/server/DocumentChecker.kt
@@ -14,6 +14,8 @@ import org.bsplines.ltexls.parsing.AnnotatedTextFragment
import org.bsplines.ltexls.parsing.CodeAnnotatedTextBuilder
import org.bsplines.ltexls.parsing.CodeFragment
import org.bsplines.ltexls.parsing.CodeFragmentizer
+import org.bsplines.ltexls.parsing.plaintext.PlaintextAnnotatedTextBuilder
+import org.bsplines.ltexls.parsing.program.ProgramCommentRegexs
import org.bsplines.ltexls.settings.HiddenFalsePositive
import org.bsplines.ltexls.settings.Settings
import org.bsplines.ltexls.settings.SettingsManager
@@ -39,7 +41,7 @@ class DocumentChecker(
private fun fragmentizeDocument(
document: LtexTextDocumentItem,
- range: Range?,
+ range: Range? = null,
): List {
val codeFragmentizer: CodeFragmentizer = CodeFragmentizer.create(document.languageId)
var code: String = document.text
@@ -57,12 +59,19 @@ class DocumentChecker(
private fun buildAnnotatedTextFragments(
codeFragments: List,
document: LtexTextDocumentItem,
+ hasRange: Boolean = false,
): List {
val annotatedTextFragments = ArrayList()
for (codeFragment: CodeFragment in codeFragments) {
- val builder: CodeAnnotatedTextBuilder =
- CodeAnnotatedTextBuilder.create(codeFragment.codeLanguageId)
+ val builder: CodeAnnotatedTextBuilder = if (
+ hasRange && ProgramCommentRegexs.isSupportedCodeLanguageId(codeFragment.codeLanguageId)
+ ) {
+ PlaintextAnnotatedTextBuilder(codeFragment.codeLanguageId)
+ } else {
+ CodeAnnotatedTextBuilder.create(codeFragment.codeLanguageId)
+ }
+
builder.setSettings(codeFragment.settings)
builder.addCode(codeFragment.code)
val curAnnotatedText: AnnotatedText = builder.build()
@@ -74,12 +83,12 @@ class DocumentChecker(
private fun checkAnnotatedTextFragments(
annotatedTextFragments: List,
- rangeOffset: Int,
+ rangeStartPos: Int? = null,
): List {
val matches = ArrayList()
for (annotatedTextFragment: AnnotatedTextFragment in annotatedTextFragments) {
- matches.addAll(checkAnnotatedTextFragment(annotatedTextFragment, rangeOffset))
+ matches.addAll(checkAnnotatedTextFragment(annotatedTextFragment, rangeStartPos))
}
return matches
@@ -88,7 +97,7 @@ class DocumentChecker(
@Suppress("TooGenericExceptionCaught")
private fun checkAnnotatedTextFragment(
annotatedTextFragment: AnnotatedTextFragment,
- rangeOffset: Int,
+ rangeStartPos: Int? = null,
): List {
val codeFragment: CodeFragment = annotatedTextFragment.codeFragment
var settings: Settings = codeFragment.settings
@@ -115,8 +124,7 @@ class DocumentChecker(
val codeLanguageId: String = codeFragment.codeLanguageId
- if (!settings.enabled.contains(codeLanguageId)
- && (codeLanguageId != "nop") && (codeLanguageId != "plaintext")) {
+ if (shouldSkipCheck(codeLanguageId, settings, rangeStartPos)) {
Logging.logger.fine(I18n.format("skippingTextCheckAsLtexHasBeenDisabled", codeLanguageId))
return emptyList()
} else if (settings.dictionary.contains("BsPlInEs")) {
@@ -157,8 +165,10 @@ class DocumentChecker(
for (match: LanguageToolRuleMatch in matches) {
result.add(
match.copy(
- fromPos = match.fromPos + annotatedTextFragment.codeFragment.fromPos + rangeOffset,
- toPos = match.toPos + annotatedTextFragment.codeFragment.fromPos + rangeOffset,
+ fromPos =
+ match.fromPos + annotatedTextFragment.codeFragment.fromPos + (rangeStartPos ?: 0),
+ toPos =
+ match.toPos + annotatedTextFragment.codeFragment.fromPos + (rangeStartPos ?: 0),
),
)
}
@@ -259,14 +269,14 @@ class DocumentChecker(
): Pair, List> {
this.lastCheckedDocument = document
val originalSettings: Settings = this.settingsManager.settings
- val rangeOffset: Int = (if (range == null) 0 else document.convertPosition(range.start))
+ val rangeStartPos: Int? = if (range != null) document.convertPosition(range.start) else null
try {
val codeFragments: List = fragmentizeDocument(document, range)
val annotatedTextFragments: List =
- buildAnnotatedTextFragments(codeFragments, document)
+ buildAnnotatedTextFragments(codeFragments, document, (range != null))
val matches: List =
- checkAnnotatedTextFragments(annotatedTextFragments, rangeOffset)
+ checkAnnotatedTextFragments(annotatedTextFragments, rangeStartPos)
return Pair(matches, annotatedTextFragments)
} finally {
this.settingsManager.settings = originalSettings
@@ -275,5 +285,18 @@ class DocumentChecker(
companion object {
private const val MAX_LOG_TEXT_LENGTH = 100
+
+ private fun shouldSkipCheck(
+ codeLanguageId: String,
+ settings: Settings,
+ rangeStartPos: Int?,
+ ): Boolean {
+ return (
+ (rangeStartPos == null)
+ && !settings.enabled.contains(codeLanguageId)
+ && (codeLanguageId != "nop")
+ && (codeLanguageId != "plaintext")
+ )
+ }
}
}
diff --git a/src/test/kotlin/org/bsplines/ltexls/server/DocumentCheckerTest.kt b/src/test/kotlin/org/bsplines/ltexls/server/DocumentCheckerTest.kt
index a9392fa..b3ba47c 100644
--- a/src/test/kotlin/org/bsplines/ltexls/server/DocumentCheckerTest.kt
+++ b/src/test/kotlin/org/bsplines/ltexls/server/DocumentCheckerTest.kt
@@ -144,20 +144,40 @@ class DocumentCheckerTest {
@Test
fun testRange() {
- val document: LtexTextDocumentItem = createDocument(
+ var document: LtexTextDocumentItem = createDocument(
"markdown",
"# Test\n\nThis is an **test.**\n\nThis is an **test.**\n",
)
val settingsManager = SettingsManager(Settings(_logLevel = Level.FINEST))
val documentChecker = DocumentChecker(settingsManager)
- val checkingResult: Pair, List> =
+ var checkingResult: Pair, List> =
documentChecker.check(document, Range(Position(4, 0), Position(4, 20)))
- val matches: List = checkingResult.first
+ var matches: List = checkingResult.first
assertEquals(1, matches.size)
assertEquals("EN_A_VS_AN", matches[0].ruleId)
assertEquals("This is an test.", matches[0].sentence?.trim())
assertEquals(38, matches[0].fromPos)
assertEquals(40, matches[0].toPos)
+
+ document = createDocument(
+ "cpp",
+ """
+ #include
+
+ int main() {
+ std::cout << "This is an test." << std::endl;
+ return 0;
+ }
+
+ """.trimIndent(),
+ )
+ checkingResult = documentChecker.check(document, Range(Position(3, 16), Position(3, 32)))
+ matches = checkingResult.first
+ assertEquals(1, matches.size)
+ assertEquals("EN_A_VS_AN", matches[0].ruleId)
+ assertEquals("This is an test.", matches[0].sentence?.trim())
+ assertEquals(58, matches[0].fromPos)
+ assertEquals(60, matches[0].toPos)
}
@Test