From ac6147fa43edf23343fc0362612798c5aa162648 Mon Sep 17 00:00:00 2001 From: Julian Valentin Date: Tue, 10 Aug 2021 19:43:11 +0200 Subject: [PATCH] Add support for rule-dependent severities Fixes #95. --- changelog.xml | 3 + .../ltexls/server/CodeActionGenerator.kt | 10 ++- .../org/bsplines/ltexls/settings/Settings.kt | 89 ++++++++++++++++--- .../bsplines/ltexls/settings/SettingsTest.kt | 26 ++++-- 4 files changed, 107 insertions(+), 21 deletions(-) diff --git a/changelog.xml b/changelog.xml index 3c2379bd..7fb54be3 100644 --- a/changelog.xml +++ b/changelog.xml @@ -22,6 +22,9 @@ Add non-server batch mode via `--input-documents` + + Add support for rule-dependent diagnostic severities in [`ltex.diagnosticSeverity`](https://valentjn.github.io/vscode-ltex/docs/settings.html#ltexdiagnosticseverity) + Add support for vowel dummies in LaTeX (`"vowelDummy"` in [`ltex.latex.commands`](https://valentjn.github.io/vscode-ltex/docs/settings.html#ltexlatexcommands)) and Markdown (`"vowelDummy"` in [`ltex.markdown.nodes`](https://valentjn.github.io/vscode-ltex/docs/settings.html#ltexmarkdownnodes)) diff --git a/src/main/kotlin/org/bsplines/ltexls/server/CodeActionGenerator.kt b/src/main/kotlin/org/bsplines/ltexls/server/CodeActionGenerator.kt index f7aaf2cc..40b97f45 100644 --- a/src/main/kotlin/org/bsplines/ltexls/server/CodeActionGenerator.kt +++ b/src/main/kotlin/org/bsplines/ltexls/server/CodeActionGenerator.kt @@ -21,6 +21,7 @@ import org.eclipse.lsp4j.CodeActionKind import org.eclipse.lsp4j.CodeActionParams import org.eclipse.lsp4j.Command import org.eclipse.lsp4j.Diagnostic +import org.eclipse.lsp4j.DiagnosticSeverity import org.eclipse.lsp4j.Range import org.eclipse.lsp4j.ResourceOperation import org.eclipse.lsp4j.TextDocumentEdit @@ -36,7 +37,14 @@ class CodeActionGenerator( val diagnostic = Diagnostic() diagnostic.range = Range(document.convertPosition(match.fromPos), document.convertPosition(match.toPos)) - diagnostic.severity = this.settingsManager.settings.diagnosticSeverity + + val diagnosticSeverityMap: Map = + this.settingsManager.settings.diagnosticSeverity + var diagnosticSeverity: DiagnosticSeverity? = diagnosticSeverityMap[match.ruleId] + if (diagnosticSeverity == null) diagnosticSeverity = diagnosticSeverityMap["default"] + if (diagnosticSeverity == null) diagnosticSeverity = DiagnosticSeverity.Information + diagnostic.severity = diagnosticSeverity + diagnostic.source = "LTeX" diagnostic.message = match.message.replace(SUGGESTION_REGEX, "'$1'") + " \u2013 " + match.ruleId return diagnostic diff --git a/src/main/kotlin/org/bsplines/ltexls/settings/Settings.kt b/src/main/kotlin/org/bsplines/ltexls/settings/Settings.kt index 62e6e116..fed2d1ea 100644 --- a/src/main/kotlin/org/bsplines/ltexls/settings/Settings.kt +++ b/src/main/kotlin/org/bsplines/ltexls/settings/Settings.kt @@ -34,7 +34,7 @@ data class Settings( private val _languageToolHttpServerUri: String? = null, private val _logLevel: Level? = null, private val _sentenceCacheSize: Long? = null, - private val _diagnosticSeverity: DiagnosticSeverity? = null, + private val _diagnosticSeverity: Map? = null, private val _checkFrequency: CheckFrequency? = null, private val _clearDiagnosticsWhenClosingFile: Boolean? = null, ) { @@ -74,8 +74,8 @@ data class Settings( get() = (this._logLevel ?: Level.FINE) val sentenceCacheSize: Long get() = (this._sentenceCacheSize ?: DEFAULT_SENTENCE_CACHE_SIZE) - val diagnosticSeverity: DiagnosticSeverity - get() = (this._diagnosticSeverity ?: DiagnosticSeverity.Information) + val diagnosticSeverity: Map + get() = (this._diagnosticSeverity ?: DEFAULT_DIAGNOSTIC_SEVERITY) val checkFrequency: CheckFrequency get() = (this._checkFrequency ?: CheckFrequency.Edit) val clearDiagnosticsWhenClosingFile: Boolean @@ -174,6 +174,8 @@ data class Settings( val DEFAULT_ENABLED = setOf( "bibtex", "latex", "html", "markdown", "org", "restructuredtext", "rsweave") private const val DEFAULT_SENTENCE_CACHE_SIZE = 2000L + private val DEFAULT_DIAGNOSTIC_SEVERITY: Map = + mapOf(Pair("default", DiagnosticSeverity.Information)) @Suppress("LongMethod") fun fromJson( @@ -229,11 +231,8 @@ data class Settings( ), ) val sentenceCacheSize: Long? = getSettingFromJsonAsLong(jsonSettings, "sentenceCacheSize") - val diagnosticSeverity: DiagnosticSeverity? = getSettingFromJsonAsEnum( - jsonSettings, - "diagnosticSeverity", - DiagnosticSeverity::class.java.enumConstants, - ) + val diagnosticSeverity: Map? = + getDiagnosticSeverityFromJson(jsonSettings) val checkFrequency: CheckFrequency? = getSettingFromJsonAsEnum( jsonSettings, "checkFrequency", @@ -320,18 +319,43 @@ data class Settings( } } + private fun getDiagnosticSeverityFromJson( + jsonSettings: JsonElement, + ): Map? { + val jsonElement: JsonElement? = + getSettingFromJsonAsJsonElement(jsonSettings, "diagnosticSeverity") + + return if (jsonElement == null) { + null + } else if (jsonElement.isJsonObject) { + convertJsonObjectToMapOfEnums( + jsonElement.asJsonObject, + DiagnosticSeverity::class.java.enumConstants, + ) + } else if (jsonElement.isJsonPrimitive) { + val jsonPrimitive: JsonPrimitive = jsonElement.asJsonPrimitive + + if (jsonPrimitive.isString) { + val enumValue: DiagnosticSeverity? = convertStringToEnum( + jsonPrimitive.asString, + DiagnosticSeverity::class.java.enumConstants, + ) + if (enumValue != null) mapOf(Pair("default", enumValue)) else null + } else { + null + } + } else { + null + } + } + private fun getSettingFromJsonAsEnum( jsonSettings: JsonElement, name: String, enumValues: Array, ): T? { val enumString: String = getSettingFromJsonAsString(jsonSettings, name) ?: return null - - for (enumValue: T in enumValues) { - if (enumValue.toString().equals(enumString, ignoreCase = true)) return enumValue - } - - return null + return convertStringToEnum(enumString, enumValues) } private fun getSettingFromJsonAsJsonElement( @@ -506,6 +530,43 @@ data class Settings( return map } + private fun convertJsonObjectToMapOfEnums( + obj: JsonObject?, + enumValues: Array, + ): Map? { + if (obj == null) return null + val map = HashMap() + + for (entry: Map.Entry in obj.entrySet()) { + val enumValue: T? = convertJsonElementToEnum(entry.value, enumValues) + if (enumValue != null) map[entry.key] = enumValue + } + + return map + } + + private fun convertJsonElementToEnum(jsonElement: JsonElement, enumValues: Array): T? { + return if (jsonElement.isJsonPrimitive) { + val jsonPrimitive: JsonPrimitive = jsonElement.asJsonPrimitive + + if (jsonPrimitive.isString) { + convertStringToEnum(jsonPrimitive.asString, enumValues) + } else { + null + } + } else { + null + } + } + + private fun convertStringToEnum(enumString: String, enumValues: Array): T? { + for (enumValue: T in enumValues) { + if (enumValue.toString().equals(enumString, ignoreCase = true)) return enumValue + } + + return null + } + private fun mergeMapOfListsIntoMapOfSets( mapOfLists: Map>?, ): Map>? { diff --git a/src/test/kotlin/org/bsplines/ltexls/settings/SettingsTest.kt b/src/test/kotlin/org/bsplines/ltexls/settings/SettingsTest.kt index 612ef436..d0712c05 100644 --- a/src/test/kotlin/org/bsplines/ltexls/settings/SettingsTest.kt +++ b/src/test/kotlin/org/bsplines/ltexls/settings/SettingsTest.kt @@ -115,8 +115,8 @@ class SettingsTest { assertEquals(1337, settings.sentenceCacheSize) settings2 = compareSettings(settings, settings2, true) - settings = settings.copy(_diagnosticSeverity = DiagnosticSeverity.Error) - assertEquals(DiagnosticSeverity.Error, settings.diagnosticSeverity) + settings = settings.copy(_diagnosticSeverity = mapOf(Pair("ruleId", DiagnosticSeverity.Error))) + assertEquals(mapOf(Pair("ruleId", DiagnosticSeverity.Error)), settings.diagnosticSeverity) settings2 = compareSettings(settings, settings2, false) settings = settings.copy(_checkFrequency = Settings.CheckFrequency.Manual) @@ -270,19 +270,33 @@ class SettingsTest { jsonSettings.addProperty("diagnosticSeverity", "error") settings = Settings.fromJson(jsonSettings, jsonWorkspaceSpecificSettings) - assertEquals(DiagnosticSeverity.Error, settings.diagnosticSeverity) + assertEquals(mapOf(Pair("default", DiagnosticSeverity.Error)), settings.diagnosticSeverity) jsonSettings.addProperty("diagnosticSeverity", "warning") settings = Settings.fromJson(jsonSettings, jsonWorkspaceSpecificSettings) - assertEquals(DiagnosticSeverity.Warning, settings.diagnosticSeverity) + assertEquals(mapOf(Pair("default", DiagnosticSeverity.Warning)), settings.diagnosticSeverity) jsonSettings.addProperty("diagnosticSeverity", "information") settings = Settings.fromJson(jsonSettings, jsonWorkspaceSpecificSettings) - assertEquals(DiagnosticSeverity.Information, settings.diagnosticSeverity) + assertEquals( + mapOf(Pair("default", DiagnosticSeverity.Information)), + settings.diagnosticSeverity, + ) jsonSettings.addProperty("diagnosticSeverity", "hint") settings = Settings.fromJson(jsonSettings, jsonWorkspaceSpecificSettings) - assertEquals(DiagnosticSeverity.Hint, settings.diagnosticSeverity) + assertEquals(mapOf(Pair("default", DiagnosticSeverity.Hint)), settings.diagnosticSeverity) + + val diagnosticSeverity = JsonObject() + diagnosticSeverity.addProperty("ruleId", "warning") + diagnosticSeverity.addProperty("default", "error") + + jsonSettings.add("diagnosticSeverity", diagnosticSeverity) + settings = Settings.fromJson(jsonSettings, jsonWorkspaceSpecificSettings) + assertEquals( + mapOf(Pair("ruleId", DiagnosticSeverity.Warning), Pair("default", DiagnosticSeverity.Error)), + settings.diagnosticSeverity, + ) jsonSettings.addProperty("checkFrequency", "edit") settings = Settings.fromJson(jsonSettings, jsonWorkspaceSpecificSettings)