Repository navigation
Conversation
`desloppify autofix` called fixer.fix() without a path, and the generic fixer treated a missing path as a dry run. Tool-backed fixers (ktlint, rubocop, ...) never ran their fix command, yet printed "Fixed N". - FixerConfig.takes_scan_path: the command passes the scan path to fixers that run an external tool. - Count fixes per file (before vs after re-check) instead of slicing the first N entries. Claim nothing when the re-check fails. - Summary and query count distinct files, not results. - Dry-run preview shows the flagged lines for tool-backed fixers instead of an empty "Sample changes" section. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
github-actions Bot
added a commit
to citizenadam/desloppify
that referenced
this pull request
Oct 30, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
desloppify autofix <tool>-violationnever runs the tool for generic (tool-backed) fixers, yet reports success.cmd_autofixcallsfixer.fix(entries, dry_run=dry_run)without apath.make_generic_fixertreats a missing path the same as a dry run (if dry_run or not path:), so it returns one{file, line}entry per issue without runningfix_cmd. The existing tests always passpath=directly, so they never exercise the CLI call.Seen on a Kotlin project (ktlint, 6390 violations in ~100 files):
Nothing was changed on disk. Related problems in the same path:
len(entries) - len(remaining), andentries[:fixed_count]are reported as "the fixed ones", which is an arbitrary slice. If the re-check fails (the tool errors anddetectreturns[]), every entry counts as fixed.files_fixed,files_would_fix) uselen(results)as a file count. Generic fixers return one result per issue, hence "across 6390 files".--dry-runprints an empty "Sample changes (before → after)" section for generic fixers. The preview only shows entries whosenameis inremoved, and generic results have neither. fix: handle generic fixers that return entries without 'removed' key #484 fixed the crash on this shape but not the empty preview.Fix
FixerConfig.takes_scan_path(defaultFalse).make_generic_fixersets it, andcmd_autofixpassespath=only to fixers that set it, so the TypeScript and Rust fixer signatures are unchanged. A generic fixer called without a path outside dry-run now raises instead of silently doing nothing.{file, fixed_count, summary}. After runningfix_cmd, it re-runs the check throughrun_tool_resultand counts fixes per file (before − after). If the re-check errors, it claims nothing and reportsrecheck_failed. The fix command's exit code is still not treated as failure, because formatters such as ktlint exit non-zero when unfixable violations remain._result_item_count()is shared by the command, the cascade and the preview:len(removed), elsefixed_count, else 1.Tests
tests/lang/common/test_generic_plugin_integrations.pyandtests/commands/test_cmd_autofix.py. 7 of them fail onmain; the eighth (fixers without the flag still get nopath) guards against a regression and passes on both.mainon Windows (review runner and tree-sitter import tests), so none are related.ruff check . --select E9,F63,F7,F82,mypy(configured files) andlint-importsall pass.Not in scope
The ktlint JSON parser is #680 / #778, and #778 also adds a Kotlin-specific fixer. This PR fixes the shared generic path that every other tool-backed language still uses.
🤖 Generated with Claude Code