-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Expand file tree
/
Copy pathFileHeaderConfiguration.swift
More file actions
134 lines (112 loc) · 5.39 KB
/
FileHeaderConfiguration.swift
File metadata and controls
134 lines (112 loc) · 5.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import Foundation
import SourceKittenFramework
import SwiftLintCore
struct FileHeaderConfiguration: SeverityBasedRuleConfiguration {
typealias Parent = FileHeaderRule
private static let fileNamePlaceholder = "SWIFTLINT_CURRENT_FILENAME"
private static let stringRegexOptions: NSRegularExpression.Options = [.ignoreMetacharacters]
private static let patternRegexOptions: NSRegularExpression.Options =
[.anchorsMatchLines, .dotMatchesLineSeparators]
@ConfigurationElement(key: "severity")
private(set) var severityConfiguration = SeverityConfiguration<Parent>(.warning)
@ConfigurationElement(key: "required_string")
private var requiredString: String?
@ConfigurationElement(key: "required_pattern")
private var requiredPattern: String?
@ConfigurationElement(key: "forbidden_string")
private var forbiddenString: String?
@ConfigurationElement(key: "forbidden_pattern")
private var forbiddenPattern: String?
private var _forbiddenRegex: RegularExpression?
private var _requiredRegex: RegularExpression?
private static let defaultRegex = regex("\\bCopyright\\b", options: [.caseInsensitive])
mutating func apply(configuration: Any) throws(Issue) {
guard let configuration = configuration as? [String: String] else {
throw .invalidConfiguration(ruleID: Parent.identifier)
}
// Cache the created regexes if possible.
// If the pattern contains the SWIFTLINT_CURRENT_FILENAME placeholder,
// the regex will be recompiled for each validated file.
if let requiredString = configuration[$requiredString.key] {
self.requiredString = requiredString
if !requiredString.contains(Self.fileNamePlaceholder) {
_requiredRegex = try .from(
pattern: requiredString,
options: Self.stringRegexOptions,
for: Parent.identifier
)
}
} else if let requiredPattern = configuration[$requiredPattern.key] {
self.requiredPattern = requiredPattern
if !requiredPattern.contains(Self.fileNamePlaceholder) {
_requiredRegex = try .from(pattern: requiredPattern, for: Parent.identifier)
}
}
if let forbiddenString = configuration[$forbiddenString.key] {
self.forbiddenString = forbiddenString
if !forbiddenString.contains(Self.fileNamePlaceholder) {
_forbiddenRegex = try .from(
pattern: forbiddenString,
options: Self.stringRegexOptions,
for: Parent.identifier
)
}
} else if let forbiddenPattern = configuration[$forbiddenPattern.key] {
self.forbiddenPattern = forbiddenPattern
if !forbiddenPattern.contains(Self.fileNamePlaceholder) {
_forbiddenRegex = try .from(pattern: forbiddenPattern, for: Parent.identifier)
}
}
if let severityString = configuration[$severityConfiguration.key] {
try severityConfiguration.apply(configuration: severityString)
}
}
private func makeRegex(for file: SwiftLintFile,
using pattern: String,
options: NSRegularExpression.Options,
escapeFileName: Bool) -> NSRegularExpression? {
// Recompile the regex for this file...
let replacedPattern = file.path.map { path in
let fileName = path.lastPathComponent
// Replace SWIFTLINT_CURRENT_FILENAME with the filename.
let escapedName = escapeFileName ? NSRegularExpression.escapedPattern(for: fileName) : fileName
return pattern.replacingOccurrences(of: Self.fileNamePlaceholder,
with: escapedName)
} ?? pattern
do {
return try NSRegularExpression(pattern: replacedPattern, options: options)
} catch {
queuedFatalError("Failed to compile pattern '\(replacedPattern)'")
}
}
private func regexFromString(for file: SwiftLintFile, using pattern: String) -> NSRegularExpression? {
makeRegex(for: file, using: pattern, options: Self.stringRegexOptions, escapeFileName: false)
}
private func regexFromPattern(for file: SwiftLintFile, using pattern: String) -> NSRegularExpression? {
makeRegex(for: file, using: pattern, options: Self.patternRegexOptions, escapeFileName: true)
}
func forbiddenRegex(for file: SwiftLintFile) -> NSRegularExpression? {
if _forbiddenRegex != nil {
return _forbiddenRegex?.regex
}
if let regex = forbiddenString.flatMap({ regexFromString(for: file, using: $0) }) {
return regex
}
if let regex = forbiddenPattern.flatMap({ regexFromPattern(for: file, using: $0) }) {
return regex
}
if requiredPattern == nil, requiredString == nil {
return Self.defaultRegex
}
return nil
}
func requiredRegex(for file: SwiftLintFile) -> NSRegularExpression? {
if _requiredRegex != nil {
return _requiredRegex?.regex
}
if let regex = requiredString.flatMap({ regexFromString(for: file, using: $0) }) {
return regex
}
return requiredPattern.flatMap { regexFromPattern(for: file, using: $0) }
}
}