diff --git a/build.gradle.kts b/build.gradle.kts index c35d0e0..65a6a01 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,7 +17,7 @@ pluginBundle { } group = "io.github.1c-syntax" -version = "0.5.2" +version = "0.6.0" repositories { mavenLocal() diff --git a/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/BSLDeveloperToolsPlugin.kt b/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/BSLDeveloperToolsPlugin.kt index 184c5d0..9da874e 100644 --- a/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/BSLDeveloperToolsPlugin.kt +++ b/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/BSLDeveloperToolsPlugin.kt @@ -39,6 +39,13 @@ class BSLDeveloperToolsPlugin : Plugin { it.outputDir.set(project.layout.projectDirectory) } + project.tasks.register("generateDiagnosticDocs", GenerateDiagnosticDocsTask::class.java) { + it.outputDir.set(project.layout.projectDirectory) + } + project.tasks.register("generateDiagnosticsIndex", GenerateDiagnosticsIndexTask::class.java) { + it.outputDir.set(project.layout.projectDirectory) + } + project.tasks.register("precommit") { it.description = "Run all precommit tasks" it.group = "Developer tools" diff --git a/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/GenerateDiagnosticDocsTask.kt b/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/GenerateDiagnosticDocsTask.kt new file mode 100644 index 0000000..a1197ad --- /dev/null +++ b/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/GenerateDiagnosticDocsTask.kt @@ -0,0 +1,348 @@ +/* + * This file is a part of BSLLS Development tools gradle plugin. + * + * Copyright (c) 2020-2022 + * Valery Maximov and contributors + * + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * BSLLS Development tools gradle plugin is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * BSLLS Development tools gradle plugin is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with BSLLS Development tools gradle plugin. + */ +package com.github._1c_syntax.bsllsdevtools + +import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.severityEnMap +import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.severityRuMap +import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.typeEnMap +import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.typeParamRuMap +import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.typeRuMap +import org.gradle.api.DefaultTask +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.model.ObjectFactory +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.options.Option +import java.io.File + +open class GenerateDiagnosticDocsTask @javax.inject.Inject constructor(objects: ObjectFactory) : DefaultTask() { + + init { + group = "build" + description = "Generate diagnostic docs" + dependsOn(":jar") + outputs.upToDateWhen { false } + } + + @Option(option = "build", description = "Generate diagnostic docs in docs folder") + private var build = false + + private val templateDocHeader = "# ()\n\n\n" + + "\n" + private val templateDocFooter = + "## \n\n" + + "\n" + + "### \n\n```bsl\n// BSLLS:-off\n// BSLLS:-on\n```\n\n" + + "### \n\n```json\n\"\": \n```\n" + + @OutputDirectory + val outputDir: DirectoryProperty = objects.directoryProperty() + + fun setBuild(build: Boolean) { + this.build = build + } + + @TaskAction + fun run() { + if (!build) { + Utils.createDocFolder(outputDir, "build/docs/diagnostics", true) + Utils.createDocFolder(outputDir, "build/docs/en/diagnostics", true) + } + + val diagnosticsMetadata = BSLLSSourceReader.getDiagnosticsMetadata(project) + + diagnosticsMetadata.forEach { + generateDocFile("ru", it.key, it.value) + generateDocFile("en", it.key, it.value) + } + } + + private fun generateDocFile(lang: String, key: String, metadata: HashMap) { + val sourcePath = Utils.diagnosticDocPath(outputDir, lang, key) + + var destinationPath = sourcePath + if (!build) { + destinationPath = if (lang == "ru") { + File(outputDir.get().asFile.path, "build/docs/diagnostics/${key}.md") + } else { + File(outputDir.get().asFile.path, "build/docs/en/diagnostics/${key}.md") + } + } + + val text = sourcePath.readText(charset("UTF-8")) + + var header = "## Описание диагностики" + var footer = "## Сниппеты" + + val headerText = templateDocHeader + .replace("", metadata["description_$lang"].toString()) + .replace("", makeDiagnosticMetadata(lang, metadata)) + .replace("", makeDiagnosticParams(lang, metadata)) + .replace("", key) + + var footerText = templateDocFooter + .replace("", key) + .replace("", makeDiagnosticConfigExample(metadata)) + + if (lang == "ru") { + footerText = footerText + .replace("", "Сниппеты") + .replace("", "Экранирование кода") + .replace("", "Параметр конфигурационного файла") + } else { + footerText = footerText + .replace("", "Snippets") + .replace("", "Diagnostic ignorance in code") + .replace("", "Parameter for config") + header = "## Description" + footer = "## Snippets" + } + + var index = text.indexOf(header) + var newText = if (index < 0) { + "$headerText$header\n\n$text" + } else { + "$headerText${text.substring(index)}" + } + + index = newText.indexOf(footer) + newText = if (index < 1) { + "${newText.trimEnd()}\n\n$footerText" + } else { + "${newText.substring(0, index - 1).trimEnd()}\n\n$footerText" + } + + destinationPath.writeText(newText, charset("UTF-8")) + } + + private fun makeDiagnosticMetadata(lang: String, metadata: HashMap): String { + val keys = hashMapOf( + "Type" to "", + "Scope" to "", + "Severity" to "", + "Activated" to "", + "Minutes" to "", + "Tags" to "" + ) + + val keysMaxLen = Utils.createKeysLenMap(keys) + + val headerValues = HashMap(keys) + val tableValues = HashMap(keys) + + if (lang == "ru") { + headerValues["Type"] = "Тип" + headerValues["Scope"] = "Поддерживаются
языки" + headerValues["Severity"] = "Важность" + headerValues["Activated"] = "Включена
по умолчанию" + headerValues["Minutes"] = "Время на
исправление (мин)" + headerValues["Tags"] = "Теги" + + tableValues["Type"] = "`${typeRuMap.getOrDefault(metadata.getOrDefault("type", ""), "")}`" + tableValues["Severity"] = "`${severityRuMap.getOrDefault(metadata.getOrDefault("severity", ""), "")}`" + tableValues["Activated"] = "`${ + if (metadata.getOrDefault("activatedByDefault", "").toString() + .lowercase() != "false" + ) "Да" else "Нет" + }`" + } else { + headerValues["Type"] = "Type" + headerValues["Scope"] = "Scope" + headerValues["Severity"] = "Severity" + headerValues["Activated"] = "Activated
by default" + headerValues["Minutes"] = "Minutes
to fix" + headerValues["Tags"] = "Tags" + + tableValues["Type"] = "`${typeEnMap.getOrDefault(metadata.getOrDefault("type", ""), "")}`" + tableValues["Severity"] = "`${severityEnMap.getOrDefault(metadata.getOrDefault("severity", ""), "")}`" + tableValues["Activated"] = "`${ + if (metadata.getOrDefault("activatedByDefault", "").toString() + .lowercase() != "false" + ) "Yes" else "No" + }`" + } + + tableValues["Scope"] = "`${ + if (metadata.getOrDefault("scope", "") + .toString() == "ALL" + ) "BSL`
`OS" else metadata.getOrDefault("scope", "").toString() + }`" + tableValues["Minutes"] = "`${metadata.getOrDefault("minutesToFix", "")}`" + tableValues["Tags"] = metadata.getOrDefault("tags", "").toString().lowercase() + .replace("[", "`") + .replace("]", "`") + .replace(", ", "`
`") + + // запоминаем максимальные длины строк + конецевые пробелы + Utils.computeMaxLens(keysMaxLen, headerValues) + Utils.computeMaxLens(keysMaxLen, tableValues) + + // получаем строки с учетом длины + val header = computeMetaLineString(keysMaxLen, headerValues) + val line = computeMetaLineString(keysMaxLen, tableValues) + val order = computeMetaOrderString(keysMaxLen) + + return "$header\n$order\n$line\n" + } + + private fun makeDiagnosticParams(lang: String, metadata: HashMap): String { + val params = metadata.getOrDefault("parameters", arrayListOf>()) as ArrayList<*> + if (params.isEmpty()) { + return "" + } + + val paramsBody: String + + val keys = hashMapOf( + "Name" to "", + "Type" to "", + "Description" to "", + "Def" to "" + ) + + val keysMaxLen = Utils.createKeysLenMap(keys) + val headerValues = HashMap(keys) + val tableValues = ArrayList>() + + if (lang == "ru") { + paramsBody = "## Параметры\n\n" + + headerValues["Name"] = "Имя" + headerValues["Type"] = "Тип" + headerValues["Description"] = "Описание" + headerValues["Def"] = "Значение
по умолчанию" + } else { + paramsBody = "## Parameters\n\n" + + headerValues["Name"] = "Name" + headerValues["Type"] = "Type" + headerValues["Description"] = "Description" + headerValues["Def"] = "Default value" + } + + params.forEach { + if (it is HashMap<*, *>) { + + val tableValue = HashMap(keys) + tableValue["Name"] = "`${it.getOrDefault("name", "")}`" + + var typeValue = it.getOrDefault("type", "").toString() + if (lang == "ru") { + typeValue = typeParamRuMap.getOrDefault(typeValue, typeValue) + tableValue["Description"] = "`${it.getOrDefault("description_ru", "")}`" + } else { + tableValue["Description"] = "`${it.getOrDefault("description_en", "")}`" + } + + tableValue["Type"] = "`${typeValue}`" + tableValue["Def"] = "`${it.getOrDefault("defaultValue", "")}`" + + tableValues.add(tableValue) + } + } + + // запоминаем максимальные длины строк + концевые пробелы + Utils.computeMaxLens(keysMaxLen, headerValues) + Utils.computeMaxLens(keysMaxLen, tableValues) + + // получаем строки с учетом длины + val header = computeParamsLineString(keysMaxLen, headerValues) + var lines = "" + tableValues.forEach { + lines += computeParamsLineString(keysMaxLen, it) + "\n" + } + + val order = computeParamsOrderString(keysMaxLen) + + return "$paramsBody\n$header\n$order\n$lines" + } + + private fun makeDiagnosticConfigExample(metadata: HashMap): String { + val params = metadata.getOrDefault("parameters", arrayListOf>()) + if (params is ArrayList<*>) { + + if (params.isEmpty()) { + return "false" + } + + var configBody = "" + var configDelimiter = "" + params.forEach { + if (it is HashMap<*, *>) { + val qoutes = if (it.getOrDefault("type", "") == "Boolean" + || it.getOrDefault("type", "") == "Integer" + || it.getOrDefault("type", "") == "Float" + ) "" else "\"" + configBody += "$configDelimiter \"${it.getOrDefault("name", "")}\": " + + "${qoutes}${ + it.getOrDefault("defaultValue", "") + .toString().replace("\\", "\\\\") + }${qoutes}" + configDelimiter = ",\n" + } + } + configBody = "{\n${configBody}\n}" + return configBody + } + + return "" + } + + private fun computeMetaLineString(maxKeysLen: HashMap, values: HashMap): String { + return "| ${values["Type"]?.let { maxKeysLen["Type"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + + "| ${values["Scope"]?.let { maxKeysLen["Scope"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + + "| ${values["Severity"]?.let { maxKeysLen["Severity"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + + "| ${values["Activated"]?.let { maxKeysLen["Activated"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + + "| ${values["Minutes"]?.let { maxKeysLen["Minutes"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + + "| ${values["Tags"]?.let { maxKeysLen["Tags"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + + "|" + } + + private fun computeMetaOrderString(maxKeysLen: HashMap): String { + val dash = "-" + return "|:${dash.repeat(maxKeysLen["Type"]!!)}:" + + "|:${dash.repeat(maxKeysLen["Scope"]!!)}:" + + "|:${dash.repeat(maxKeysLen["Severity"]!!)}:" + + "|:${dash.repeat(maxKeysLen["Activated"]!!)}:" + + "|:${dash.repeat(maxKeysLen["Minutes"]!!)}:" + + "|:${dash.repeat(maxKeysLen["Tags"]!!)}:" + + "|" + } + + private fun computeParamsLineString(maxKeysLen: HashMap, values: HashMap): String { + return "| ${values["Name"]?.let { maxKeysLen["Name"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + + "| ${values["Type"]?.let { maxKeysLen["Type"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + + "| ${values["Description"]?.let { maxKeysLen["Description"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + + "| ${values["Def"]?.let { maxKeysLen["Def"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + + "|" + } + + private fun computeParamsOrderString(maxKeysLen: HashMap): String { + val dash = "-" + return "|:${dash.repeat(maxKeysLen["Name"]!!)}:" + + "|:${dash.repeat(maxKeysLen["Type"]!!)}:" + + "|:${dash.repeat(maxKeysLen["Description"]!!)}:" + + "|:${dash.repeat(maxKeysLen["Def"]!!)}:" + + "|" + } + +} diff --git a/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/GenerateDiagnosticsIndexTask.kt b/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/GenerateDiagnosticsIndexTask.kt new file mode 100644 index 0000000..9105c01 --- /dev/null +++ b/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/GenerateDiagnosticsIndexTask.kt @@ -0,0 +1,158 @@ +/* + * This file is a part of BSLLS Development tools gradle plugin. + * + * Copyright (c) 2020-2022 + * Valery Maximov and contributors + * + * SPDX-License-Identifier: LGPL-3.0-or-later + * + * BSLLS Development tools gradle plugin is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * BSLLS Development tools gradle plugin is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with BSLLS Development tools gradle plugin. + */ +package com.github._1c_syntax.bsllsdevtools + +import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.severityEnMap +import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.severityRuMap +import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.typeEnMap +import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.typeRuMap +import org.gradle.api.DefaultTask +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.model.ObjectFactory +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.options.Option +import java.io.File + +open class GenerateDiagnosticsIndexTask @javax.inject.Inject constructor(objects: ObjectFactory) : DefaultTask() { + + init { + group = "build" + description = "Generate diagnostics index" + dependsOn(":jar") + outputs.upToDateWhen { false } + } + + @Option(option = "build", description = "Generate diagnostic docs in docs folder") + private var build = false + + private val templateIndexLine = + "\n [](.md) | | | | | " + + @OutputDirectory + val outputDir: DirectoryProperty = objects.directoryProperty() + + fun setBuild(build: Boolean) { + this.build = build + } + + @TaskAction + fun run() { + if (!build) { + Utils.createDocFolder(outputDir, "build/docs/diagnostics", false) + Utils.createDocFolder(outputDir, "build/docs/en/diagnostics", false) + } + + val diagnosticsMetadata = BSLLSSourceReader.getDiagnosticsMetadata(project).toSortedMap() + + generateDiagnosticIndex("ru", diagnosticsMetadata) + generateDiagnosticIndex("en", diagnosticsMetadata) + } + + private fun generateDiagnosticIndex(lang: String, diagnosticsMetadata: Map>) { + var indexText = "" + val typeCount = hashMapOf() + diagnosticsMetadata.forEach { + val metadata = it.value + val typeString: String + val typeKey: String = metadata.getOrDefault("type", "") as String + val tags = metadata.getOrDefault("tags", "").toString().lowercase() + .replace("[", "`") + .replace("]", "`") + .replace(", ", "`
`") + if (lang == "ru") { + typeString = typeRuMap.getOrDefault(typeKey, "") + indexText += templateIndexLine + .replace("", it.key) + .replace("", metadata["description_ru"].toString()) + .replace( + "", + if (metadata.getOrDefault("activatedByDefault", "").toString() + .lowercase() != "false" + ) "Да" else "Нет" + ) + .replace( + "", severityRuMap + .getOrDefault(metadata.getOrDefault("severity", "") as String, "") + ) + .replace("", typeString) + .replace("", tags) + } else { + typeString = typeEnMap.getOrDefault(typeKey, "") + indexText += templateIndexLine + .replace("", it.key) + .replace("", metadata["description_en"].toString()) + .replace( + "", + if (metadata.getOrDefault("activatedByDefault", "").toString() + .lowercase() != "false" + ) "Yes" else "No" + ) + .replace( + "", severityEnMap + .getOrDefault(metadata.getOrDefault("severity", "") as String, "") + ) + .replace("", typeString) + .replace("", tags) + } + + typeCount[typeKey] = typeCount.getOrDefault(typeKey, 0) + 1 + } + + val sourcePath = Utils.diagnosticIndexPath(outputDir, lang) + var destinationPath = sourcePath + if (!build) { + destinationPath = if (lang == "ru") { + File(outputDir.get().asFile.path, "build/docs/index.md") + } else { + File(outputDir.get().asFile.path, "build/docs/en/index.md") + } + } + + val text = sourcePath.readText(charset("UTF-8")) + + var header = "## Список реализованных диагностик" + var total = "Общее количество:" + var table = "| Ключ | Название | Включена по умолчанию | Важность | Тип | Теги |" + if (lang == "en") { + header = "## Implemented diagnostics" + total = "Total:" + table = "| Key | Name| Enabled by default | Severity | Type | Tags |" + } + table += "\n| --- | --- | :-: | --- | --- | --- |" + + total += " **${diagnosticsMetadata.size}**\n\n* ${ + typeCount.map { + if (lang == "ru") { + typeRuMap.getOrDefault(it.key, "") + } else { + typeEnMap.getOrDefault(it.key, "") + } + ": **${it.value}**" + }.joinToString("\n* ") + }\n" + val indexHeader = text.indexOf(header) + destinationPath.writeText( + "${text.substring(0, indexHeader - 1).trimEnd()}\n\n${header}\n\n${total}\n\n${table}${indexText}", + charset("UTF-8") + ) + } +} diff --git a/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/UpdateDiagnosticDocsTask.kt b/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/UpdateDiagnosticDocsTask.kt index 9ed4d20..0312fb2 100644 --- a/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/UpdateDiagnosticDocsTask.kt +++ b/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/UpdateDiagnosticDocsTask.kt @@ -21,17 +21,11 @@ */ package com.github._1c_syntax.bsllsdevtools -import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.severityEnMap -import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.severityRuMap -import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.typeEnMap -import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.typeParamRuMap -import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.typeRuMap import org.gradle.api.DefaultTask import org.gradle.api.file.DirectoryProperty import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction -import java.io.File open class UpdateDiagnosticDocsTask @javax.inject.Inject constructor(objects: ObjectFactory) : DefaultTask() { @@ -42,13 +36,8 @@ open class UpdateDiagnosticDocsTask @javax.inject.Inject constructor(objects: Ob outputs.upToDateWhen { false } } - private val templateDocHeader = "# ()\n\n\n" + + private val templateDocHeader = "# ()\n\n" + "\n" - private val templateDocFooter = - "## \n\n" + - "\n" + - "### \n\n```bsl\n// BSLLS:-off\n// BSLLS:-on\n```\n\n" + - "### \n\n```json\n\"\": \n```\n" @OutputDirectory val outputDir: DirectoryProperty = objects.directoryProperty() @@ -63,12 +52,7 @@ open class UpdateDiagnosticDocsTask @javax.inject.Inject constructor(objects: Ob } private fun updateDocFile(lang: String, key: String, metadata: HashMap) { - val docPath = if (lang == "ru") { - File(outputDir.get().asFile.path, "docs/diagnostics/${key}.md") - } else { - File(outputDir.get().asFile.path, "docs/en/diagnostics/${key}.md") - } - + val docPath = Utils.diagnosticDocPath(outputDir, lang, key) val text = docPath.readText(charset("UTF-8")) var header = "## Описание диагностики" @@ -76,24 +60,9 @@ open class UpdateDiagnosticDocsTask @javax.inject.Inject constructor(objects: Ob val headerText = templateDocHeader .replace("", metadata["description_$lang"].toString()) - .replace("", makeDiagnosticMetadata(lang, metadata)) - .replace("", makeDiagnosticParams(lang, metadata)) .replace("", key) - var footerText = templateDocFooter - .replace("", key) - .replace("", makeDiagnosticConfigExample(metadata)) - - if (lang == "ru") { - footerText = footerText - .replace("", "Сниппеты") - .replace("", "Экранирование кода") - .replace("", "Параметр конфигурационного файла") - } else { - footerText = footerText - .replace("", "Snippets") - .replace("", "Diagnostic ignorance in code") - .replace("", "Parameter for config") + if (lang == "en") { header = "## Description" footer = "## Snippets" } @@ -107,223 +76,11 @@ open class UpdateDiagnosticDocsTask @javax.inject.Inject constructor(objects: Ob index = newText.indexOf(footer) newText = if (index < 1) { - "${newText.trimEnd()}\n\n$footerText" + "${newText.trimEnd()}\n" } else { - "${newText.substring(0, index - 1).trimEnd()}\n\n$footerText" + "${newText.substring(0, index - 1).trimEnd()}\n" } docPath.writeText(newText, charset("UTF-8")) } - - private fun makeDiagnosticMetadata(lang: String, metadata: HashMap): String { - val keys = hashMapOf( - "Type" to "", - "Scope" to "", - "Severity" to "", - "Activated" to "", - "Minutes" to "", - "Tags" to "" - ) - - val keysMaxLen = Utils.createKeysLenMap(keys) - - val headerValues = HashMap(keys) - val tableValues = HashMap(keys) - - if (lang == "ru") { - headerValues["Type"] = "Тип" - headerValues["Scope"] = "Поддерживаются
языки" - headerValues["Severity"] = "Важность" - headerValues["Activated"] = "Включена
по умолчанию" - headerValues["Minutes"] = "Время на
исправление (мин)" - headerValues["Tags"] = "Теги" - - tableValues["Type"] = "`${typeRuMap.getOrDefault(metadata.getOrDefault("type", ""), "")}`" - tableValues["Severity"] = "`${severityRuMap.getOrDefault(metadata.getOrDefault("severity", ""), "")}`" - tableValues["Activated"] = "`${ - if (metadata.getOrDefault("activatedByDefault", "").toString() - .lowercase() != "false" - ) "Да" else "Нет" - }`" - } else { - headerValues["Type"] = "Type" - headerValues["Scope"] = "Scope" - headerValues["Severity"] = "Severity" - headerValues["Activated"] = "Activated
by default" - headerValues["Minutes"] = "Minutes
to fix" - headerValues["Tags"] = "Tags" - - tableValues["Type"] = "`${typeEnMap.getOrDefault(metadata.getOrDefault("type", ""), "")}`" - tableValues["Severity"] = "`${severityEnMap.getOrDefault(metadata.getOrDefault("severity", ""), "")}`" - tableValues["Activated"] = "`${ - if (metadata.getOrDefault("activatedByDefault", "").toString() - .lowercase() != "false" - ) "Yes" else "No" - }`" - } - - tableValues["Scope"] = "`${ - if (metadata.getOrDefault("scope", "") - .toString() == "ALL" - ) "BSL`
`OS" else metadata.getOrDefault("scope", "").toString() - }`" - tableValues["Minutes"] = "`${metadata.getOrDefault("minutesToFix", "")}`" - tableValues["Tags"] = metadata.getOrDefault("tags", "").toString().lowercase() - .replace("[", "`") - .replace("]", "`") - .replace(", ", "`
`") - - // запоминаем максимальные длины строк + конецевые пробелы - Utils.computeMaxLens(keysMaxLen, headerValues) - Utils.computeMaxLens(keysMaxLen, tableValues) - - // получаем строки с учетом длины - val header = computeMetaLineString(keysMaxLen, headerValues) - val line = computeMetaLineString(keysMaxLen, tableValues) - val order = computeMetaOrderString(keysMaxLen) - - return "$header\n$order\n$line\n" - } - - private fun makeDiagnosticParams(lang: String, metadata: HashMap): String { - val params = metadata.getOrDefault("parameters", arrayListOf>()) as ArrayList<*> - if (params.isEmpty()) { - return "" - } - - val paramsBody: String - - val keys = hashMapOf( - "Name" to "", - "Type" to "", - "Description" to "", - "Def" to "" - ) - - val keysMaxLen = Utils.createKeysLenMap(keys) - val headerValues = HashMap(keys) - val tableValues = ArrayList>() - - if (lang == "ru") { - paramsBody = "## Параметры\n\n" - - headerValues["Name"] = "Имя" - headerValues["Type"] = "Тип" - headerValues["Description"] = "Описание" - headerValues["Def"] = "Значение
по умолчанию" - } else { - paramsBody = "## Parameters\n\n" - - headerValues["Name"] = "Name" - headerValues["Type"] = "Type" - headerValues["Description"] = "Description" - headerValues["Def"] = "Default value" - } - - params.forEach { - if (it is HashMap<*, *>) { - - val tableValue = HashMap(keys) - tableValue["Name"] = "`${it.getOrDefault("name", "")}`" - - var typeValue = it.getOrDefault("type", "").toString() - if (lang == "ru") { - typeValue = typeParamRuMap.getOrDefault(typeValue, typeValue) - tableValue["Description"] = "`${it.getOrDefault("description_ru", "")}`" - } else { - tableValue["Description"] = "`${it.getOrDefault("description_en", "")}`" - } - - tableValue["Type"] = "`${typeValue}`" - tableValue["Def"] = "`${it.getOrDefault("defaultValue", "")}`" - - tableValues.add(tableValue) - } - } - - // запоминаем максимальные длины строк + концевые пробелы - Utils.computeMaxLens(keysMaxLen, headerValues) - Utils.computeMaxLens(keysMaxLen, tableValues) - - // получаем строки с учетом длины - val header = computeParamsLineString(keysMaxLen, headerValues) - var lines = "" - tableValues.forEach { - lines += computeParamsLineString(keysMaxLen, it) + "\n" - } - - val order = computeParamsOrderString(keysMaxLen) - - return "$paramsBody\n$header\n$order\n$lines" - } - - private fun makeDiagnosticConfigExample(metadata: HashMap): String { - val params = metadata.getOrDefault("parameters", arrayListOf>()) - if (params is ArrayList<*>) { - - if (params.isEmpty()) { - return "false" - } - - var configBody = "" - var configDelimiter = "" - params.forEach { - if (it is HashMap<*, *>) { - val qoutes = if (it.getOrDefault("type", "") == "Boolean" - || it.getOrDefault("type", "") == "Integer" - || it.getOrDefault("type", "") == "Float" - ) "" else "\"" - configBody += "$configDelimiter \"${it.getOrDefault("name", "")}\": " + - "${qoutes}${ - it.getOrDefault("defaultValue", "") - .toString().replace("\\", "\\\\") - }${qoutes}" - configDelimiter = ",\n" - } - } - configBody = "{\n${configBody}\n}" - return configBody - } - - return "" - } - - private fun computeMetaLineString(maxKeysLen: HashMap, values: HashMap): String { - return "| ${values["Type"]?.let { maxKeysLen["Type"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + - "| ${values["Scope"]?.let { maxKeysLen["Scope"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + - "| ${values["Severity"]?.let { maxKeysLen["Severity"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + - "| ${values["Activated"]?.let { maxKeysLen["Activated"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + - "| ${values["Minutes"]?.let { maxKeysLen["Minutes"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + - "| ${values["Tags"]?.let { maxKeysLen["Tags"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + - "|" - } - - private fun computeMetaOrderString(maxKeysLen: HashMap): String { - val dash = "-" - return "|:${dash.repeat(maxKeysLen["Type"]!!)}:" + - "|:${dash.repeat(maxKeysLen["Scope"]!!)}:" + - "|:${dash.repeat(maxKeysLen["Severity"]!!)}:" + - "|:${dash.repeat(maxKeysLen["Activated"]!!)}:" + - "|:${dash.repeat(maxKeysLen["Minutes"]!!)}:" + - "|:${dash.repeat(maxKeysLen["Tags"]!!)}:" + - "|" - } - - private fun computeParamsLineString(maxKeysLen: HashMap, values: HashMap): String { - return "| ${values["Name"]?.let { maxKeysLen["Name"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + - "| ${values["Type"]?.let { maxKeysLen["Type"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + - "| ${values["Description"]?.let { maxKeysLen["Description"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + - "| ${values["Def"]?.let { maxKeysLen["Def"]?.let { len -> Utils.wrapSpaces(it, len) } }} " + - "|" - } - - private fun computeParamsOrderString(maxKeysLen: HashMap): String { - val dash = "-" - return "|:${dash.repeat(maxKeysLen["Name"]!!)}:" + - "|:${dash.repeat(maxKeysLen["Type"]!!)}:" + - "|:${dash.repeat(maxKeysLen["Description"]!!)}:" + - "|:${dash.repeat(maxKeysLen["Def"]!!)}:" + - "|" - } - } diff --git a/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/UpdateDiagnosticsIndexTask.kt b/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/UpdateDiagnosticsIndexTask.kt index 3e5cc8d..a0f052b 100644 --- a/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/UpdateDiagnosticsIndexTask.kt +++ b/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/UpdateDiagnosticsIndexTask.kt @@ -21,16 +21,11 @@ */ package com.github._1c_syntax.bsllsdevtools -import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.severityEnMap -import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.severityRuMap -import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.typeEnMap -import com.github._1c_syntax.bsllsdevtools.BSLLSSourceReader.Companion.typeRuMap import org.gradle.api.DefaultTask import org.gradle.api.file.DirectoryProperty import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.OutputDirectory import org.gradle.api.tasks.TaskAction -import java.io.File open class UpdateDiagnosticsIndexTask @javax.inject.Inject constructor(objects: ObjectFactory) : DefaultTask() { @@ -41,99 +36,27 @@ open class UpdateDiagnosticsIndexTask @javax.inject.Inject constructor(objects: outputs.upToDateWhen { false } } - private val templateIndexLine = - "\n [](.md) | | | | | " - @OutputDirectory val outputDir: DirectoryProperty = objects.directoryProperty() @TaskAction fun run() { - val diagnosticsMetadata = BSLLSSourceReader.getDiagnosticsMetadata(project).toSortedMap() - updateDiagnosticIndex("ru", diagnosticsMetadata) - updateDiagnosticIndex("en", diagnosticsMetadata) + updateDiagnosticIndex("ru") + updateDiagnosticIndex("en") } - private fun updateDiagnosticIndex(lang: String, diagnosticsMetadata: Map>) { - var indexText = "" - val typeCount = hashMapOf() - diagnosticsMetadata.forEach { - val metadata = it.value - val typeString: String - val typeKey: String = metadata.getOrDefault("type", "") as String - val tags = metadata.getOrDefault("tags", "").toString().lowercase() - .replace("[", "`") - .replace("]", "`") - .replace(", ", "`
`") - if (lang == "ru") { - typeString = typeRuMap.getOrDefault(typeKey, "") - indexText += templateIndexLine - .replace("", it.key) - .replace("", metadata["description_ru"].toString()) - .replace( - "", - if (metadata.getOrDefault("activatedByDefault", "").toString() - .lowercase() != "false" - ) "Да" else "Нет" - ) - .replace( - "", severityRuMap - .getOrDefault(metadata.getOrDefault("severity", "") as String, "") - ) - .replace("", typeString) - .replace("", tags) - } else { - typeString = typeEnMap.getOrDefault(typeKey, "") - indexText += templateIndexLine - .replace("", it.key) - .replace("", metadata["description_en"].toString()) - .replace( - "", - if (metadata.getOrDefault("activatedByDefault", "").toString() - .lowercase() != "false" - ) "Yes" else "No" - ) - .replace( - "", severityEnMap - .getOrDefault(metadata.getOrDefault("severity", "") as String, "") - ) - .replace("", typeString) - .replace("", tags) - } - - typeCount[typeKey] = typeCount.getOrDefault(typeKey, 0) + 1 - } - - val indexPath = if (lang == "ru") { - File(outputDir.get().asFile.path, "docs/diagnostics/index.md") - } else { - File(outputDir.get().asFile.path, "docs/en/diagnostics/index.md") - } - + private fun updateDiagnosticIndex(lang: String) { + val indexPath = Utils.diagnosticIndexPath(outputDir, lang) val text = indexPath.readText(charset("UTF-8")) var header = "## Список реализованных диагностик" - var total = "Общее количество:" - var table = "| Ключ | Название | Включена по умолчанию | Важность | Тип | Тэги |" if (lang == "en") { header = "## Implemented diagnostics" - total = "Total:" - table = "| Key | Name| Enabled by default | Severity | Type | Tags |" } - table += "\n| --- | --- | :-: | --- | --- | --- |" - total += " **${diagnosticsMetadata.size}**\n\n* ${ - typeCount.map { - if (lang == "ru") { - typeRuMap.getOrDefault(it.key, "") - } else { - typeEnMap.getOrDefault(it.key, "") - } + ": **${it.value}**" - }.joinToString("\n* ") - }\n" val indexHeader = text.indexOf(header) indexPath.writeText( - text.substring(0, indexHeader - 1) + "\n${header}\n\n${total}\n\n${table}${indexText}", + "${text.substring(0, indexHeader - 1).trimEnd()}\n${header}\n", charset("UTF-8") ) } diff --git a/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/Utils.kt b/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/Utils.kt index 94c34e7..256f1fe 100644 --- a/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/Utils.kt +++ b/src/main/kotlin/com/github/_1c_syntax/bsllsdevtools/Utils.kt @@ -21,6 +21,9 @@ */ package com.github._1c_syntax.bsllsdevtools +import org.gradle.api.file.DirectoryProperty +import java.io.File + object Utils { @JvmStatic fun wrapSpaces(string: String, len: Int): String { @@ -56,4 +59,31 @@ object Utils { return keysLenMap } + + @JvmStatic + fun diagnosticDocPath(outputDir: DirectoryProperty, lang: String, key: String): File { + return if (lang == "ru") { + File(outputDir.get().asFile.path, "docs/diagnostics/${key}.md") + } else { + File(outputDir.get().asFile.path, "docs/en/diagnostics/${key}.md") + } + } + + @JvmStatic + fun diagnosticIndexPath(outputDir: DirectoryProperty, lang: String): File { + return if (lang == "ru") { + File(outputDir.get().asFile.path, "docs/diagnostics/index.md") + } else { + File(outputDir.get().asFile.path, "docs/en/diagnostics/index.md") + } + } + + @JvmStatic + fun createDocFolder(outputDir: DirectoryProperty, folder: String, clean: Boolean) { + val dir = File(outputDir.get().asFile.path, folder) + if (dir.exists() && clean) { + dir.deleteRecursively() + } + dir.mkdirs() + } } diff --git a/src/main/resources/Template_en.md b/src/main/resources/Template_en.md index e226f26..883df51 100644 --- a/src/main/resources/Template_en.md +++ b/src/main/resources/Template_en.md @@ -1,9 +1,5 @@ # () - - -## - ## Description @@ -18,19 +14,3 @@ * Источник: [Стандарт: Тексты модулей](https://its.1c.ru/db/v8std#content:456:hdoc) * Полезная информация: [Отказ от использования модальных окон](https://its.1c.ru/db/metod8dev#content:5272:hdoc) * Источник: [Cognitive complexity, ver. 1.4](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) --> - -## Snippets - - -### Diagnostic ignorance in code - -```bsl -// BSLLS:-off -// BSLLS:-on -``` - -### Parameter for config - -```json -"": -``` diff --git a/src/main/resources/Template_ru.md b/src/main/resources/Template_ru.md index 525de0e..b9acec9 100644 --- a/src/main/resources/Template_ru.md +++ b/src/main/resources/Template_ru.md @@ -1,9 +1,5 @@ # () - - -## - ## Описание диагностики @@ -18,19 +14,3 @@ * Источник: [Стандарт: Тексты модулей](https://its.1c.ru/db/v8std#content:456:hdoc) * Полезная информация: [Отказ от использования модальных окон](https://its.1c.ru/db/metod8dev#content:5272:hdoc) * Источник: [Cognitive complexity, ver. 1.4](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) --> - -## Сниппеты - - -### Экранирование кода - -```bsl -// BSLLS:-off -// BSLLS:-on -``` - -### Параметр конфигурационного файла - -```json -"": -``` \ No newline at end of file