Skip to content

Commit 884a6e0

Browse files
committed
Make parsing noise resilient
1 parent 64331d3 commit 884a6e0

File tree

2 files changed

+51
-27
lines changed

2 files changed

+51
-27
lines changed

Sources/ReleaseNotesCore/Parser.swift

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,11 @@ import SemanticVersion
1818

1919
enum Parser {
2020

21-
static let progress = Skip(
22-
"Updating"
23-
.orElse("Updated")
24-
.orElse("Computing")
25-
.orElse("Computed")
26-
.orElse("Creating working copy")
27-
.orElse("Working copy of")
28-
)
29-
.skip(Prefix { $0 != "\n"})
30-
31-
static let anyProgress = Many(progress, separator: "\n")
21+
static let dependencyStart = Int.parser().skip(" dependenc")
22+
23+
static let progressLine = Not(dependencyStart).skip(PrefixThrough("\n"))
24+
25+
static let progress = Many(progressLine)
3226

3327
static let dependencyCount = Int.parser()
3428
.skip(
@@ -73,13 +67,29 @@ enum Parser {
7367

7468
static let updates = Many(update, separator: "\n")
7569

76-
static let packageUpdate = Skip(anyProgress)
70+
static let packageUpdate = Skip(progress)
7771
.skip(Many("\n"))
7872
.take(dependencyCount)
7973
.take(updates)
8074
.map { (count, updates) -> [Update] in
8175
assert(updates.count == count)
8276
return updates
8377
}
84-
78+
79+
}
80+
81+
82+
struct Not<P>: Parsing.Parser where P: Parsing.Parser {
83+
let parser: P
84+
85+
init(_ parser: P) { self.parser = parser }
86+
87+
func parse(_ input: inout P.Input) -> Void? {
88+
let original = input
89+
if parser.parse(&input) != nil {
90+
input = original
91+
return nil
92+
}
93+
return ()
94+
}
8595
}

Tests/ReleaseNotesTests/ParserCoreTests.swift

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,39 +14,40 @@
1414

1515
@testable import ReleaseNotesCore
1616
import XCTest
17+
import Parsing
1718

1819

1920
final class ParserCoreTests: XCTestCase {
2021

21-
func test_progress() throws {
22+
func test_progressLine() throws {
2223
do {
23-
var input = "Updating https://github.com/pointfreeco/swift-parsing"[...]
24-
XCTAssertNotNil(Parser.progress.parse(&input))
24+
var input = "Updating https://github.com/pointfreeco/swift-parsing\n"[...]
25+
XCTAssertNotNil(Parser.progressLine.parse(&input))
2526
XCTAssertEqual(input, "")
2627
}
2728
do {
28-
var input = "Updated https://github.com/apple/swift-argument-parser (0.81s)"[...]
29-
XCTAssertNotNil(Parser.progress.parse(&input))
29+
var input = "Updated https://github.com/apple/swift-argument-parser (0.81s)\n"[...]
30+
XCTAssertNotNil(Parser.progressLine.parse(&input))
3031
XCTAssertEqual(input, "")
3132
}
3233
do {
33-
var input = "Computing version for https://github.com/pointfreeco/swift-parsing"[...]
34-
XCTAssertNotNil(Parser.progress.parse(&input))
34+
var input = "Computing version for https://github.com/pointfreeco/swift-parsing\n"[...]
35+
XCTAssertNotNil(Parser.progressLine.parse(&input))
3536
XCTAssertEqual(input, "")
3637
}
3738
do {
38-
var input = "Computed https://github.com/pointfreeco/swift-parsing at 0.4.1 (0.02s)"[...]
39-
XCTAssertNotNil(Parser.progress.parse(&input))
39+
var input = "Computed https://github.com/pointfreeco/swift-parsing at 0.4.1 (0.02s)\n"[...]
40+
XCTAssertNotNil(Parser.progressLine.parse(&input))
4041
XCTAssertEqual(input, "")
4142
}
4243
do {
43-
var input = "Creating working copy for https://github.com/JohnSundell/Plot.git"[...]
44-
XCTAssertNotNil(Parser.progress.parse(&input))
44+
var input = "Creating working copy for https://github.com/JohnSundell/Plot.git\n"[...]
45+
XCTAssertNotNil(Parser.progressLine.parse(&input))
4546
XCTAssertEqual(input, "")
4647
}
4748
do {
48-
var input = "Working copy of https://github.com/JohnSundell/Plot.git resolved at 0.10.0"[...]
49-
XCTAssertNotNil(Parser.progress.parse(&input))
49+
var input = "Working copy of https://github.com/JohnSundell/Plot.git resolved at 0.10.0\n"[...]
50+
XCTAssertNotNil(Parser.progressLine.parse(&input))
5051
XCTAssertEqual(input, "")
5152
}
5253
}
@@ -67,8 +68,9 @@ final class ParserCoreTests: XCTestCase {
6768
Computed https://github.com/apple/swift-argument-parser at 1.0.2 (0.01s)
6869
Creating working copy for https://github.com/JohnSundell/Plot.git
6970
Working copy of https://github.com/JohnSundell/Plot.git resolved at 0.10.0
71+
7072
"""[...]
71-
XCTAssertNotNil(Parser.anyProgress.parse(&input))
73+
XCTAssertNotNil(Skip(Parser.progress).parse(&input))
7274
XCTAssertEqual(input, "")
7375
}
7476

@@ -300,4 +302,16 @@ final class ParserCoreTests: XCTestCase {
300302
XCTAssertEqual(Parser.packageUpdate.parse(&input)?.count, 6)
301303
}
302304

305+
func test_progress_resilience() throws {
306+
// Ensure random output before the dependency count line is ignored
307+
var input = """
308+
foo
309+
bar
310+
~ something
311+
1 dependency has changed:
312+
~ fluent-postgres-driver 2.2.2 -> fluent-postgres-driver 2.2.3
313+
"""[...]
314+
XCTAssertEqual(Parser.packageUpdate.parse(&input)?.count, 1)
315+
}
316+
303317
}

0 commit comments

Comments
 (0)