@@ -116,6 +116,30 @@ fileprivate extension Array where Element: Hashable, Element: Comparable {
116116 }
117117}
118118
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+
119143class ValidateSyntaxNodes : XCTestCase {
120144 /// All nodes with base kind e.g. `ExprSyntax` should end with `ExprSyntax`.
121145 func testBaseKindSuffix( ) {
@@ -514,12 +538,7 @@ class ValidateSyntaxNodes: XCTestCase {
514538
515539 for node in SYNTAX_NODES . compactMap ( \. layoutNode) {
516540 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) {
523542 failures. append (
524543 ValidationFailure (
525544 node: node. kind,
@@ -533,7 +552,6 @@ class ValidateSyntaxNodes: XCTestCase {
533552 assertFailuresMatchXFails (
534553 failures,
535554 expectedFailures: [
536- ValidationFailure ( node: . accessorParameters, message: " could conform to trait 'NamedDecl' but does not " ) ,
537555 ValidationFailure ( node: . availabilityCondition, message: " could conform to trait 'Parenthesized' but does not " ) ,
538556 ValidationFailure ( node: . _canImportExpr, message: " could conform to trait 'Parenthesized' but does not " ) ,
539557 ValidationFailure (
@@ -542,10 +560,6 @@ class ValidateSyntaxNodes: XCTestCase {
542560 ) ,
543561 ValidationFailure ( node: . editorPlaceholderDecl, message: " could conform to trait 'MissingNode' but does not " ) ,
544562 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 " ) ,
549563 ValidationFailure (
550564 node: . yieldedExpressionsClause,
551565 message: " could conform to trait 'Parenthesized' but does not "
0 commit comments