Skip to content

Commit fc7042b

Browse files
committed
Make rules work even inside of nested data structures. Fixes #778.
1 parent f0d1167 commit fc7042b

7 files changed

+269
-14
lines changed

Sources/SwiftFormat/Core/Pipelines+Generated.swift

+4
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ class LintPipeline: SyntaxVisitor {
3737
}
3838

3939
override func visit(_ node: ActorDeclSyntax) -> SyntaxVisitorContinueKind {
40+
visitIfEnabled(AllPublicDeclarationsHaveDocumentation.visit, for: node)
4041
visitIfEnabled(TypeNamesShouldBeCapitalized.visit, for: node)
4142
return .visitChildren
4243
}
4344
override func visitPost(_ node: ActorDeclSyntax) {
45+
onVisitPost(rule: AllPublicDeclarationsHaveDocumentation.self, for: node)
4446
onVisitPost(rule: TypeNamesShouldBeCapitalized.self, for: node)
4547
}
4648

@@ -179,6 +181,7 @@ class LintPipeline: SyntaxVisitor {
179181
}
180182

181183
override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind {
184+
visitIfEnabled(AllPublicDeclarationsHaveDocumentation.visit, for: node)
182185
visitIfEnabled(BeginDocumentationCommentWithOneLineSummary.visit, for: node)
183186
visitIfEnabled(FullyIndirectEnum.visit, for: node)
184187
visitIfEnabled(NoLeadingUnderscores.visit, for: node)
@@ -188,6 +191,7 @@ class LintPipeline: SyntaxVisitor {
188191
return .visitChildren
189192
}
190193
override func visitPost(_ node: EnumDeclSyntax) {
194+
onVisitPost(rule: AllPublicDeclarationsHaveDocumentation.self, for: node)
191195
onVisitPost(rule: BeginDocumentationCommentWithOneLineSummary.self, for: node)
192196
onVisitPost(rule: FullyIndirectEnum.self, for: node)
193197
onVisitPost(rule: NoLeadingUnderscores.self, for: node)

Sources/SwiftFormat/Rules/AllPublicDeclarationsHaveDocumentation.swift

+12-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public final class AllPublicDeclarationsHaveDocumentation: SyntaxLintRule {
4646

4747
public override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind {
4848
diagnoseMissingDocComment(DeclSyntax(node), name: node.name.text, modifiers: node.modifiers)
49-
return .skipChildren
49+
return .visitChildren
5050
}
5151

5252
public override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind {
@@ -57,7 +57,17 @@ public final class AllPublicDeclarationsHaveDocumentation: SyntaxLintRule {
5757

5858
public override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind {
5959
diagnoseMissingDocComment(DeclSyntax(node), name: node.name.text, modifiers: node.modifiers)
60-
return .skipChildren
60+
return .visitChildren
61+
}
62+
63+
public override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind {
64+
diagnoseMissingDocComment(DeclSyntax(node), name: node.name.text, modifiers: node.modifiers)
65+
return .visitChildren
66+
}
67+
68+
public override func visit(_ node: ActorDeclSyntax) -> SyntaxVisitorContinueKind {
69+
diagnoseMissingDocComment(DeclSyntax(node), name: node.name.text, modifiers: node.modifiers)
70+
return .visitChildren
6171
}
6272

6373
public override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind {

Sources/SwiftFormat/Rules/BeginDocumentationCommentWithOneLineSummary.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public final class BeginDocumentationCommentWithOneLineSummary: SyntaxLintRule {
4040

4141
public override func visit(_ node: EnumDeclSyntax) -> SyntaxVisitorContinueKind {
4242
diagnoseDocComments(in: DeclSyntax(node))
43-
return .skipChildren
43+
return .visitChildren
4444
}
4545

4646
public override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind {
@@ -60,7 +60,7 @@ public final class BeginDocumentationCommentWithOneLineSummary: SyntaxLintRule {
6060

6161
public override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind {
6262
diagnoseDocComments(in: DeclSyntax(node))
63-
return .skipChildren
63+
return .visitChildren
6464
}
6565

6666
public override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind {
@@ -70,7 +70,7 @@ public final class BeginDocumentationCommentWithOneLineSummary: SyntaxLintRule {
7070

7171
public override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind {
7272
diagnoseDocComments(in: DeclSyntax(node))
73-
return .skipChildren
73+
return .visitChildren
7474
}
7575

7676
public override func visit(_ node: ProtocolDeclSyntax) -> SyntaxVisitorContinueKind {

Sources/SwiftFormat/Rules/UseSynthesizedInitializer.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public final class UseSynthesizedInitializer: SyntaxLintRule {
7272
extraneousInitializers.forEach { diagnose(.removeRedundantInitializer, on: $0) }
7373
}
7474

75-
return .skipChildren
75+
return .visitChildren
7676
}
7777

7878
/// Compares the actual access level of an initializer with the access level of a synthesized

Tests/SwiftFormatTests/Rules/AllPublicDeclarationsHaveDocumentationTests.swift

+164-8
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,40 @@ final class AllPublicDeclarationsHaveDocumentationTests: LintOrFormatRuleTestCas
77
assertLint(
88
AllPublicDeclarationsHaveDocumentation.self,
99
"""
10-
1️⃣public func lightswitchRave() {
11-
}
10+
1️⃣public func lightswitchRave() {}
11+
/// Comment.
12+
public func lightswitchRave() {}
13+
func lightswitchRave() {}
1214
13-
2️⃣public var isSblounskched: Int {
14-
return 0
15-
}
15+
2️⃣public var isSblounskched: Int { return 0 }
16+
/// Comment.
17+
public var isSblounskched: Int { return 0 }
18+
var isSblounskched: Int { return 0 }
1619
17-
/// Everybody to the limit.
18-
public func fhqwhgads() {
19-
}
20+
3️⃣public struct Foo {}
21+
/// Comment.
22+
public struct Foo {}
23+
struct Foo {}
24+
25+
4️⃣public actor Bar {}
26+
/// Comment.
27+
public actor Bar {}
28+
actor Bar {}
29+
30+
5️⃣public class Baz {}
31+
/// Comment.
32+
public class Baz {}
33+
class Baz {}
34+
35+
6️⃣public enum Qux {}
36+
/// Comment.
37+
public enum Qux {}
38+
enum Qux {}
39+
40+
7️⃣public typealias MyType = Int
41+
/// Comment.
42+
public typealias MyType = Int
43+
typealias MyType = Int
2044
2145
/**
2246
* Determines if an email was delorted.
@@ -28,6 +52,138 @@ final class AllPublicDeclarationsHaveDocumentationTests: LintOrFormatRuleTestCas
2852
findings: [
2953
FindingSpec("1️⃣", message: "add a documentation comment for 'lightswitchRave()'"),
3054
FindingSpec("2️⃣", message: "add a documentation comment for 'isSblounskched'"),
55+
FindingSpec("3️⃣", message: "add a documentation comment for 'Foo'"),
56+
FindingSpec("4️⃣", message: "add a documentation comment for 'Bar'"),
57+
FindingSpec("5️⃣", message: "add a documentation comment for 'Baz'"),
58+
FindingSpec("6️⃣", message: "add a documentation comment for 'Qux'"),
59+
FindingSpec("7️⃣", message: "add a documentation comment for 'MyType'")
60+
]
61+
)
62+
}
63+
64+
func testNestedDecls() {
65+
assertLint(
66+
AllPublicDeclarationsHaveDocumentation.self,
67+
"""
68+
/// Comment.
69+
public struct MyContainer {
70+
1️⃣public func lightswitchRave() {}
71+
/// Comment.
72+
public func lightswitchRave() {}
73+
func lightswitchRave() {}
74+
75+
2️⃣public var isSblounskched: Int { return 0 }
76+
/// Comment.
77+
public var isSblounskched: Int { return 0 }
78+
var isSblounskched: Int { return 0 }
79+
80+
3️⃣public struct Foo {}
81+
/// Comment.
82+
public struct Foo {}
83+
struct Foo {}
84+
85+
4️⃣public actor Bar {}
86+
/// Comment.
87+
public actor Bar {}
88+
actor Bar {}
89+
90+
5️⃣public class Baz {}
91+
/// Comment.
92+
public class Baz {}
93+
class Baz {}
94+
95+
6️⃣public enum Qux {}
96+
/// Comment.
97+
public enum Qux {}
98+
enum Qux {}
99+
100+
7️⃣public typealias MyType = Int
101+
/// Comment.
102+
public typealias MyType = Int
103+
typealias MyType = Int
104+
105+
}
106+
""",
107+
findings: [
108+
FindingSpec("1️⃣", message: "add a documentation comment for 'lightswitchRave()'"),
109+
FindingSpec("2️⃣", message: "add a documentation comment for 'isSblounskched'"),
110+
FindingSpec("3️⃣", message: "add a documentation comment for 'Foo'"),
111+
FindingSpec("4️⃣", message: "add a documentation comment for 'Bar'"),
112+
FindingSpec("5️⃣", message: "add a documentation comment for 'Baz'"),
113+
FindingSpec("6️⃣", message: "add a documentation comment for 'Qux'"),
114+
FindingSpec("7️⃣", message: "add a documentation comment for 'MyType'")
115+
]
116+
)
117+
}
118+
119+
func testNestedInStruct() {
120+
assertLint(
121+
AllPublicDeclarationsHaveDocumentation.self,
122+
"""
123+
/// Comment.
124+
public struct MyContainer {
125+
1️⃣public typealias MyType = Int
126+
/// Comment.
127+
public typealias MyType = Int
128+
typealias MyType = Int
129+
}
130+
""",
131+
findings: [
132+
FindingSpec("1️⃣", message: "add a documentation comment for 'MyType'"),
133+
]
134+
)
135+
}
136+
137+
func testNestedInClass() {
138+
assertLint(
139+
AllPublicDeclarationsHaveDocumentation.self,
140+
"""
141+
/// Comment.
142+
public class MyContainer {
143+
1️⃣public typealias MyType = Int
144+
/// Comment.
145+
public typealias MyType = Int
146+
typealias MyType = Int
147+
}
148+
""",
149+
findings: [
150+
FindingSpec("1️⃣", message: "add a documentation comment for 'MyType'"),
151+
]
152+
)
153+
}
154+
155+
func testNestedInEnum() {
156+
assertLint(
157+
AllPublicDeclarationsHaveDocumentation.self,
158+
"""
159+
/// Comment.
160+
public enum MyContainer {
161+
1️⃣public typealias MyType = Int
162+
/// Comment.
163+
public typealias MyType = Int
164+
typealias MyType = Int
165+
}
166+
""",
167+
findings: [
168+
FindingSpec("1️⃣", message: "add a documentation comment for 'MyType'"),
169+
]
170+
)
171+
}
172+
173+
func testNestedInActor() {
174+
assertLint(
175+
AllPublicDeclarationsHaveDocumentation.self,
176+
"""
177+
/// Comment.
178+
public actor MyContainer {
179+
1️⃣public typealias MyType = Int
180+
/// Comment.
181+
public typealias MyType = Int
182+
typealias MyType = Int
183+
}
184+
""",
185+
findings: [
186+
FindingSpec("1️⃣", message: "add a documentation comment for 'MyType'"),
31187
]
32188
)
33189
}

Tests/SwiftFormatTests/Rules/BeginDocumentationCommentWithOneLineSummaryTests.swift

+65
Original file line numberDiff line numberDiff line change
@@ -169,4 +169,69 @@ final class BeginDocumentationCommentWithOneLineSummaryTests: LintOrFormatRuleTe
169169
"""
170170
)
171171
}
172+
173+
func testNestedInsideStruct() {
174+
assertLint(
175+
BeginDocumentationCommentWithOneLineSummary.self,
176+
"""
177+
struct MyContainer {
178+
/// This docline should not succeed.
179+
/// There are two sentences without a blank line between them.
180+
1️⃣struct Test {}
181+
}
182+
""",
183+
findings: [
184+
FindingSpec("1️⃣", message: #"add a blank comment line after this sentence: "This docline should not succeed.""#)
185+
]
186+
)
187+
}
188+
189+
func testNestedInsideEnum() {
190+
assertLint(
191+
BeginDocumentationCommentWithOneLineSummary.self,
192+
"""
193+
enum MyContainer {
194+
/// This docline should not succeed.
195+
/// There are two sentences without a blank line between them.
196+
1️⃣struct Test {}
197+
}
198+
""",
199+
findings: [
200+
FindingSpec("1️⃣", message: #"add a blank comment line after this sentence: "This docline should not succeed.""#)
201+
]
202+
)
203+
}
204+
205+
func testNestedInsideClass() {
206+
assertLint(
207+
BeginDocumentationCommentWithOneLineSummary.self,
208+
"""
209+
class MyContainer {
210+
/// This docline should not succeed.
211+
/// There are two sentences without a blank line between them.
212+
1️⃣struct Test {}
213+
}
214+
""",
215+
findings: [
216+
FindingSpec("1️⃣", message: #"add a blank comment line after this sentence: "This docline should not succeed.""#)
217+
]
218+
)
219+
}
220+
221+
func testNestedInsideActor() {
222+
assertLint(
223+
BeginDocumentationCommentWithOneLineSummary.self,
224+
"""
225+
actor MyContainer {
226+
/// This docline should not succeed.
227+
/// There are two sentences without a blank line between them.
228+
1️⃣struct Test {}
229+
}
230+
""",
231+
findings: [
232+
FindingSpec("1️⃣", message: #"add a blank comment line after this sentence: "This docline should not succeed.""#)
233+
]
234+
)
235+
}
236+
172237
}

Tests/SwiftFormatTests/Rules/UseSynthesizedInitializerTests.swift

+20
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,26 @@ final class UseSynthesizedInitializerTests: LintOrFormatRuleTestCase {
2626
)
2727
}
2828

29+
func testNestedMemberwiseInitializerIsDiagnosed() {
30+
assertLint(
31+
UseSynthesizedInitializer.self,
32+
"""
33+
public struct MyContainer {
34+
public struct Person {
35+
public var name: String
36+
37+
1️⃣init(name: String) {
38+
self.name = name
39+
}
40+
}
41+
}
42+
""",
43+
findings: [
44+
FindingSpec("1️⃣", message: "remove this explicit initializer, which is identical to the compiler-synthesized initializer"),
45+
]
46+
)
47+
}
48+
2949
func testInternalMemberwiseInitializerIsDiagnosed() {
3050
assertLint(
3151
UseSynthesizedInitializer.self,

0 commit comments

Comments
 (0)