Skip to content

Commit 3e46a89

Browse files
committed
add single_line_body opt-in format rule; bridge global format config to rules via FormatAwareRule protocol (#188)
1 parent 16beed8 commit 3e46a89

38 files changed

Lines changed: 1078 additions & 34 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
# 8ak-rh2
3+
title: Standardize rule names for consistency
4+
status: in-progress
5+
type: task
6+
priority: normal
7+
created_at: 2026-04-11T19:12:38Z
8+
updated_at: 2026-04-11T19:12:38Z
9+
sync:
10+
github:
11+
issue_number: "189"
12+
synced_at: "2026-04-11T19:12:48Z"
13+
---
14+
15+
Rename ~25 rules for naming consistency across three merged rule sources.
16+
17+
## Changes
18+
19+
### 1. Synonym Standardization (redundant/unneeded/unnecessary/superfluous → redundant)
20+
- [ ] UnneededOverrideRule → RedundantOverrideRule
21+
- [ ] UnneededEscapingRule → RedundantEscapingRule
22+
- [ ] UnneededSynthesizedInitializerRule → RedundantSynthesizedInitializerRule
23+
- [ ] UnneededBreakInSwitchRule → RedundantBreakInSwitchRule
24+
- [ ] UnneededThrowsRule → RedundantThrowsRule (id: redundant_throws)
25+
- [ ] UnneededParenthesesInClosureArgumentRule → RedundantClosureArgumentParensRule
26+
- [ ] UnnecessaryFileprivateRule → RedundantFileprivateRule
27+
- [ ] SuperfluousElseRule → RedundantElseRule
28+
- [ ] SuperfluousDisableCommandRule → RedundantDisableCommandRule
29+
30+
### 2. Verb Tense
31+
- [ ] SortedEnumCasesRule → SortEnumCasesRule
32+
- [ ] SortedFirstLastRule → MinMaxOverSortedRule
33+
34+
### 3. Gerund vs Noun
35+
- [ ] ForceUnwrappingRule → ForceUnwrapRule
36+
37+
### 4. Prefer prefix
38+
- [ ] PreferSelfTypeOverTypeOfSelfRule → SelfTypeOverTypeOfSelfRule
39+
- [ ] PreferZeroOverExplicitInitRule → ZeroOverExplicitInitRule
40+
41+
### 5. Type/ID mismatch
42+
- [ ] EnumCaseAssociatedValuesLengthRule → EnumCaseAssociatedValuesCountRule
43+
44+
### 6. Long names
45+
- [ ] VerticalParameterAlignmentOnCallRule → CallParameterAlignmentRule
46+
- [ ] AnonymousArgumentInMultilineClosureRule → MultilineClosureAnonymousArgumentRule
47+
- [ ] EmptyParenthesesWithTrailingClosureRule → TrailingClosureEmptyParensRule
48+
- [ ] MultipleClosuresWithTrailingClosureRule → MultipleTrailingClosuresRule
49+
- [ ] RawValueForCamelCasedCodableEnumRule → CodableEnumRawValueRule
50+
- [ ] ContainsOverRangeNilComparisonRule → ContainsOverRangeCheckRule
51+
- [ ] NonOptionalStringDataConversionRule → StringDataConversionRule
52+
- [ ] BlankLinesBetweenChainedFunctionsRule → NoBlankLineInChainRule
53+
54+
### 7. Vague names
55+
- [ ] CaptureVariableRule → ImplicitSelfCaptureRule
56+
- [ ] ControlStatementRule → ControlStatementParensRule
57+
- [ ] LetVarWhitespaceRule → DeclarationWhitespaceRule
58+
- [ ] AttributesRule → AttributePlacementRule
59+
60+
### 8. Spacing vs Whitespace
61+
- [ ] ReturnArrowWhitespaceRule → ReturnArrowSpacingRule
62+
- [ ] FunctionNameWhitespaceRule → FunctionNameSpacingRule
63+
- [ ] OperatorUsageWhitespaceRule → OperatorUsageSpacingRule
64+
65+
### 9. Plural
66+
- [ ] BlankLinesAfterGuardStatementsRule → BlankLineAfterGuardRule
67+
68+
### Final
69+
- [ ] Run GeneratePipeline
70+
- [ ] Build succeeds
71+
- [ ] Tests pass

.issues/9/9qw-72x--improve-rule-summaries-fill-empty-static-let-summa.md

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
---
22
# 9qw-72x
33
title: 'Improve rule summaries: fill empty static let summary fields'
4-
status: ready
4+
status: completed
55
type: task
66
priority: normal
77
created_at: 2026-04-11T18:22:20Z
8-
updated_at: 2026-04-11T18:22:20Z
8+
updated_at: 2026-04-11T18:55:20Z
99
sync:
1010
github:
1111
issue_number: "181"
12-
synced_at: "2026-04-11T18:44:01Z"
12+
synced_at: "2026-04-11T19:12:32Z"
1313
---
1414

1515
6+ rules have `static let summary = ""`. Fill them in with concise, useful descriptions.
@@ -25,6 +25,42 @@ Identified rules with empty summaries:
2525

2626
## Tasks
2727

28-
- [ ] Find all rules with empty summary fields
29-
- [ ] Write concise summaries for each
30-
- [ ] Verify build passes
28+
- [x] Find all rules with empty summary fields (found 16)
29+
- [x] Write concise summaries for each
30+
- [x] Verify build passes
31+
32+
33+
## Summary of Changes
34+
35+
Filled in 16 empty rule summaries and improved 9 existing ones that were vague or awkwardly phrased.
36+
37+
### 16 new summaries
38+
- `number_separator` — Underscores should be used as thousand separators in large decimal numbers
39+
- `unhandled_throwing_task` — Errors thrown inside a Task are silently lost unless the result is checked
40+
- `non_overridable_class_declaration` — Use `static` or `final` instead of `class` for non-overridable members
41+
- `superfluous_disable_command` — Disable commands for rules that didn't trigger a violation are superfluous
42+
- `blanket_disable_command` — Disable commands should be scoped with `next`, `this`, or `previous` instead of the whole file
43+
- `static_over_final_class` — Prefer `static` over `final class` or `class` in a final class
44+
- `shorthand_argument` — Shorthand closure arguments (`$0`, `$1`) should be used sparingly and close to the closure opening
45+
- `inclusive_language` — Identifiers should use inclusive language that avoids discrimination
46+
- `unused_parameter` — Unused function parameters should be removed or replaced with `_`
47+
- `type_name` — Type names should be alphanumeric, start uppercase, and have a reasonable length
48+
- `contrasted_opening_brace` — Opening braces should be on a separate line from the preceding declaration
49+
- `opening_brace` — Opening braces should be preceded by a single space and on the same line as the declaration
50+
- `switch_case_alignment` — Case statements should vertically align with their enclosing switch's closing brace
51+
- `colon` — Colons should have no space before and one space after
52+
- `attribute_name_spacing` — There should be no space between an attribute or modifier and its arguments
53+
- `attributes` — Attributes should be on their own line for functions and types, same line for variables and imports
54+
55+
### 9 improved summaries
56+
- `invalid_command` — was "sm: command is invalid"
57+
- `unused_setter_value` — was "Setter value is not used"
58+
- `joined_default_parameter` — was "Discouraged explicit usage of the default separator"
59+
- `file_types_order` — was "Specifies how the types within a file should be ordered."
60+
- `type_contents_order` — was "Specifies the order of subtypes, properties, methods & more within a type."
61+
- `xct_specific_matcher` — was "Prefer specific XCTest matchers."
62+
- `discouraged_direct_init` — was "Discouraged direct initialization of types that can be harmful"
63+
- `syntactic_sugar` — was "Shorthand syntactic sugar should be used, i.e. [Int] instead of Array<Int>."
64+
- `self_binding` — was "Re-bind `self` to a consistent identifier name."
65+
66+
Confirmed: `summary` is the only description field on the `Rule` protocol — there is no separate `description` property. They are the same thing.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
# ypa-vrg
3+
title: Single-line body format rule
4+
status: completed
5+
type: feature
6+
priority: normal
7+
created_at: 2026-04-11T19:01:44Z
8+
updated_at: 2026-04-11T19:11:37Z
9+
sync:
10+
github:
11+
issue_number: "188"
12+
synced_at: "2026-04-11T19:12:32Z"
13+
---
14+
15+
Add a `single_line_body` format rule that condenses any braced block with a single statement onto one line when it fits within the print width.
16+
17+
## Requirements
18+
19+
- [x] Add `FormatAwareRule` protocol to bridge global `format.max_width` to rules
20+
- [x] Update `RuleResolver.loadRules` with `formatDefaults` injection
21+
- [x] Update call sites to pass format defaults
22+
- [x] Create `SingleLineBodyOptions` with `max_width`
23+
- [x] Create `SingleLineBodyRule` with Visitor + Rewriter
24+
- [x] Run `swift run GeneratePipeline`
25+
- [x] Create tests (20 passing)
26+
- [x] Build and test (full suite — 474 pass, 3 pre-existing failures in unrelated rule)
27+
28+
## Constructs handled
29+
30+
- guard, if, for, while, do, defer, catch (`CodeBlockSyntax`)
31+
- closures (`ClosureExprSyntax`)
32+
- getter-only computed properties (`AccessorBlockSyntax`)
33+
- willSet/didSet/get/set (`AccessorDeclSyntax`)
34+
35+
## Width calculation
36+
37+
Visual start column (tabs × indent width + spaces) + flattened single-line length ≤ max_width
38+
39+
40+
41+
## Summary of Changes
42+
43+
Added `single_line_body` opt-in format rule that condenses any single-statement braced block to one line when it fits within `format.max_width`.
44+
45+
**New files:**
46+
- `SingleLineBodyRule.swift` — Rule + Visitor (4 node types) + Rewriter
47+
- `SingleLineBodyOptions.swift``max_width` option
48+
- `SingleLineBodyRuleTests.swift` — 20 tests
49+
50+
**Infrastructure:**
51+
- `FormatAwareRule` protocol in `Rule.swift` — lets rules declare which global format keys they need
52+
- `RuleResolver.loadRules` gains `formatDefaults` parameter — injects global format config into FormatAwareRule conformers
53+
- Call sites (`SwiftiomaticCLI`, `FormatCommand`) pass `formatDefaults`

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- Nested per-directory configuration ([#169](https://github.com/toba/swiftiomatic/issues/169))
1010
- Add `dump-config` CLI subcommand to show resolved configuration
1111
- Support file-level `sm:disable:file` scope
12+
- `single_line_body` format rule; condense single-statement blocks to one line ([#188](https://github.com/toba/swiftiomatic/issues/188))
1213

1314
### 🐛 Fixes
1415

Sources/SwiftiomaticCLI/FormatCommand.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ struct FormatCommand: ParsableCommand {
133133
enabled: cfg.enabledLintRules.isEmpty ? nil : Set(cfg.enabledLintRules),
134134
disabled: Set(cfg.disabledLintRules),
135135
ruleConfigs: cfg.lintRuleConfigs,
136+
formatDefaults: ["max_width": cfg.formatMaxWidth],
136137
)
137138
let correctableRules = allRules.filter { type(of: $0).isCorrectable }
138139
guard !correctableRules.isEmpty else { return 0 }

Sources/SwiftiomaticCLI/SwiftiomaticCLI.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ struct Analyze: AsyncParsableCommand {
108108
disabled: mergedDisabled,
109109
onlyRules: Set(onlyRule),
110110
ruleConfigs: cfg.lintRuleConfigs,
111+
formatDefaults: ["max_width": cfg.formatMaxWidth],
111112
)
112113

113114
let analyzer = Analyzer(

Sources/SwiftiomaticKit/Rules/AccessControl/Modifiers/NonOverridableClassDeclarationRule.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import SwiftSyntax
33
struct NonOverridableClassDeclarationRule {
44
static let id = "non_overridable_class_declaration"
55
static let name = "Class Declaration in Final Class"
6-
static let summary = ""
6+
static let summary = "Use `static` or `final` instead of `class` for non-overridable members"
77
static let isCorrectable = true
88
static let isOptIn = true
99
static var nonTriggeringExamples: [Example] {

Sources/SwiftiomaticKit/Rules/AccessControl/Modifiers/StaticOverFinalClassRule.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import SwiftSyntax
33
struct StaticOverFinalClassRule {
44
static let id = "static_over_final_class"
55
static let name = "Static Over Final Class"
6-
static let summary = ""
6+
static let summary = "Prefer `static` over `final class` or `class` in a final class"
77
static var nonTriggeringExamples: [Example] {
88
[
99
Example(

Sources/SwiftiomaticKit/Rules/ControlFlow/Closures/SelfBindingRule.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import SwiftSyntax
55
struct SelfBindingRule {
66
static let id = "self_binding"
77
static let name = "Self Binding"
8-
static let summary = "Re-bind `self` to a consistent identifier name."
8+
static let summary = "Rebind `self` to a consistent identifier name in closures"
99
static let isCorrectable = true
1010
static let isOptIn = true
1111
static var nonTriggeringExamples: [Example] {

Sources/SwiftiomaticKit/Rules/ControlFlow/Closures/ShorthandArgumentRule.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import SwiftSyntax
33
struct ShorthandArgumentRule {
44
static let id = "shorthand_argument"
55
static let name = "Shorthand Argument"
6-
static let summary = ""
6+
static let summary = "Shorthand closure arguments (`$0`, `$1`) should be used sparingly and close to the closure opening"
77
static let isOptIn = true
88
static var nonTriggeringExamples: [Example] {
99
[

0 commit comments

Comments
 (0)