Skip to content

Commit f070daa

Browse files
Ensures wrapped VFL extents are parsed correctly (#20)
1 parent 28df2fc commit f070daa

File tree

4 files changed

+138
-12
lines changed

4 files changed

+138
-12
lines changed

Sources/App/Parsing/ConstraintsParser+AutoLayoutPrimitives.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ extension ConstraintsParser {
2323

2424
static let number = numberString.map(parseDouble)
2525
.named("number")
26+
27+
static let spacing = number.otherwise(spacedNumber)
28+
29+
static let defaultedRelation = optional(relation).map { $0 ?? .equal }
30+
31+
static let extent = defaultedRelation.then(spacing)
2632
}
2733

2834
private extension ConstraintsParser {
@@ -35,6 +41,10 @@ private extension ConstraintsParser {
3541
static let decimal = signedInteger.then(optional(postDecimal)).map { "\($0)\($1 ?? "")" }
3642
static let numberString = decimal.then(optional(exponent)).map { "\($0)\($1 ?? "")" }
3743

44+
static let spacingTerm = string("NSSpace")
45+
.otherwise(string("NSLayoutAnchorConstraintSpace"))
46+
static let spacedNumber = spacingTerm.skipThen(string("(")).skipThen(number).thenSkip(")")
47+
3848
static func parserForAttribute(_ attribute: Attribute) -> Parser<Attribute> {
3949
let attributeParser = attribute.labels.reduce(pureError(), { string($1).otherwise($0) })
4050
return attributeParser.map { _ in return attribute }

Sources/App/Parsing/ConstraintsParser+EquationConstraint.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ extension ConstraintsParser {
2424
private extension ConstraintsParser {
2525

2626
static let layoutItemAttribute = partialInstance.then(dotAttribute)
27-
static let anyConstant = nsSpaceConstant.otherwise(constant)
27+
static let anyConstant = extent.map { Constant($1) }.otherwise(constant)
2828
static let constant = number.map(Constant.init).otherwise(pure(Constant()))
29-
static let nsSpaceConstant = unbracketedNSSpace.map { Constant($0.1) }
3029
static let preMultiplier = optional(number.thenSkip(string("*")).map(Multiplier.init))
3130
.named("prefixed multiplier")
3231
static let postMultiplier = optional(string("*").skipThen(wss).skipThen(number).map(Multiplier.init))

Sources/App/Parsing/ConstraintsParser+VFLConstraint.swift

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,14 @@ import Sparse
66

77
extension ConstraintsParser {
88

9-
static let vflSpaceConstraint = vflAxis.then(vflBoundedEntity).thenSkip(dash).then(spacer).thenSkip(dash).then(vflBoundedEntity).thenSkip(vflDirection).then(optionalInfo)
9+
static let vflSpaceConstraint = vflAxis.then(vflBoundedEntity).thenSkip(dash).then(vflExtent).thenSkip(dash).then(vflBoundedEntity).thenSkip(vflDirection).then(optionalInfo)
1010
.map(flatten).map(AnonymousConstraint.init)
1111

1212
static let vflExtentConstraint = vflAxis.thenSkip(character("[")).then(vflEntity).then(vflExtent).thenSkip(character("]")).thenSkip(vflDirection).then(optionalInfo)
1313
.map(flatten).map(AnonymousConstraint.init)
1414

1515
static let vflConstraint = vflExtentConstraint.otherwise(vflSpaceConstraint)
16-
17-
static let unbracketedNSSpace = string("NSSpace")
18-
.otherwise(string("NSLayoutAnchorConstraintSpace"))
19-
.skipThen(vflExtent)
20-
21-
static let nsSpacer = character("(").skipThen(unbracketedNSSpace).thenSkip(character(")"))
16+
static let vflExtent = character("(").skipThen(extent).thenSkip(character(")"))
2217
}
2318

2419
// MARK: - Private
@@ -29,12 +24,9 @@ private extension ConstraintsParser {
2924
static let vAxis = character("V").map { _ in Attribute.Axis.vertical }
3025
static let superview = character("|")
3126
static let vflAxis = hAxis.otherwise(vAxis).thenSkip(colon)
32-
static let vflRelation = optional(relation).map { $0 ?? .equal }
33-
static let vflExtent = character("(").skipThen(vflRelation).then(number).thenSkip(character(")"))
3427
static let vflIdentifierCharacter = characterNot(in: "[]|()")
3528
static let vflIdentifier = many(identifierCharacter.and(vflIdentifierCharacter)).asString()
3629
static let vflEntity = instance.map({ PartialInstance.instance($0) }).otherwise(vflIdentifier.map({ PartialInstance.identifier($0) }))
3730
static let vflBoundedEntity = character("[").skipThen(vflEntity).thenSkip(character("]")).otherwise(string("|").map({ _ in PartialInstance.superview }))
3831
static let vflDirection = optional(string("(LTR)").otherwise(string("(RTL)")))
39-
static let spacer = vflExtent.otherwise(nsSpacer)
4032
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
{
2+
"constraints" : [
3+
{
4+
"constant" : {
5+
"prefix" : "+ ",
6+
"value" : "8"
7+
},
8+
"description" : "<code style=\"box-shadow: 0px -1px 0px #F39C12 inset; padding-bottom: 1px;\">Label<\/code>'s top edge should be at least <code style=\"box-shadow: 0px -1px 0px #C0392B inset; padding-bottom: 1px;\">ClassName<\/code>'s top edge plus 8.",
9+
"first" : {
10+
"attribute" : {
11+
"includesMargin" : false,
12+
"name" : "top"
13+
},
14+
"instance" : {
15+
"address" : "0x111b35c20",
16+
"className" : "UILabel",
17+
"color" : "rgb(243,156,18)",
18+
"initial" : "L",
19+
"name" : "Label",
20+
"suffix" : ""
21+
}
22+
},
23+
"identity" : {
24+
"address" : "0x2828051d0",
25+
"className" : "_UISystemBaselineConstraint",
26+
"color" : "rgb(26,188,156)",
27+
"initial" : "U",
28+
"name" : "_UISystemBaselineConstraint"
29+
},
30+
"relation" : ">=",
31+
"second" : {
32+
"attribute" : {
33+
"includesMargin" : false,
34+
"name" : "top"
35+
},
36+
"instance" : {
37+
"address" : "0x111b35a60",
38+
"className" : "ModuleName.ClassName",
39+
"color" : "rgb(192,57,43)",
40+
"initial" : "C",
41+
"name" : "ClassName",
42+
"suffix" : ""
43+
}
44+
}
45+
},
46+
{
47+
"description" : "<code style=\"box-shadow: 0px -1px 0px #F39C12 inset; padding-bottom: 1px;\">Label<\/code>'s vertical center should equal <code style=\"box-shadow: 0px -1px 0px #C0392B inset; padding-bottom: 1px;\">ClassName<\/code>'s vertical center.",
48+
"first" : {
49+
"attribute" : {
50+
"includesMargin" : false,
51+
"name" : "centerY"
52+
},
53+
"instance" : {
54+
"address" : "0x111b35c20",
55+
"className" : "UILabel",
56+
"color" : "rgb(243,156,18)",
57+
"initial" : "L",
58+
"name" : "Label",
59+
"suffix" : ""
60+
}
61+
},
62+
"identity" : {
63+
"address" : "0x282805130",
64+
"className" : "NSLayoutConstraint",
65+
"color" : "rgb(26,188,156)",
66+
"initial" : "N",
67+
"name" : "NSLayoutConstraint"
68+
},
69+
"relation" : "==",
70+
"second" : {
71+
"attribute" : {
72+
"includesMargin" : false,
73+
"name" : "centerY"
74+
},
75+
"instance" : {
76+
"address" : "0x111b35a60",
77+
"className" : "ModuleName.ClassName",
78+
"color" : "rgb(192,57,43)",
79+
"initial" : "C",
80+
"name" : "ClassName",
81+
"suffix" : ""
82+
}
83+
}
84+
},
85+
{
86+
"constant" : {
87+
"value" : "0"
88+
},
89+
"description" : "<code style=\"box-shadow: 0px -1px 0px #C0392B inset; padding-bottom: 1px;\">ClassName<\/code>'s height should equal 0.",
90+
"first" : {
91+
"attribute" : {
92+
"includesMargin" : false,
93+
"name" : "height"
94+
},
95+
"instance" : {
96+
"address" : "0x111b35a60",
97+
"className" : "ModuleName.ClassName",
98+
"color" : "rgb(192,57,43)",
99+
"initial" : "C",
100+
"name" : "ClassName",
101+
"suffix" : ""
102+
}
103+
},
104+
"footnote" : {
105+
"marker" : "",
106+
"text" : "This constraint was added by a table or collection view to enforce its cell size."
107+
},
108+
"identity" : {
109+
"address" : "0x282803ed0",
110+
"className" : "NSLayoutConstraint",
111+
"color" : "rgb(26,188,156)",
112+
"identifier" : "UIView-Encapsulated-Layout-Height",
113+
"initial" : "U",
114+
"name" : "UIView-Encapsulated-Layout-Height"
115+
},
116+
"relation" : "=="
117+
}
118+
],
119+
"footnotes" : [
120+
{
121+
"marker" : "",
122+
"text" : "This constraint was added by a table or collection view to enforce its cell size."
123+
}
124+
]
125+
}

0 commit comments

Comments
 (0)