You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
bug(#334): add three registry suggestions to --fix
Register node => fix builders in src/fixers.js for three declarative rules,
each a suggestion applied only under --fix-suggestions: output-method-xml
(switch method="xml" to "html"), missing-version-in-stylesheet (insert
version="1.0" after the element name), and mode-or-priority-without-match
(delete the orphan attribute when exactly one of mode/priority is present, else
leave the defect fix-less). The per-file linter now skips attaching a fix when
the builder returns null. No new linter or category move — a declarative rule
carries a fix through the registry.
Copy file name to clipboardExpand all lines: CLAUDE.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -137,9 +137,9 @@ Configuration by users: a `.xslint.yml` file (discovered by walking up from the
137
137
138
138
Command-line flags override the file; the file overrides the built-in defaults. Resolution lives in `src/config.js` (which also exposes the config's `base` directory); `src/xslint.js` expands each rule pattern against the check names, folds `off` rules into the suppression list, filters excluded files against `base`, applies severity overrides to the collected defects, and resolves the effective `max-warnings`/`log-level`/`quiet`.
139
139
140
-
Fixing by users: `xslint --fix` rewrites the mechanically-fixable defects in place (`--fix-dry-run` reports the same result without writing any file). A defect is fixable when it carries a `fix: {line, col, value, replacement, suggestion?}` — `xpath-format-linter` attaches one to each `redundant-whitespace` defect, `xpath-axis-linter` to each `unabbreviated-axis` defect, `namespace-linter` to each `redundant-namespace-declarations` defect (its `value` is the reconstructed ` xmlns:prefix="uri"` text, so the verify step skips a single-quoted or oddly spaced declaration rather than deleting the wrong span), and `node-set-linter` to each `use-node-set-extension` defect (a single span from `prefix:node-set(` through its matching `)`, replaced by the inner argument). A *declarative* xpath rule can carry a fix too, without becoming a code-based linter: `src/fixers.js` maps a check name to a `node => fix` builder, and `xpath-linter` attaches the fix that builder returns to each defect it finds for that check — that is how `using-disable-output-escaping` gets its fix. Attribute-deleting fixes (the namespace declaration, the `disable-output-escaping` attribute) share `deletion(attribute)` in `src/fixes.js`. `src/fixer.js` maps each fix's position to a source offset and applies it *only* when the span still holds the exact `value` (a shifted offset — an entity ahead of the run, an already-edited file — is skipped, never corrupting the source), applying a file's fixes from the end backwards so earlier offsets stay valid, and returns the rewritten content per changed file plus the defects it applied. `src/xslint.js` writes the changed files (unless `--fix-dry-run`) and drops the applied defects from the report, so the exit code reflects only what remains.
140
+
Fixing by users: `xslint --fix` rewrites the mechanically-fixable defects in place (`--fix-dry-run` reports the same result without writing any file). A defect is fixable when it carries a `fix: {line, col, value, replacement, suggestion?}` — `xpath-format-linter` attaches one to each `redundant-whitespace` defect, `xpath-axis-linter` to each `unabbreviated-axis` defect, `namespace-linter` to each `redundant-namespace-declarations` defect (its `value` is the reconstructed ` xmlns:prefix="uri"` text, so the verify step skips a single-quoted or oddly spaced declaration rather than deleting the wrong span), and `node-set-linter` to each `use-node-set-extension` defect (a single span from `prefix:node-set(` through its matching `)`, replaced by the inner argument). A *declarative* xpath rule can carry a fix too, without becoming a code-based linter: `src/fixers.js` maps a check name to a `node => fix` builder, and `xpath-linter` attaches the fix that builder returns to each defect it finds for that check (a builder returns null when it cannot resolve the defect with one edit, and the linter then leaves the defect fix-less). The registry drives four suggestions — `using-disable-output-escaping` and `mode-or-priority-without-match` (delete an attribute), `output-method-xml` (`method="xml"`→`"html"`), and `missing-version-in-stylesheet` (insert `version="1.0"` after the element name). Attribute-deleting fixes (the namespace declaration, the `disable-output-escaping` and orphan `mode`/`priority` attributes) share `deletion(attribute)` in `src/fixes.js`. `src/fixer.js` maps each fix's position to a source offset and applies it *only* when the span still holds the exact `value` (a shifted offset — an entity ahead of the run, an already-edited file — is skipped, never corrupting the source), applying a file's fixes from the end backwards so earlier offsets stay valid, and returns the rewritten content per changed file plus the defects it applied. `src/xslint.js` writes the changed files (unless `--fix-dry-run`) and drops the applied defects from the report, so the exit code reflects only what remains.
141
141
142
-
Fixes come in two tiers, set by the `suggestion` flag on the `fix`. A plain fix is *safe* — deterministic and semantics-preserving — and `--fix` applies it. A fix with `suggestion: true` is *opinionated* — it changes behavior, removes code, or is one of several valid corrections — so `--fix` leaves it and only `--fix-suggestions` applies it (`fixer.js` takes a `suggestions` flag and gates on it). `using-disable-output-escaping` is the first suggestion: deleting the attribute changes how output is escaped. When neither flag is passed, `xslint.js` counts the fixable defects and logs how many `--fix` would fix and how many more `--fix-suggestions` would. The fix engine is check-agnostic — the `fix` shape is the whole contract — so a new fixer attaches a `fix` (marking it a suggestion when it should be opt-in) and needs no engine change; the structural fixes (removing an unused variable, merging nested `xsl:if`) wait on the full-fidelity parser (#228) for exact per-node source spans.
142
+
Fixes come in two tiers, set by the `suggestion` flag on the `fix`. A plain fix is *safe* — deterministic and semantics-preserving — and `--fix` applies it. A fix with `suggestion: true` is *opinionated* — it changes behavior, removes code, or is one of several valid corrections — so `--fix` leaves it and only `--fix-suggestions` applies it (`fixer.js` takes a `suggestions` flag and gates on it). Every fix in `src/fixers.js` is a suggestion so far — deleting `disable-output-escaping` changes escaping, switching the output method changes serialization, the declared version is a guess, and dropping `mode`/`priority` is one of two corrections. When neither flag is passed, `xslint.js` counts the fixable defects and logs how many `--fix` would fix and how many more `--fix-suggestions` would. The fix engine is check-agnostic — the `fix` shape is the whole contract — so a new fixer attaches a `fix` (marking it a suggestion when it should be opt-in) and needs no engine change; the structural fixes (removing an unused variable, merging nested `xsl:if`) wait on the full-fidelity parser (#228) for exact per-node source spans.
143
143
144
144
## Keeping Docs in Sync
145
145
@@ -162,7 +162,7 @@ A change that leaves any of these describing the old behavior is not done.
162
162
| `src/xsl-validator.js` | Builds the corpus from raw sources; reports each stylesheet that is not well-formed XML and leaves it out |
163
163
| `src/xpath-validator.js` | Splits each corpus expression into the valid ones (kept for the expression linters) and the malformed ones (reported) |
164
164
| `src/xpath-linter.js` | Loads `checks/xpath/*.yaml`, applies per-file XPath rules, and attaches any `src/fixers.js` fix to the defect |
165
-
| `src/fixers.js` | Maps a declarative check name to a `node => fix` builder, so an xpath rule can carry a fix (e.g. the `using-disable-output-escaping` suggestion) |
165
+
| `src/fixers.js` | Maps a declarative check name to a `node => fix` builder, so an xpath rule can carry a fix — the suggestions for `using-disable-output-escaping`, `output-method-xml`, `missing-version-in-stylesheet`, `mode-or-priority-without-match` |
166
166
| `src/fixes.js` | Shared fix builders — `deletion(attribute)` reconstructs an attribute's ` name="value"` span for removal |
167
167
| `src/corpus-linter.js` | Loads `checks/corpus/*.yaml`, applies cross-file rules over the corpus |
168
168
| `src/xpath-axis-linter.js` | Tokenizes every XPath/pattern attribute in the corpus and flags each verbose axis (`unabbreviated-axis`) with a fix |
0 commit comments