@@ -16,47 +16,35 @@ struct MissingDocsRule: Rule {
1616}
1717
1818private extension MissingDocsRule {
19- final class Visitor : ViolationsSyntaxVisitor < ConfigurationType > {
20- private var aclScope = Stack < AccessControlBehavior > ( )
19+ final class Visitor : EffectiveAccessControlSyntaxVisitor < ConfigurationType > {
20+ init ( configuration: ConfigurationType , file: SwiftLintFile ) {
21+ super. init (
22+ configuration: configuration,
23+ file: file,
24+ evaluateEffectiveAcl: configuration. evaluateEffectiveAccessControlLevel
25+ )
26+ }
2127
2228 override func visit( _ node: ActorDeclSyntax ) -> SyntaxVisitorContinueKind {
23- defer {
24- aclScope. push (
25- behavior: . actor ( node. modifiers. accessibility) ,
26- evalEffectiveAcl: configuration. evaluateEffectiveAccessControlLevel
27- )
28- }
2929 if node. inherits, configuration. excludesInheritedTypes {
30+ _ = super. visit ( node)
3031 return . skipChildren
3132 }
3233 collectViolation ( from: node, on: node. actorKeyword)
33- return . visitChildren
34- }
35-
36- override func visitPost( _: ActorDeclSyntax ) {
37- aclScope. pop ( )
34+ return super. visit ( node)
3835 }
3936
4037 override func visitPost( _ node: AssociatedTypeDeclSyntax ) {
4138 collectViolation ( from: node, on: node. associatedtypeKeyword)
4239 }
4340
4441 override func visit( _ node: ClassDeclSyntax ) -> SyntaxVisitorContinueKind {
45- defer {
46- aclScope. push (
47- behavior: . class( node. modifiers. accessibility) ,
48- evalEffectiveAcl: configuration. evaluateEffectiveAccessControlLevel
49- )
50- }
5142 if node. inherits, configuration. excludesInheritedTypes {
43+ _ = super. visit ( node)
5244 return . skipChildren
5345 }
5446 collectViolation ( from: node, on: node. classKeyword)
55- return . visitChildren
56- }
57-
58- override func visitPost( _: ClassDeclSyntax ) {
59- aclScope. pop ( )
47+ return super. visit ( node)
6048 }
6149
6250 override func visit( _: ClosureExprSyntax ) -> SyntaxVisitorContinueKind {
@@ -68,52 +56,38 @@ private extension MissingDocsRule {
6856 }
6957
7058 override func visitPost( _ node: EnumCaseDeclSyntax ) {
71- guard !node. hasDocComment, case let . enum ( enumAcl ) = aclScope . peek ( ) else {
59+ guard !node. hasDocComment, let enumAccessControlLevel else {
7260 return
7361 }
74- let acl = enumAcl ?? . internal
75- if let parameter = configuration. parameters. first ( where: { $0. value == acl } ) {
62+ if let parameter = configuration. parameters. first ( where: { $0. value == enumAccessControlLevel } ) {
7663 violations. append (
77- ReasonedRuleViolation (
64+ . init (
7865 position: node. caseKeyword. positionAfterSkippingLeadingTrivia,
79- reason: " \( acl ) declarations should be documented " ,
66+ reason: " \( enumAccessControlLevel ) declarations should be documented " ,
8067 severity: parameter. severity
8168 )
8269 )
8370 }
8471 }
8572
8673 override func visit( _ node: EnumDeclSyntax ) -> SyntaxVisitorContinueKind {
87- defer {
88- aclScope. push (
89- behavior: . enum( node. modifiers. accessibility) ,
90- evalEffectiveAcl: configuration. evaluateEffectiveAccessControlLevel
91- )
92- }
9374 if node. inherits, configuration. excludesInheritedTypes {
75+ _ = super. visit ( node)
9476 return . skipChildren
9577 }
9678 collectViolation ( from: node, on: node. enumKeyword)
97- return . visitChildren
98- }
99-
100- override func visitPost( _: EnumDeclSyntax ) {
101- aclScope. pop ( )
79+ return super. visit ( node)
10280 }
10381
10482 override func visit( _ node: ExtensionDeclSyntax ) -> SyntaxVisitorContinueKind {
105- defer { aclScope. push ( . extension( node. modifiers. accessibility) ) }
10683 if node. inherits, configuration. excludesInheritedTypes {
84+ _ = super. visit ( node)
10785 return . skipChildren
10886 }
10987 if !configuration. excludesExtensions {
11088 collectViolation ( from: node, on: node. extensionKeyword)
11189 }
112- return . visitChildren
113- }
114-
115- override func visitPost( _: ExtensionDeclSyntax ) {
116- aclScope. pop ( )
90+ return super. visit ( node)
11791 }
11892
11993 override func visit( _ node: FunctionDeclSyntax ) -> SyntaxVisitorContinueKind {
@@ -129,39 +103,21 @@ private extension MissingDocsRule {
129103 }
130104
131105 override func visit( _ node: ProtocolDeclSyntax ) -> SyntaxVisitorContinueKind {
132- defer {
133- aclScope. push (
134- behavior: . protocol( node. modifiers. accessibility) ,
135- evalEffectiveAcl: configuration. evaluateEffectiveAccessControlLevel
136- )
137- }
138106 if node. inherits, configuration. excludesInheritedTypes {
107+ _ = super. visit ( node)
139108 return . skipChildren
140109 }
141110 collectViolation ( from: node, on: node. protocolKeyword)
142- return . visitChildren
143- }
144-
145- override func visitPost( _: ProtocolDeclSyntax ) {
146- aclScope. pop ( )
111+ return super. visit ( node)
147112 }
148113
149114 override func visit( _ node: StructDeclSyntax ) -> SyntaxVisitorContinueKind {
150- defer {
151- aclScope. push (
152- behavior: . struct( node. modifiers. accessibility) ,
153- evalEffectiveAcl: configuration. evaluateEffectiveAccessControlLevel
154- )
155- }
156115 if node. inherits, configuration. excludesInheritedTypes {
116+ _ = super. visit ( node)
157117 return . skipChildren
158118 }
159119 collectViolation ( from: node, on: node. structKeyword)
160- return . visitChildren
161- }
162-
163- override func visitPost( _: StructDeclSyntax ) {
164- aclScope. pop ( )
120+ return super. visit ( node)
165121 }
166122
167123 override func visit( _ node: SubscriptDeclSyntax ) -> SyntaxVisitorContinueKind {
@@ -182,10 +138,7 @@ private extension MissingDocsRule {
182138 if node. modifiers. contains ( keyword: . override) || node. hasDocComment {
183139 return
184140 }
185- let acl = aclScope. computeAcl (
186- givenExplicitAcl: node. modifiers. accessibility,
187- evalEffectiveAcl: configuration. evaluateEffectiveAccessControlLevel
188- )
141+ let acl = effectiveAccessControlLevel ( for: node. modifiers)
189142 if let parameter = configuration. parameters. first ( where: { $0. value == acl } ) {
190143 violations. append (
191144 ReasonedRuleViolation (
@@ -230,94 +183,3 @@ private extension SyntaxProtocol {
230183 }
231184 }
232185}
233-
234- private extension DeclModifierListSyntax {
235- var accessibility : AccessControlLevel ? {
236- filter { $0. detail == nil } . compactMap { AccessControlLevel ( description: $0. name. text) } . first
237- }
238- }
239-
240- private enum AccessControlBehavior {
241- case `actor`( AccessControlLevel ? )
242- case local
243- case `class`( AccessControlLevel ? )
244- case `enum`( AccessControlLevel ? )
245- case `extension`( AccessControlLevel ? )
246- case `protocol`( AccessControlLevel ? )
247- case `struct`( AccessControlLevel ? )
248-
249- var effectiveAcl : AccessControlLevel {
250- explicitAcl ?? . internal
251- }
252-
253- var explicitAcl : AccessControlLevel ? {
254- switch self {
255- case let . actor ( acl) : acl
256- case . local: nil
257- case let . class( acl) : acl
258- case let . enum( acl) : acl
259- case let . extension( acl) : acl
260- case let . protocol( acl) : acl
261- case let . struct( acl) : acl
262- }
263- }
264-
265- func sameWith( acl: AccessControlLevel ) -> Self {
266- switch self {
267- case . actor : . actor ( acl)
268- case . local: . local
269- case . class: . class( acl)
270- case . enum: . enum( acl)
271- case . extension: . extension( acl)
272- case . protocol: . protocol( acl)
273- case . struct: . struct( acl)
274- }
275- }
276- }
277-
278- /// Implementation of Swift's effective ACL logic. Should be moved to a specialized syntax visitor for reuse some time.
279- private extension Stack < AccessControlBehavior > {
280- mutating func push( behavior: AccessControlBehavior , evalEffectiveAcl: Bool ) {
281- if let parentBehavior = peek ( ) {
282- switch parentBehavior {
283- case . local:
284- push ( . local)
285- case . actor , . class, . struct, . enum:
286- if behavior. effectiveAcl <= parentBehavior. effectiveAcl || !evalEffectiveAcl {
287- push ( behavior)
288- } else {
289- push ( behavior. sameWith ( acl: parentBehavior. effectiveAcl) )
290- }
291- case . extension, . protocol:
292- if behavior. explicitAcl != nil {
293- push ( behavior)
294- } else {
295- push ( behavior. sameWith ( acl: parentBehavior. effectiveAcl) )
296- }
297- }
298- } else {
299- push ( behavior)
300- }
301- }
302-
303- func computeAcl( givenExplicitAcl acl: AccessControlLevel ? , evalEffectiveAcl: Bool ) -> AccessControlLevel {
304- if let parentBehavior = peek ( ) {
305- switch parentBehavior {
306- case . local:
307- . private
308- case . actor , . class, . struct, . enum:
309- if let acl {
310- acl < parentBehavior. effectiveAcl || !evalEffectiveAcl ? acl : parentBehavior. effectiveAcl
311- } else {
312- parentBehavior. effectiveAcl >= . internal ? . internal : parentBehavior. effectiveAcl
313- }
314- case . protocol:
315- parentBehavior. effectiveAcl
316- case . extension:
317- acl ?? parentBehavior. effectiveAcl
318- }
319- } else {
320- acl ?? . internal
321- }
322- }
323- }
0 commit comments