editor: detekt counts returns, so the promotion guards collapse into one
CI & Build / Build now, or wait for Android? (push) Successful in 3s
CI & Build / Python lint (push) Successful in 5s
CI & Build / TypeScript typecheck (push) Successful in 9s
CI & Build / Python tests (push) Successful in 16s
CI & Build / integration (push) Successful in 21s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 3m0s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 5m0s
Desktop (Tauri) / Update manifest (push) Successful in 4s
Android / Kotlin + Rust (APK) (push) Successful in 8m3s

`promotingTasks` had four returns against ReturnCount's limit of two — three of
them the same `return this`. Collapsed into a null-or-task guard and a
`changed` flag, which says the contract more plainly anyway: the list comes
back untouched unless something was actually promoted.

Mirrored in blocks.ts even though nothing lints it there. The two files are
kept line-by-line alike on purpose, and letting them drift on shape is how the
next person stops trusting that reading one tells you the other.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-27 12:59:15 -04:00
co-authored by Claude Opus 5
parent 1a49ae7ea9
commit f50204a98b
2 changed files with 10 additions and 6 deletions
@@ -167,11 +167,13 @@ fun List<EditorBlock>.plusTask(): Pair<List<EditorBlock>, Long> {
* only the way it is drawn. * only the way it is drawn.
*/ */
internal fun List<EditorBlock>.promotingTasks(index: Int): List<EditorBlock> { internal fun List<EditorBlock>.promotingTasks(index: Int): List<EditorBlock> {
val block = getOrNull(index) ?: return this val block = getOrNull(index)
if (block.isTask) return this if (block == null || block.isTask) return this
val split = splitBlocks(block.value.text, nextId()) val split = splitBlocks(block.value.text, nextId())
if (split.size == 1 && !split.first().isTask) return this // A single prose block back means there was nothing to promote. `splitBlocks` never
return take(index) + split + drop(index + 1) // returns an empty list, so `first()` is safe.
val changed = split.size > 1 || split.first().isTask
return if (changed) take(index) + split + drop(index + 1) else this
} }
/** /**
+4 -2
View File
@@ -137,6 +137,8 @@ export function promoteTasks(blocks: EditorBlock[], index: number): EditorBlock[
const block = blocks[index]; const block = blocks[index];
if (!block || block.checked !== null) return blocks; if (!block || block.checked !== null) return blocks;
const split = splitBlocks(block.text, nextId(blocks)); const split = splitBlocks(block.text, nextId(blocks));
if (split.length === 1 && split[0].checked === null) return blocks; // A single prose block back means there was nothing to promote. `splitBlocks` never
return [...blocks.slice(0, index), ...split, ...blocks.slice(index + 1)]; // returns an empty array, so `split[0]` is safe.
const changed = split.length > 1 || split[0].checked !== null;
return changed ? [...blocks.slice(0, index), ...split, ...blocks.slice(index + 1)] : blocks;
} }