Skip to content

Commit 8a61126

Browse files
Try to add --treat-warnings-as-errors (#28)
1 parent fcda613 commit 8a61126

File tree

2 files changed

+119
-70
lines changed

2 files changed

+119
-70
lines changed

Sources/LocheckCommand/main.swift

+111-70
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ let version = "0.9.2"
1616
struct Locheck: ParsableCommand {
1717
static let configuration = CommandConfiguration(
1818
abstract: """
19-
Validate your Xcode localization files. Currently only works on .strings. The different
20-
commands have different amounts of automation. `discover` operates on a directory of
21-
.lproj files, `lproj` operates on specific .lproj files, and `strings` operates on
22-
specific .strings files.
19+
Validate your Xcode localization files. The different commands have
20+
different amounts of automation. `discover` operates on a directory of
21+
.lproj files, `lproj` operates on specific .lproj files, and `strings`
22+
operates on specific .strings files.
2323
""",
2424
subcommands: [
2525
DiscoverLproj.self,
@@ -36,10 +36,11 @@ private func withProblemReporter(
3636
root: String,
3737
ignore: [String],
3838
ignoreWarnings: Bool,
39+
treatWarningsAsErrors: Bool,
3940
_ block: (ProblemReporter) -> Void) {
4041
let problemReporter = ProblemReporter(root: root, ignoredProblemIdentifiers: ignore, ignoreWarnings: ignoreWarnings)
4142
block(problemReporter)
42-
if problemReporter.hasError {
43+
if problemReporter.hasError || (treatWarningsAsErrors && problemReporter.hasWarning) {
4344
print("Errors found")
4445
Darwin.exit(1)
4546
}
@@ -53,6 +54,9 @@ private let ignoreMissingHelpText: ArgumentHelp =
5354

5455
private let ignoreWarningsHelpText: ArgumentHelp = "Ignore all warning-level issues."
5556

57+
private let treatWarningsAsErrorsHelpText: ArgumentHelp =
58+
"Return a non-zero exit code if any warnings, not just errors, were encountered."
59+
5660
private protocol HasIgnoreWithShorthand {
5761
var ignore: [String] { get }
5862
var ignoreMissing: Bool { get }
@@ -81,24 +85,31 @@ struct XCStrings: HasIgnoreWithShorthand, ParsableCommand {
8185
@Flag(help: ignoreWarningsHelpText)
8286
fileprivate var ignoreWarnings = false
8387

88+
@Flag(help: treatWarningsAsErrorsHelpText)
89+
fileprivate var treatWarningsAsErrors = false
90+
8491
func validate() throws {
8592
try stringsFiles.forEach { try $0.validate(ext: "strings") }
8693
}
8794

8895
func run() {
89-
withProblemReporter(root: "", ignore: ignoreWithShorthand, ignoreWarnings: ignoreWarnings) { problemReporter in
90-
let base = stringsFiles[0]
91-
let translationFiles = stringsFiles.dropFirst()
92-
for file in translationFiles {
93-
let translationFile = try! File(path: file.argument)
94-
parseAndValidateXCStrings(
95-
base: try! File(path: base.argument),
96-
translation: translationFile,
97-
translationLanguageName: translationFile.nameExcludingExtension,
98-
problemReporter: problemReporter)
96+
withProblemReporter(
97+
root: "",
98+
ignore: ignoreWithShorthand,
99+
ignoreWarnings: ignoreWarnings,
100+
treatWarningsAsErrors: treatWarningsAsErrors) { problemReporter in
101+
let base = stringsFiles[0]
102+
let translationFiles = stringsFiles.dropFirst()
103+
for file in translationFiles {
104+
let translationFile = try! File(path: file.argument)
105+
parseAndValidateXCStrings(
106+
base: try! File(path: base.argument),
107+
translation: translationFile,
108+
translationLanguageName: translationFile.nameExcludingExtension,
109+
problemReporter: problemReporter)
110+
}
111+
problemReporter.printSummary()
99112
}
100-
problemReporter.printSummary()
101-
}
102113
}
103114
}
104115

@@ -119,32 +130,39 @@ struct AndroidStrings: HasIgnoreWithShorthand, ParsableCommand {
119130
@Flag(help: ignoreWarningsHelpText)
120131
fileprivate var ignoreWarnings = false
121132

133+
@Flag(help: treatWarningsAsErrorsHelpText)
134+
fileprivate var treatWarningsAsErrors = false
135+
122136
func validate() throws {
123137
try stringsFiles.forEach { try $0.validate(ext: "xml") }
124138
}
125139

126140
func run() {
127-
withProblemReporter(root: "", ignore: ignoreWithShorthand, ignoreWarnings: ignoreWarnings) { problemReporter in
128-
let baseFile = stringsFiles[0]
129-
let translationFiles = stringsFiles.dropFirst()
130-
if translationFiles.isEmpty {
131-
// Just do what we can with the base language, i.e. validate plurals
132-
_ = AndroidStringsFile(path: baseFile.argument, problemReporter: problemReporter)
133-
}
134-
for file in translationFiles {
135-
let translationFile = try! File(path: file.argument)
136-
var translationLanguageName = translationFile.parent!.nameExcludingExtension
137-
if translationLanguageName.hasPrefix("values-") {
138-
translationLanguageName = String(translationLanguageName.dropFirst("values-".count))
141+
withProblemReporter(
142+
root: "",
143+
ignore: ignoreWithShorthand,
144+
ignoreWarnings: ignoreWarnings,
145+
treatWarningsAsErrors: treatWarningsAsErrors) { problemReporter in
146+
let baseFile = stringsFiles[0]
147+
let translationFiles = stringsFiles.dropFirst()
148+
if translationFiles.isEmpty {
149+
// Just do what we can with the base language, i.e. validate plurals
150+
_ = AndroidStringsFile(path: baseFile.argument, problemReporter: problemReporter)
151+
}
152+
for file in translationFiles {
153+
let translationFile = try! File(path: file.argument)
154+
var translationLanguageName = translationFile.parent!.nameExcludingExtension
155+
if translationLanguageName.hasPrefix("values-") {
156+
translationLanguageName = String(translationLanguageName.dropFirst("values-".count))
157+
}
158+
parseAndValidateAndroidStrings(
159+
base: try! File(path: baseFile.argument),
160+
translation: translationFile,
161+
translationLanguageName: translationLanguageName,
162+
problemReporter: problemReporter)
139163
}
140-
parseAndValidateAndroidStrings(
141-
base: try! File(path: baseFile.argument),
142-
translation: translationFile,
143-
translationLanguageName: translationLanguageName,
144-
problemReporter: problemReporter)
164+
problemReporter.printSummary()
145165
}
146-
problemReporter.printSummary()
147-
}
148166
}
149167
}
150168

@@ -164,30 +182,38 @@ struct Stringsdict: HasIgnoreWithShorthand, ParsableCommand {
164182
@Flag(help: ignoreWarningsHelpText)
165183
fileprivate var ignoreWarnings = false
166184

185+
@Flag(help: treatWarningsAsErrorsHelpText)
186+
fileprivate var treatWarningsAsErrors = false
187+
167188
func validate() throws {
168189
try stringsdictFiles.forEach { try $0.validate(ext: "stringsdict") }
169190
}
170191

171192
func run() {
172-
withProblemReporter(root: "", ignore: ignoreWithShorthand, ignoreWarnings: ignoreWarnings) { problemReporter in
173-
let baseFile = stringsdictFiles[0]
174-
let translationFiles = stringsdictFiles.dropFirst()
175-
// Just do what we can with the base language, i.e. validate plurals
176-
if translationFiles.isEmpty, let stringsdictFile = StringsdictFile(
177-
path: baseFile.argument,
178-
problemReporter: problemReporter) {
179-
stringsdictFile.entries.forEach { _ = $0.getCanonicalArgumentList(problemReporter: problemReporter) }
180-
}
181-
for file in translationFiles {
182-
let translationFile = try! File(path: file.argument)
183-
parseAndValidateStringsdict(
184-
base: try! File(path: baseFile.argument),
185-
translation: translationFile,
186-
translationLanguageName: translationFile.nameExcludingExtension,
187-
problemReporter: problemReporter)
193+
withProblemReporter(
194+
root: "",
195+
ignore: ignoreWithShorthand,
196+
ignoreWarnings: ignoreWarnings,
197+
treatWarningsAsErrors: treatWarningsAsErrors) { problemReporter in
198+
let baseFile = stringsdictFiles[0]
199+
let translationFiles = stringsdictFiles.dropFirst()
200+
// Just do what we can with the base language, i.e. validate plurals
201+
if translationFiles.isEmpty, let stringsdictFile = StringsdictFile(
202+
path: baseFile.argument,
203+
problemReporter: problemReporter) {
204+
stringsdictFile.entries
205+
.forEach { _ = $0.getCanonicalArgumentList(problemReporter: problemReporter) }
206+
}
207+
for file in translationFiles {
208+
let translationFile = try! File(path: file.argument)
209+
parseAndValidateStringsdict(
210+
base: try! File(path: baseFile.argument),
211+
translation: translationFile,
212+
translationLanguageName: translationFile.nameExcludingExtension,
213+
problemReporter: problemReporter)
214+
}
215+
problemReporter.printSummary()
188216
}
189-
problemReporter.printSummary()
190-
}
191217
}
192218
}
193219

@@ -207,6 +233,9 @@ struct Lproj: HasIgnoreWithShorthand, ParsableCommand {
207233
@Flag(help: ignoreWarningsHelpText)
208234
fileprivate var ignoreWarnings = false
209235

236+
@Flag(help: treatWarningsAsErrorsHelpText)
237+
fileprivate var treatWarningsAsErrors = false
238+
210239
func validate() throws {
211240
try lprojFiles.forEach { try $0.validate(ext: "lproj") }
212241
}
@@ -219,21 +248,25 @@ struct Lproj: HasIgnoreWithShorthand, ParsableCommand {
219248
"Validating \(translationFiles.count) lproj files against \(try! Folder(path: baseFile.argument).name)")
220249
}
221250

222-
withProblemReporter(root: "", ignore: ignoreWithShorthand, ignoreWarnings: ignoreWarnings) { problemReporter in
223-
// Same as in DiscoverLproj command below
224-
if translationFiles.isEmpty {
225-
// Just do what we can with the base language, i.e. validate plurals
226-
let lprojFiles = LprojFiles(folder: try! Folder(path: baseFile.argument))
227-
lprojFiles.validateInternally(problemReporter: problemReporter)
228-
}
229-
for translation in translationFiles {
230-
validateLproj(
231-
base: LprojFiles(folder: try! Folder(path: baseFile.argument)),
232-
translation: LprojFiles(folder: try! Folder(path: translation.argument)),
233-
problemReporter: problemReporter)
251+
withProblemReporter(
252+
root: "",
253+
ignore: ignoreWithShorthand,
254+
ignoreWarnings: ignoreWarnings,
255+
treatWarningsAsErrors: treatWarningsAsErrors) { problemReporter in
256+
// Same as in DiscoverLproj command below
257+
if translationFiles.isEmpty {
258+
// Just do what we can with the base language, i.e. validate plurals
259+
let lprojFiles = LprojFiles(folder: try! Folder(path: baseFile.argument))
260+
lprojFiles.validateInternally(problemReporter: problemReporter)
261+
}
262+
for translation in translationFiles {
263+
validateLproj(
264+
base: LprojFiles(folder: try! Folder(path: baseFile.argument)),
265+
translation: LprojFiles(folder: try! Folder(path: translation.argument)),
266+
problemReporter: problemReporter)
267+
}
268+
problemReporter.printSummary()
234269
}
235-
problemReporter.printSummary()
236-
}
237270
}
238271
}
239272

@@ -258,6 +291,9 @@ struct DiscoverLproj: HasIgnoreWithShorthand, ParsableCommand {
258291
@Flag(help: ignoreWarningsHelpText)
259292
fileprivate var ignoreWarnings = false
260293

294+
@Flag(help: treatWarningsAsErrorsHelpText)
295+
fileprivate var treatWarningsAsErrors = false
296+
261297
func validate() throws {
262298
for directory in directories {
263299
try directory.validate()
@@ -296,7 +332,8 @@ struct DiscoverLproj: HasIgnoreWithShorthand, ParsableCommand {
296332
withProblemReporter(
297333
root: directory.argument,
298334
ignore: ignoreWithShorthand,
299-
ignoreWarnings: ignoreWarnings) { problemReporter in
335+
ignoreWarnings: ignoreWarnings,
336+
treatWarningsAsErrors: treatWarningsAsErrors) { problemReporter in
300337
// Same as in Lproj command above
301338
if translationLproj.isEmpty {
302339
// Just do what we can with the base language, i.e. validate plurals
@@ -329,6 +366,9 @@ struct DiscoverValues: HasIgnoreWithShorthand, ParsableCommand {
329366
@Flag(help: ignoreWarningsHelpText)
330367
fileprivate var ignoreWarnings = false
331368

369+
@Flag(help: treatWarningsAsErrorsHelpText)
370+
fileprivate var treatWarningsAsErrors = false
371+
332372
func validate() throws {
333373
for directory in directories {
334374
try directory.validate()
@@ -378,7 +418,8 @@ struct DiscoverValues: HasIgnoreWithShorthand, ParsableCommand {
378418
withProblemReporter(
379419
root: directory.argument,
380420
ignore: ignoreWithShorthand,
381-
ignoreWarnings: ignoreWarnings) { problemReporter in
421+
ignoreWarnings: ignoreWarnings,
422+
treatWarningsAsErrors: treatWarningsAsErrors) { problemReporter in
382423
for translation in translationValues {
383424
parseAndValidateAndroidStrings(
384425
base: primaryValues,

Sources/LocheckLogic/ProblemReporter.swift

+8
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,14 @@ public class ProblemReporter {
134134
}
135135
}
136136

137+
/**
138+
Returns true iff a `.warning`-severity problem has been reported. Returns `false` if no problems
139+
or only errors were reported.
140+
*/
141+
public var hasWarning: Bool {
142+
problems.contains(where: { $0.problem.severity == .warning })
143+
}
144+
137145
/**
138146
Returns true iff an `.error`-severity problem has been reported. Returns `false` if no problems
139147
or only warnings were reported.

0 commit comments

Comments
 (0)