fix(scripts): stop m3-touch-targets.py reading comments as code
A KDoc line on the dialect picker's row composable, explaining that it used `Card(onClick = …)` rather than a `Modifier.clickable`, was counted as a bare clickable chain. The budget is zero, so a sentence about the rule broke `./gradlew check`. The comment was reworded to get around it, which was the wrong fix -- the sentence was right -- and it is restored here. Not a new rule. m3-spacing-positions.py skips `\s*(//|\*|/\*)` and m3-title-case.py skips the same three prefixes as a startswith tuple; only this checker was missing the two block-comment ones, having been written with `//` alone. m3-audit.sh explains the whole problem at NOT_A_COMMENT, where a note about a hardcoded colour once counted as a colour. The same function had the mirror bug, which is the dangerous direction. It looked for minimumInteractiveComponentSize in a two-line window without stripping comments, so a comment above a real bare `.clickable` that merely mentioned the modifier would have excused it. A false positive is noise; a silently excused offender is a miss. Both lines of the window are now read as code only. Checked against six cases: a bare clickable is still caught, a guard on the same line and a guard on the line above still excuse one, a starred KDoc no longer counts, and a real offender under a comment naming the modifier is now caught. Counts for the tree are unchanged -- 0 before and after -- which was worth establishing, since a broken detector would also report zero. A prefix test rather than block tracking, and the limitation is written on the function: a `/* ... */ `body line not starting with `*` still reads as code. There are 539 block comments under ui/ and not one such line, because every KDoc here stars its body, and three identical rules spelled three ways would be worse than one limitation on the record. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,14 @@ a pointer on desktop has to land on.
|
||||
Components that carry their own minimum -- IconButton, Button, Checkbox, ListItem and the
|
||||
rest of material3 -- are not `.clickable` call sites and never appear here.
|
||||
|
||||
Comments are not code, in either direction. A KDoc line explaining that a row uses a
|
||||
clickable `Card` *rather than* a `Modifier.clickable` was counted as a call site, which
|
||||
breaks a zero budget and so breaks `./gradlew check`; and a comment above a real call site
|
||||
that merely mentions `minimumInteractiveComponentSize` would have excused it. The first is
|
||||
noise and the second is a miss, so both lines of the window are read as code only. This is
|
||||
the same thing m3-audit.sh's `NOT_A_COMMENT` exists for, spelled as m3-title-case.py
|
||||
spells it -- see the note there on a colour comment counting as a colour.
|
||||
|
||||
Usage: m3-touch-targets.py [--list]
|
||||
"""
|
||||
import os, re, sys
|
||||
@@ -21,6 +29,18 @@ import os, re, sys
|
||||
UI = 'composeApp/src/commonMain/kotlin/press/mantra/compose/ui'
|
||||
|
||||
|
||||
def _is_comment(line):
|
||||
"""Whether `line` is a comment line: `//`, or a `/*` block's opener or body.
|
||||
|
||||
A prefix test rather than block tracking, because that is what the other two checkers
|
||||
do and three identical rules spelled three ways is worse than one limitation. The
|
||||
limitation: a `/* ... */` body line that does not start with `*` reads as code. There
|
||||
are 539 block comments under `ui/` and not one such line, since every KDoc here stars
|
||||
its body -- if that ever stops being true, this is the function to make stateful.
|
||||
"""
|
||||
return line.lstrip().startswith(('//', '*', '/*'))
|
||||
|
||||
|
||||
def offenders():
|
||||
found = []
|
||||
for root, _, files in os.walk(UI):
|
||||
@@ -32,11 +52,14 @@ def offenders():
|
||||
for i, line in enumerate(lines):
|
||||
if '.clickable' not in line:
|
||||
continue
|
||||
if line.lstrip().startswith('//') or line.startswith('import '):
|
||||
if _is_comment(line) or line.startswith('import '):
|
||||
continue
|
||||
# The modifier may sit on this line or on the one above, since a chain
|
||||
# broken across lines is the common shape.
|
||||
window = '\n'.join(lines[max(0, i - 1):i + 1])
|
||||
# broken across lines is the common shape. Comment lines are dropped from
|
||||
# the window rather than kept: an exemption has to be in the code.
|
||||
window = '\n'.join(
|
||||
l for l in lines[max(0, i - 1):i + 1] if not _is_comment(l)
|
||||
)
|
||||
if 'minimumInteractiveComponentSize' in window:
|
||||
continue
|
||||
found.append((path, i + 1, line.strip()[:90]))
|
||||
|
||||
Reference in New Issue
Block a user