Skip to content

Commit 8c8fcd0

Browse files
authored
Merge pull request #585 from ahoppen/ahoppen/no-optionalcollection-nodes
Update for the fact that syntax collections are always non-optional in SwiftSyntax now
2 parents 178ff52 + d81e987 commit 8c8fcd0

12 files changed

+92
-94
lines changed

Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
274274
// Prioritize keeping "<modifiers> macro <name>(" together. Also include the ")" if the
275275
// parameter list is empty.
276276
let firstTokenAfterAttributes =
277-
node.modifiers?.firstToken(viewMode: .sourceAccurate) ?? node.macroKeyword
277+
node.modifiers.firstToken(viewMode: .sourceAccurate) ?? node.macroKeyword
278278
before(firstTokenAfterAttributes, tokens: .open)
279279
after(node.macroKeyword, tokens: .break)
280280
if hasArguments || node.genericParameterClause != nil {
@@ -352,7 +352,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
352352

353353
// Prioritize keeping "<modifiers> func <name>(" together. Also include the ")" if the parameter
354354
// list is empty.
355-
let firstTokenAfterAttributes = node.modifiers?.firstToken(viewMode: .sourceAccurate) ?? node.funcKeyword
355+
let firstTokenAfterAttributes = node.modifiers.firstToken(viewMode: .sourceAccurate) ?? node.funcKeyword
356356
before(firstTokenAfterAttributes, tokens: .open)
357357
after(node.funcKeyword, tokens: .break)
358358
if hasArguments || node.genericParameterClause != nil {
@@ -392,7 +392,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
392392
arrangeParameterClause(node.signature.parameterClause, forcesBreakBeforeRightParen: node.body != nil)
393393

394394
// Prioritize keeping "<modifiers> init<punctuation>" together.
395-
let firstTokenAfterAttributes = node.modifiers?.firstToken(viewMode: .sourceAccurate) ?? node.initKeyword
395+
let firstTokenAfterAttributes = node.modifiers.firstToken(viewMode: .sourceAccurate) ?? node.initKeyword
396396
before(firstTokenAfterAttributes, tokens: .open)
397397

398398
if hasArguments || node.genericParameterClause != nil {
@@ -427,7 +427,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
427427
before(node.firstToken(viewMode: .sourceAccurate), tokens: .open)
428428

429429
// Prioritize keeping "<modifiers> subscript" together.
430-
if let firstModifierToken = node.modifiers?.firstToken(viewMode: .sourceAccurate) {
430+
if let firstModifierToken = node.modifiers.firstToken(viewMode: .sourceAccurate) {
431431
before(firstModifierToken, tokens: .open)
432432

433433
if hasArguments || node.genericParameterClause != nil {
@@ -700,18 +700,16 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
700700
? Token.break(.same, newlines: .soft) : Token.space
701701
before(node.catchKeyword, tokens: catchPrecedingBreak)
702702

703-
if let catchItems = node.catchItems {
704-
// If there are multiple items in the `catch` clause, wrap each in open/close breaks so that
705-
// their internal breaks stack correctly. Otherwise, if there is only a single clause, use the
706-
// old (pre-SE-0276) behavior (a fixed space after the `catch` keyword).
707-
if catchItems.count > 1 {
708-
for catchItem in catchItems {
709-
before(catchItem.firstToken(viewMode: .sourceAccurate), tokens: .break(.open(kind: .continuation)))
710-
after(catchItem.lastToken(viewMode: .sourceAccurate), tokens: .break(.close(mustBreak: false), size: 0))
711-
}
712-
} else {
713-
before(node.catchItems?.firstToken(viewMode: .sourceAccurate), tokens: .space)
703+
// If there are multiple items in the `catch` clause, wrap each in open/close breaks so that
704+
// their internal breaks stack correctly. Otherwise, if there is only a single clause, use the
705+
// old (pre-SE-0276) behavior (a fixed space after the `catch` keyword).
706+
if node.catchItems.count > 1 {
707+
for catchItem in node.catchItems {
708+
before(catchItem.firstToken(viewMode: .sourceAccurate), tokens: .break(.open(kind: .continuation)))
709+
after(catchItem.lastToken(viewMode: .sourceAccurate), tokens: .break(.close(mustBreak: false), size: 0))
714710
}
711+
} else {
712+
before(node.catchItems.firstToken(viewMode: .sourceAccurate), tokens: .space)
715713
}
716714

717715
arrangeBracesAndContents(of: node.body, contentsKeyPath: \.statements)
@@ -1023,11 +1021,11 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
10231021
preVisitInsertingContextualBreaks(node)
10241022

10251023
// If there are multiple trailing closures, force all the closures in the call to break.
1026-
if let additionalTrailingClosures = node.additionalTrailingClosures {
1024+
if !node.additionalTrailingClosures.isEmpty {
10271025
if let closure = node.trailingClosure {
10281026
forcedBreakingClosures.insert(closure.id)
10291027
}
1030-
for additionalTrailingClosure in additionalTrailingClosures {
1028+
for additionalTrailingClosure in node.additionalTrailingClosures {
10311029
forcedBreakingClosures.insert(additionalTrailingClosure.closure.id)
10321030
}
10331031
}

Sources/SwiftFormatRules/AddModifierRewriter.swift

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -23,124 +23,136 @@ fileprivate final class AddModifierRewriter: SyntaxRewriter {
2323
override func visit(_ node: VariableDeclSyntax) -> DeclSyntax {
2424
// Check for modifiers, and, if none, insert the modifier and relocate trivia from the displaced
2525
// token.
26-
guard var modifiers = node.modifiers else {
26+
guard !node.modifiers.isEmpty else {
2727
let result = setOnlyModifier(in: node, keywordKeypath: \.bindingSpecifier)
2828
return DeclSyntax(result)
2929
}
30+
var node = node
31+
3032
// If variable already has an accessor keyword, skip (do not overwrite)
31-
guard modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
33+
guard node.modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
3234

3335
// Put accessor keyword before the first modifier keyword in the declaration
34-
modifiers.triviaPreservingInsert(modifierKeyword, at: modifiers.startIndex)
35-
return DeclSyntax(node.with(\.modifiers, modifiers))
36+
node.modifiers.triviaPreservingInsert(modifierKeyword, at: node.modifiers.startIndex)
37+
return DeclSyntax(node)
3638
}
3739

3840
override func visit(_ node: FunctionDeclSyntax) -> DeclSyntax {
3941
// Check for modifiers, and, if none, insert the modifier and relocate trivia from the displaced
4042
// token.
41-
guard var modifiers = node.modifiers else {
43+
guard !node.modifiers.isEmpty else {
4244
let result = setOnlyModifier(in: node, keywordKeypath: \.funcKeyword)
4345
return DeclSyntax(result)
4446
}
45-
guard modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
46-
modifiers.triviaPreservingInsert(modifierKeyword, at: modifiers.startIndex)
47-
return DeclSyntax(node.with(\.modifiers, modifiers))
47+
guard node.modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
48+
var node = node
49+
node.modifiers.triviaPreservingInsert(modifierKeyword, at: node.modifiers.startIndex)
50+
return DeclSyntax(node)
4851
}
4952

5053
override func visit(_ node: AssociatedTypeDeclSyntax) -> DeclSyntax {
5154
// Check for modifiers, and, if none, insert the modifier and relocate trivia from the displaced
5255
// token.
53-
guard var modifiers = node.modifiers else {
56+
guard !node.modifiers.isEmpty else {
5457
let result = setOnlyModifier(in: node, keywordKeypath: \.associatedtypeKeyword)
5558
return DeclSyntax(result)
5659
}
57-
guard modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
58-
modifiers.triviaPreservingInsert(modifierKeyword, at: modifiers.startIndex)
59-
return DeclSyntax(node.with(\.modifiers, modifiers))
60+
guard node.modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
61+
var node = node
62+
node.modifiers.triviaPreservingInsert(modifierKeyword, at: node.modifiers.startIndex)
63+
return DeclSyntax(node)
6064
}
6165

6266
override func visit(_ node: ClassDeclSyntax) -> DeclSyntax {
6367
// Check for modifiers, and, if none, insert the modifier and relocate trivia from the displaced
6468
// token.
65-
guard var modifiers = node.modifiers else {
69+
guard !node.modifiers.isEmpty else {
6670
let result = setOnlyModifier(in: node, keywordKeypath: \.classKeyword)
6771
return DeclSyntax(result)
6872
}
69-
guard modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
70-
modifiers.triviaPreservingInsert(modifierKeyword, at: modifiers.startIndex)
71-
return DeclSyntax(node.with(\.modifiers, modifiers))
73+
guard node.modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
74+
var node = node
75+
node.modifiers.triviaPreservingInsert(modifierKeyword, at: node.modifiers.startIndex)
76+
return DeclSyntax(node)
7277
}
7378

7479
override func visit(_ node: EnumDeclSyntax) -> DeclSyntax {
7580
// Check for modifiers, and, if none, insert the modifier and relocate trivia from the displaced
7681
// token.
77-
guard var modifiers = node.modifiers else {
82+
guard !node.modifiers.isEmpty else {
7883
let result = setOnlyModifier(in: node, keywordKeypath: \.enumKeyword)
7984
return DeclSyntax(result)
8085
}
81-
guard modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
82-
modifiers.triviaPreservingInsert(modifierKeyword, at: modifiers.startIndex)
83-
return DeclSyntax(node.with(\.modifiers, modifiers))
86+
guard node.modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
87+
var node = node
88+
node.modifiers.triviaPreservingInsert(modifierKeyword, at: node.modifiers.startIndex)
89+
return DeclSyntax(node)
8490
}
8591

8692
override func visit(_ node: ProtocolDeclSyntax) -> DeclSyntax {
8793
// Check for modifiers, and, if none, insert the modifier and relocate trivia from the displaced
8894
// token.
89-
guard var modifiers = node.modifiers else {
95+
96+
guard !node.modifiers.isEmpty else {
9097
let result = setOnlyModifier(in: node, keywordKeypath: \.protocolKeyword)
9198
return DeclSyntax(result)
9299
}
93-
guard modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
94-
modifiers.triviaPreservingInsert(modifierKeyword, at: modifiers.startIndex)
95-
return DeclSyntax(node.with(\.modifiers, modifiers))
100+
guard node.modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
101+
var node = node
102+
node.modifiers.triviaPreservingInsert(modifierKeyword, at: node.modifiers.startIndex)
103+
return DeclSyntax(node)
96104
}
97105

98106
override func visit(_ node: StructDeclSyntax) -> DeclSyntax {
99107
// Check for modifiers, and, if none, insert the modifier and relocate trivia from the displaced
100108
// token.
101-
guard var modifiers = node.modifiers else {
109+
guard !node.modifiers.isEmpty else {
102110
let result = setOnlyModifier(in: node, keywordKeypath: \.structKeyword)
103111
return DeclSyntax(result)
104112
}
105-
guard modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
106-
modifiers.triviaPreservingInsert(modifierKeyword, at: modifiers.startIndex)
107-
return DeclSyntax(node.with(\.modifiers, modifiers))
113+
guard node.modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
114+
var node = node
115+
node.modifiers.triviaPreservingInsert(modifierKeyword, at: node.modifiers.startIndex)
116+
return DeclSyntax(node)
108117
}
109118

110119
override func visit(_ node: TypeAliasDeclSyntax) -> DeclSyntax {
111120
// Check for modifiers, and, if none, insert the modifier and relocate trivia from the displaced
112121
// token.
113-
guard var modifiers = node.modifiers else {
122+
guard !node.modifiers.isEmpty else {
114123
let result = setOnlyModifier(in: node, keywordKeypath: \.typealiasKeyword)
115124
return DeclSyntax(result)
116125
}
117-
guard modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
118-
modifiers.triviaPreservingInsert(modifierKeyword, at: modifiers.startIndex)
119-
return DeclSyntax(node.with(\.modifiers, modifiers))
126+
guard node.modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
127+
var node = node
128+
node.modifiers.triviaPreservingInsert(modifierKeyword, at: node.modifiers.startIndex)
129+
return DeclSyntax(node)
120130
}
121131

122132
override func visit(_ node: InitializerDeclSyntax) -> DeclSyntax {
123133
// Check for modifiers, and, if none, insert the modifier and relocate trivia from the displaced
124134
// token.
125-
guard var modifiers = node.modifiers else {
135+
guard !node.modifiers.isEmpty else {
126136
let result = setOnlyModifier(in: node, keywordKeypath: \.initKeyword)
127137
return DeclSyntax(result)
128138
}
129-
guard modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
130-
modifiers.triviaPreservingInsert(modifierKeyword, at: modifiers.startIndex)
131-
return DeclSyntax(node.with(\.modifiers, modifiers))
139+
guard node.modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
140+
var node = node
141+
node.modifiers.triviaPreservingInsert(modifierKeyword, at: node.modifiers.startIndex)
142+
return DeclSyntax(node)
132143
}
133144

134145
override func visit(_ node: SubscriptDeclSyntax) -> DeclSyntax {
135146
// Check for modifiers, and, if none, insert the modifier and relocate trivia from the displaced
136147
// token.
137-
guard var modifiers = node.modifiers else {
148+
guard !node.modifiers.isEmpty else {
138149
let result = setOnlyModifier(in: node, keywordKeypath: \.subscriptKeyword)
139150
return DeclSyntax(result)
140151
}
141-
guard modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
142-
modifiers.triviaPreservingInsert(modifierKeyword, at: modifiers.startIndex)
143-
return DeclSyntax(node.with(\.modifiers, modifiers))
152+
guard node.modifiers.accessLevelModifier == nil else { return DeclSyntax(node) }
153+
var node = node
154+
node.modifiers.triviaPreservingInsert(modifierKeyword, at: node.modifiers.startIndex)
155+
return DeclSyntax(node)
144156
}
145157

146158
/// Moves trivia in the given node to correct the placement of potentially displaced trivia in the

Sources/SwiftFormatRules/AlwaysUseLowerCamelCase.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public final class AlwaysUseLowerCamelCase: SyntaxLintRule {
4646
// Don't diagnose any issues when the variable is overriding, because this declaration can't
4747
// rename the variable. If the user analyzes the code where the variable is really declared,
4848
// then the diagnostic can be raised for just that location.
49-
if let modifiers = node.modifiers, modifiers.has(modifier: "override") {
49+
if node.modifiers.has(modifier: "override") {
5050
return .visitChildren
5151
}
5252

@@ -114,7 +114,7 @@ public final class AlwaysUseLowerCamelCase: SyntaxLintRule {
114114
// Don't diagnose any issues when the function is overriding, because this declaration can't
115115
// rename the function. If the user analyzes the code where the function is really declared,
116116
// then the diagnostic can be raised for just that location.
117-
if let modifiers = node.modifiers, modifiers.has(modifier: "override") {
117+
if node.modifiers.has(modifier: "override") {
118118
return .visitChildren
119119
}
120120

Sources/SwiftFormatRules/AmbiguousTrailingClosureOverload.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public final class AmbiguousTrailingClosureOverload: SyntaxLintRule {
4242
let params = fn.signature.parameterClause.parameters
4343
guard let firstParam = params.firstAndOnly else { continue }
4444
guard firstParam.type.is(FunctionTypeSyntax.self) else { continue }
45-
if let mods = fn.modifiers, mods.has(modifier: "static") || mods.has(modifier: "class") {
45+
if fn.modifiers.has(modifier: "static") || fn.modifiers.has(modifier: "class") {
4646
staticOverloads[fn.name.text, default: []].append(fn)
4747
} else {
4848
overloads[fn.name.text, default: []].append(fn)

Sources/SwiftFormatRules/DontRepeatTypeInStaticProperties.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ public final class DontRepeatTypeInStaticProperties: SyntaxLintRule {
6969
for member in members {
7070
guard
7171
let varDecl = member.decl.as(VariableDeclSyntax.self),
72-
let modifiers = varDecl.modifiers,
73-
modifiers.has(modifier: "static") || modifiers.has(modifier: "class")
72+
varDecl.modifiers.has(modifier: "static") || varDecl.modifiers.has(modifier: "class")
7473
else { continue }
7574

7675
let bareTypeName = removingPossibleNamespacePrefix(from: typeName)

Sources/SwiftFormatRules/FileScopedDeclarationPrivacy.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public final class FileScopedDeclarationPrivacy: SyntaxFormatRule {
136136
private func rewrittenDecl<DeclType: DeclSyntaxProtocol>(
137137
_ decl: DeclType,
138138
modifiers: DeclModifierListSyntax?,
139-
factory: (DeclModifierListSyntax?) -> DeclType
139+
factory: (DeclModifierListSyntax) -> DeclType
140140
) -> DeclType {
141141
let invalidAccess: TokenKind
142142
let validAccess: TokenKind

Sources/SwiftFormatRules/FullyIndirectEnum.swift

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ public final class FullyIndirectEnum: SyntaxFormatRule {
2424

2525
public override func visit(_ node: EnumDeclSyntax) -> DeclSyntax {
2626
let enumMembers = node.memberBlock.members
27-
guard let enumModifiers = node.modifiers,
28-
!enumModifiers.has(modifier: "indirect"),
27+
guard !node.modifiers.has(modifier: "indirect"),
2928
allCasesAreIndirect(in: enumMembers)
3029
else {
3130
return DeclSyntax(node)
@@ -37,14 +36,13 @@ public final class FullyIndirectEnum: SyntaxFormatRule {
3736
let newMembers = enumMembers.map {
3837
(member: MemberBlockItemSyntax) -> MemberBlockItemSyntax in
3938
guard let caseMember = member.decl.as(EnumCaseDeclSyntax.self),
40-
let modifiers = caseMember.modifiers,
41-
modifiers.has(modifier: "indirect"),
42-
let firstModifier = modifiers.first
39+
caseMember.modifiers.has(modifier: "indirect"),
40+
let firstModifier = caseMember.modifiers.first
4341
else {
4442
return member
4543
}
4644

47-
let newCase = caseMember.with(\.modifiers, modifiers.remove(name: "indirect"))
45+
let newCase = caseMember.with(\.modifiers, caseMember.modifiers.remove(name: "indirect"))
4846
let formattedCase = rearrangeLeadingTrivia(firstModifier.leadingTrivia, on: newCase)
4947
return member.with(\.decl, DeclSyntax(formattedCase))
5048
}
@@ -70,7 +68,7 @@ public final class FullyIndirectEnum: SyntaxFormatRule {
7068
let newMemberBlock = node.memberBlock.with(\.members, MemberBlockItemListSyntax(newMembers))
7169
return DeclSyntax(
7270
newEnumDecl
73-
.with(\.modifiers, (newEnumDecl.modifiers ?? DeclModifierListSyntax([])) + [newModifier])
71+
.with(\.modifiers, newEnumDecl.modifiers + [newModifier])
7472
.with(\.memberBlock, newMemberBlock))
7573
}
7674

@@ -82,7 +80,7 @@ public final class FullyIndirectEnum: SyntaxFormatRule {
8280
for member in members {
8381
if let caseMember = member.decl.as(EnumCaseDeclSyntax.self) {
8482
hadCases = true
85-
guard let modifiers = caseMember.modifiers, modifiers.has(modifier: "indirect") else {
83+
guard caseMember.modifiers.has(modifier: "indirect") else {
8684
return false
8785
}
8886
}
@@ -97,11 +95,11 @@ public final class FullyIndirectEnum: SyntaxFormatRule {
9795
) -> EnumCaseDeclSyntax {
9896
var formattedCase = enumCaseDecl
9997

100-
if var modifiers = formattedCase.modifiers, var firstModifier = modifiers.first {
98+
if var firstModifier = formattedCase.modifiers.first {
10199
// If the case has modifiers, attach the leading trivia to the first one.
102100
firstModifier.leadingTrivia = leadingTrivia
103-
modifiers[modifiers.startIndex] = firstModifier
104-
formattedCase.modifiers = modifiers
101+
formattedCase.modifiers[formattedCase.modifiers.startIndex] = firstModifier
102+
formattedCase.modifiers = formattedCase.modifiers
105103
} else {
106104
// Otherwise, attach the trivia to the `case` keyword itself.
107105
formattedCase.caseKeyword.leadingTrivia = leadingTrivia

Sources/SwiftFormatRules/NeverUseImplicitlyUnwrappedOptionals.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,9 @@ public final class NeverUseImplicitlyUnwrappedOptionals: SyntaxLintRule {
4040
public override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind {
4141
guard context.importsXCTest == .doesNotImportXCTest else { return .skipChildren }
4242
// Ignores IBOutlet variables
43-
if let attributes = node.attributes {
44-
for attribute in attributes {
45-
if (attribute.as(AttributeSyntax.self))?.attributeName.as(IdentifierTypeSyntax.self)?.name.text == "IBOutlet" {
46-
return .skipChildren
47-
}
43+
for attribute in node.attributes {
44+
if (attribute.as(AttributeSyntax.self))?.attributeName.as(IdentifierTypeSyntax.self)?.name.text == "IBOutlet" {
45+
return .skipChildren
4846
}
4947
}
5048
// Finds type annotation for variable(s)

0 commit comments

Comments
 (0)