@@ -116,6 +116,30 @@ fileprivate extension Array where Element: Hashable, Element: Comparable {
116
116
}
117
117
}
118
118
119
+ extension LayoutNode {
120
+ /// True if `self` satisfies all of the requirements of `trait`, regardless
121
+ /// of whether it actually declares conformance to it.
122
+ func canConform( to trait: Trait ) -> Bool {
123
+ if let traitBaseKind = trait. baseKind {
124
+ guard traitBaseKind == self . base else {
125
+ return false
126
+ }
127
+ }
128
+
129
+ return trait. children. allSatisfy { traitChild in
130
+ self . children. contains { nodeChild in
131
+ traitChild. hasSameType ( as: nodeChild)
132
+ }
133
+ }
134
+ }
135
+
136
+ /// True if `self` declares conformance to `trait`, regardless of whether
137
+ /// it satisfies the trait's requirements.
138
+ func conforms( to trait: Trait ) -> Bool {
139
+ self . traits. contains ( trait. traitName)
140
+ }
141
+ }
142
+
119
143
class ValidateSyntaxNodes : XCTestCase {
120
144
/// All nodes with base kind e.g. `ExprSyntax` should end with `ExprSyntax`.
121
145
func testBaseKindSuffix( ) {
@@ -514,12 +538,7 @@ class ValidateSyntaxNodes: XCTestCase {
514
538
515
539
for node in SYNTAX_NODES . compactMap ( \. layoutNode) {
516
540
for trait in TRAITS {
517
- let canConformToTrait = trait. children. allSatisfy { traitChild in
518
- node. children. contains { nodeChild in
519
- traitChild. hasSameType ( as: nodeChild)
520
- }
521
- }
522
- if canConformToTrait && !node. traits. contains ( trait. traitName) {
541
+ if node. canConform ( to: trait) && !node. conforms ( to: trait) {
523
542
failures. append (
524
543
ValidationFailure (
525
544
node: node. kind,
@@ -533,7 +552,6 @@ class ValidateSyntaxNodes: XCTestCase {
533
552
assertFailuresMatchXFails (
534
553
failures,
535
554
expectedFailures: [
536
- ValidationFailure ( node: . accessorParameters, message: " could conform to trait 'NamedDecl' but does not " ) ,
537
555
ValidationFailure ( node: . availabilityCondition, message: " could conform to trait 'Parenthesized' but does not " ) ,
538
556
ValidationFailure ( node: . _canImportExpr, message: " could conform to trait 'Parenthesized' but does not " ) ,
539
557
ValidationFailure (
@@ -542,10 +560,6 @@ class ValidateSyntaxNodes: XCTestCase {
542
560
) ,
543
561
ValidationFailure ( node: . editorPlaceholderDecl, message: " could conform to trait 'MissingNode' but does not " ) ,
544
562
ValidationFailure ( node: . editorPlaceholderExpr, message: " could conform to trait 'MissingNode' but does not " ) ,
545
- ValidationFailure ( node: . enumCaseElement, message: " could conform to trait 'NamedDecl' but does not " ) ,
546
- ValidationFailure ( node: . genericParameter, message: " could conform to trait 'NamedDecl' but does not " ) ,
547
- ValidationFailure ( node: . precedenceGroupName, message: " could conform to trait 'NamedDecl' but does not " ) ,
548
- ValidationFailure ( node: . primaryAssociatedType, message: " could conform to trait 'NamedDecl' but does not " ) ,
549
563
ValidationFailure (
550
564
node: . yieldedExpressionsClause,
551
565
message: " could conform to trait 'Parenthesized' but does not "
0 commit comments