11
11
//===----------------------------------------------------------------------===//
12
12
13
13
import Foundation
14
+ import SwiftFormatCore
14
15
import SwiftSyntax
15
16
16
17
// These rules will not be added to the pipeline.
@@ -19,7 +20,7 @@ let suppressRules = ["UseEarlyExits", "UseWhereClausesInForLoops"]
19
20
/// Collects information about rules in the formatter code base.
20
21
final class RuleCollector {
21
22
/// Information about a detected rule.
22
- private struct DetectedRule {
23
+ struct DetectedRule : Hashable {
23
24
/// The type name of the rule.
24
25
let typeName : String
25
26
@@ -28,13 +29,16 @@ final class RuleCollector {
28
29
29
30
/// Indicates whether the rule can format code (all rules can lint).
30
31
let canFormat : Bool
32
+
33
+ /// Indicates whether the rule is disabled by default, i.e. requires opting in to use it.
34
+ let isOptIn : Bool
31
35
}
32
36
33
37
/// A list of all rules that can lint (thus also including format rules) found in the code base.
34
- var allLinters = Set < String > ( )
38
+ var allLinters = Set < DetectedRule > ( )
35
39
36
40
/// A list of all the format-only rules found in the code base.
37
- var allFormatters = Set < String > ( )
41
+ var allFormatters = Set < DetectedRule > ( )
38
42
39
43
/// A dictionary mapping syntax node types to the lint/format rules that visit them.
40
44
var syntaxNodeLinters = [ String: [ String] ] ( )
@@ -63,13 +67,13 @@ final class RuleCollector {
63
67
if detectedRule. canFormat {
64
68
// Format rules just get added to their own list; we run them each over the entire tree in
65
69
// succession.
66
- allFormatters. insert ( detectedRule. typeName )
70
+ allFormatters. insert ( detectedRule)
67
71
}
68
72
69
73
// Lint rules (this includes format rules, which can also lint) get added to a mapping over
70
74
// the names of the types they touch so that they can be interleaved into one pass over the
71
75
// tree.
72
- allLinters. insert ( detectedRule. typeName )
76
+ allLinters. insert ( detectedRule)
73
77
for visitedNode in detectedRule. visitedNodes {
74
78
syntaxNodeLinters [ visitedNode, default: [ ] ] . append ( detectedRule. typeName)
75
79
}
@@ -132,7 +136,12 @@ final class RuleCollector {
132
136
/// Ignore it if it doesn't have any; there's no point in putting no-op rules in the pipeline.
133
137
/// Otherwise, return it (we don't need to look at the rest of the inheritances).
134
138
guard !visitedNodes. isEmpty else { return nil }
135
- return DetectedRule ( typeName: typeName, visitedNodes: visitedNodes, canFormat: canFormat)
139
+ guard let ruleType = _typeByName ( " SwiftFormatRules. \( typeName) " ) as? Rule . Type else {
140
+ preconditionFailure ( " Failed to find type for rule named \( typeName) " )
141
+ }
142
+ return DetectedRule (
143
+ typeName: typeName, visitedNodes: visitedNodes, canFormat: canFormat,
144
+ isOptIn: ruleType. isOptIn)
136
145
}
137
146
138
147
return nil
0 commit comments