Refactor: reduce detekt findings (unused params, throws, long methods, config)

This commit is contained in:
2026-09-27 21:54:00 +03:00
parent f3e8b2668f
commit b7d96d2ea4
13 changed files with 188 additions and 119 deletions

View File

@@ -33,92 +33,112 @@ class LabImportParser {
}
private fun parseZip(bytes: ByteArray): LabImportBundle {
val entries = readEntries(bytes)
val meta = readMeta(entries)
val readmeMd = readReadme(entries)
val variants = mutableListOf<VariantMeta>()
val assets = mutableMapOf<String, ByteArray>()
for ((path, data) in entries) {
val normalized = path.replace('\\', '/')
when {
isInDir(normalized, "variants") ->
parseVariantFile(normalized, String(data, Charsets.UTF_8), meta.levels)?.let(variants::add)
isInDir(normalized, "assets") -> assets[normalized] = data
}
}
if (variants.isEmpty()) {
throw BadRequestException("В архиве не найдены варианты (папка variants/)")
}
return LabImportBundle(meta, readmeMd, variants, assets)
}
private fun readEntries(bytes: ByteArray): Map<String, ByteArray> {
val entries = mutableMapOf<String, ByteArray>()
ZipInputStream(ByteArrayInputStream(bytes)).use { zis ->
var entry = zis.nextEntry
while (entry != null) {
if (!entry.isDirectory) {
entries[entry.name] = zis.readAllBytes()
}
if (!entry.isDirectory) entries[entry.name] = zis.readAllBytes()
entry = zis.nextEntry
}
}
return entries
}
private fun readMeta(entries: Map<String, ByteArray>): LabMeta {
val metaEntry =
entries.entries.firstOrNull { it.key.endsWith("lab.yaml") || it.key.endsWith("lab.yml") }
?: throw BadRequestException("В архиве не найден lab.yaml")
val meta = yaml.readValue(metaEntry.value, LabMeta::class.java)
val readmeEntry = entries.entries.firstOrNull { it.key.endsWith("/README.md") || it.key == "README.md" }
val readmeMd = readmeEntry?.let { String(it.value, Charsets.UTF_8) } ?: ""
val variants = mutableListOf<VariantMeta>()
val assets = mutableMapOf<String, ByteArray>()
for ((path, data) in entries) {
val p = path.replace('\\', '/')
when {
p.contains("/variants/") || p.startsWith("variants/") -> {
val content = String(data, Charsets.UTF_8)
val variant = parseVariantFile(p, content, meta.levels)
if (variant != null) variants.add(variant)
}
p.contains("/assets/") || p.startsWith("assets/") -> {
assets[p] = data
}
}
}
if (variants.isEmpty()) {
throw BadRequestException("В архиве не найдены варианты (папка variants/)")
}
return LabImportBundle(meta, readmeMd, variants, assets)
return yaml.readValue(metaEntry.value, LabMeta::class.java)
}
private fun readReadme(entries: Map<String, ByteArray>): String =
entries.entries
.firstOrNull { it.key.endsWith("/README.md") || it.key == "README.md" }
?.let { String(it.value, Charsets.UTF_8) }
?: ""
private fun isInDir(
path: String,
dir: String,
): Boolean = path.contains("/$dir/") || path.startsWith("$dir/")
private fun parseVariantFile(
path: String,
content: String,
levels: List<LabLevelMeta>,
): VariantMeta? {
val levelMap = levels.associateBy { it.code }
val lines = content.lines()
val firstSep = lines.indexOfFirst { it.trim() == "---" }
if (firstSep != 0) {
return VariantMeta(
level = "basic",
number = path.substringAfterLast("/").removeSuffix(".md"),
title = "",
statement = content.trim(),
)
}
val secondSep = lines.withIndex().firstOrNull { it.index != firstSep && it.value.trim() == "---" }?.index ?: -1
if (secondSep < 0) return null
val fmLines = lines.subList(1, secondSep)
val fm = mutableMapOf<String, String>()
for (line in fmLines) {
val parts = line.split(":", limit = 2)
if (parts.size == 2) fm[parts[0].trim()] = unquote(parts[1].trim())
}
val levelCode = normalizeLevel(fm["level"] ?: "basic")
if (levelMap[levelCode] == null) return null
val body = lines.drop(secondSep + 1).joinToString("\n").trim()
val frontMatter =
readFrontMatter(lines)
?: return VariantMeta(
level = "basic",
number = path.substringAfterLast("/").removeSuffix(".md"),
title = "",
statement = content.trim(),
)
val levelCode = normalizeLevel(frontMatter.values["level"] ?: "basic")
val number = frontMatter.values["number"]?.takeIf { it.isNotBlank() }
if (levels.none { it.code == levelCode } || number == null) return null
val body = lines.drop(frontMatter.bodyStart).joinToString("\n").trim()
return VariantMeta(
level = levelCode,
number = fm["number"]?.takeIf { it.isNotBlank() } ?: return null,
title = fm["title"] ?: "",
number = number,
title = frontMatter.values["title"] ?: "",
statement = body.ifBlank { "—" },
)
}
private fun unquote(value: String): String =
if (value.length >= 2 &&
((value.first() == '"' && value.last() == '"') || (value.first() == '\'' && value.last() == '\''))
) {
value.substring(1, value.length - 1)
} else {
value
private data class FrontMatter(
val values: Map<String, String>,
val bodyStart: Int,
)
/** Читает YAML-front-matter (между двумя `---`), иначе возвращает null. */
private fun readFrontMatter(lines: List<String>): FrontMatter? {
if (lines.firstOrNull()?.trim() != "---") return null
val end =
lines
.withIndex()
.drop(1)
.firstOrNull { it.value.trim() == "---" }
?.index ?: return null
val values = mutableMapOf<String, String>()
for (line in lines.subList(1, end)) {
val parts = line.split(":", limit = 2)
if (parts.size == 2) values[parts[0].trim()] = unquote(parts[1].trim())
}
return FrontMatter(values, end + 1)
}
private fun unquote(value: String): String = if (isQuoted(value)) value.substring(1, value.length - 1) else value
private fun isQuoted(value: String): Boolean {
if (value.length < 2) return false
val first = value.first()
val last = value.last()
return (first == '"' && last == '"') || (first == '\'' && last == '\'')
}
private fun normalizeLevel(s: String): String =
when (s.lowercase().trim()) {