Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.10] Add fixes that were present in 509.0.0 but not release/5.10 #704

Merged
merged 19 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8cf405a
Add option to disable trailing commas on multi-line collections
mlavergn Sep 6, 2023
f4dec43
- adopt PR recommendations
mlavergn Sep 7, 2023
c3a1a58
- PR setting renamed to multiElementCollectionTrailingCommas and use …
mlavergn Sep 9, 2023
9c66722
- PR add DocC header for configuration setting
mlavergn Sep 10, 2023
7a4e19a
[Format/Lint] Add a rule to detect and transform `[<Type>]()` into l…
xedin Sep 6, 2023
b2250fd
Make AlwaysUseLiteralForEmptyArrayInit rule opt-in and disabled by de…
xedin Sep 6, 2023
906b0a3
[Lint/Format] Extend empty literal initialization rule to support dic…
xedin Sep 8, 2023
beb6bf8
[Lint/Format] Rename `AlwaysUseLiteralForEmptyArrayInit` into `Always…
xedin Sep 8, 2023
af3b5a0
[Lint/Format] Extend empty literal rewritting rule to support paramet…
xedin Sep 8, 2023
2998a21
[Tests] Add a few tests to make sure that empty collection init rule …
xedin Sep 14, 2023
b5a0cf8
Format parameter packs.
allevato Sep 14, 2023
a1c54e6
Format `consume` expressions.
allevato Sep 14, 2023
2c01ad9
Format `discard` statements.
allevato Sep 14, 2023
13e5246
Format `copy` expressions.
allevato Sep 14, 2023
fb710fd
Remove a warning from `AlwaysUseLiteralForEmptyCollectionInit`.
allevato Sep 14, 2023
a061657
Support `package` access in `NoAccessLevelOnExtensionDeclaration`.
allevato Sep 14, 2023
949b0d0
Fix multi-line string wrapping in `@available` attributes.
allevato Oct 19, 2023
4bdbb28
[UseShorthandTypeNames] Fix shorthand for optional attributed types.
allevato Nov 20, 2023
317185c
Change swift-syntax dependency to 'release/5.10'
ahoppen Mar 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Documentation/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ top-level keys and values:
* `spacesAroundRangeFormationOperators` _(boolean)_: Determines whether whitespace should be forced
before and after the range formation operators `...` and `..<`.

* `multiElementCollectionTrailingCommas` _(boolean)_: Determines whether multi-element collection literals should have trailing commas.
Defaults to `true`.

> TODO: Add support for enabling/disabling specific syntax transformations in
> the pipeline.

Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil {
),
.package(
url: "https://github.com/apple/swift-syntax.git",
branch: "main"
branch: "release/5.10"
),
]
} else {
Expand Down
1 change: 1 addition & 0 deletions Sources/SwiftFormat/API/Configuration+Default.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ extension Configuration {
self.indentSwitchCaseLabels = false
self.spacesAroundRangeFormationOperators = false
self.noAssignmentInExpressions = NoAssignmentInExpressionsConfiguration()
self.multiElementCollectionTrailingCommas = true
}
}
29 changes: 29 additions & 0 deletions Sources/SwiftFormat/API/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public struct Configuration: Codable, Equatable {
case rules
case spacesAroundRangeFormationOperators
case noAssignmentInExpressions
case multiElementCollectionTrailingCommas
}

/// A dictionary containing the default enabled/disabled states of rules, keyed by the rules'
Expand Down Expand Up @@ -162,6 +163,29 @@ public struct Configuration: Codable, Equatable {
/// Contains exceptions for the `NoAssignmentInExpressions` rule.
public var noAssignmentInExpressions: NoAssignmentInExpressionsConfiguration

/// Determines if multi-element collection literals should have trailing commas.
///
/// When `true` (default), the correct form is:
/// ```swift
/// let MyCollection = [1, 2,]
/// ...
/// let MyCollection = [
/// "a": 1,
/// "b": 2,
/// ]
/// ```
///
/// When `false`, the correct form is:
/// ```swift
/// let MyCollection = [1, 2]
/// ...
/// let MyCollection = [
/// "a": 1,
/// "b": 2
/// ]
/// ```
public var multiElementCollectionTrailingCommas: Bool

/// Constructs a Configuration by loading it from a configuration file.
public init(contentsOf url: URL) throws {
let data = try Data(contentsOf: url)
Expand Down Expand Up @@ -239,6 +263,10 @@ public struct Configuration: Codable, Equatable {
try container.decodeIfPresent(
NoAssignmentInExpressionsConfiguration.self, forKey: .noAssignmentInExpressions)
?? defaults.noAssignmentInExpressions
self.multiElementCollectionTrailingCommas =
try container.decodeIfPresent(
Bool.self, forKey: .multiElementCollectionTrailingCommas)
?? defaults.multiElementCollectionTrailingCommas

// If the `rules` key is not present at all, default it to the built-in set
// so that the behavior is the same as if the configuration had been
Expand Down Expand Up @@ -271,6 +299,7 @@ public struct Configuration: Codable, Equatable {
try container.encode(fileScopedDeclarationPrivacy, forKey: .fileScopedDeclarationPrivacy)
try container.encode(indentSwitchCaseLabels, forKey: .indentSwitchCaseLabels)
try container.encode(noAssignmentInExpressions, forKey: .noAssignmentInExpressions)
try container.encode(multiElementCollectionTrailingCommas, forKey: .multiElementCollectionTrailingCommas)
try container.encode(rules, forKey: .rules)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ extension DeclModifierListSyntax {
var accessLevelModifier: DeclModifierSyntax? {
for modifier in self {
switch modifier.name.tokenKind {
case .keyword(.public), .keyword(.private), .keyword(.fileprivate), .keyword(.internal):
case .keyword(.public), .keyword(.private), .keyword(.fileprivate), .keyword(.internal),
.keyword(.package):
return modifier
default:
continue
Expand Down
3 changes: 3 additions & 0 deletions Sources/SwiftFormat/Core/Pipelines+Generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ class LintPipeline: SyntaxVisitor {
}

override func visit(_ node: FunctionParameterSyntax) -> SyntaxVisitorContinueKind {
visitIfEnabled(AlwaysUseLiteralForEmptyCollectionInit.visit, for: node)
visitIfEnabled(NoLeadingUnderscores.visit, for: node)
return .visitChildren
}
Expand Down Expand Up @@ -243,6 +244,7 @@ class LintPipeline: SyntaxVisitor {
}

override func visit(_ node: PatternBindingSyntax) -> SyntaxVisitorContinueKind {
visitIfEnabled(AlwaysUseLiteralForEmptyCollectionInit.visit, for: node)
visitIfEnabled(OmitExplicitReturns.visit, for: node)
visitIfEnabled(UseSingleLinePropertyGetter.visit, for: node)
return .visitChildren
Expand Down Expand Up @@ -356,6 +358,7 @@ extension FormatPipeline {

func rewrite(_ node: Syntax) -> Syntax {
var node = node
node = AlwaysUseLiteralForEmptyCollectionInit(context: context).rewrite(node)
node = DoNotUseSemicolons(context: context).rewrite(node)
node = FileScopedDeclarationPrivacy(context: context).rewrite(node)
node = FullyIndirectEnum(context: context).rewrite(node)
Expand Down
1 change: 1 addition & 0 deletions Sources/SwiftFormat/Core/RuleNameCache+Generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
@_spi(Testing)
public let ruleNameCache: [ObjectIdentifier: String] = [
ObjectIdentifier(AllPublicDeclarationsHaveDocumentation.self): "AllPublicDeclarationsHaveDocumentation",
ObjectIdentifier(AlwaysUseLiteralForEmptyCollectionInit.self): "AlwaysUseLiteralForEmptyCollectionInit",
ObjectIdentifier(AlwaysUseLowerCamelCase.self): "AlwaysUseLowerCamelCase",
ObjectIdentifier(AmbiguousTrailingClosureOverload.self): "AmbiguousTrailingClosureOverload",
ObjectIdentifier(BeginDocumentationCommentWithOneLineSummary.self): "BeginDocumentationCommentWithOneLineSummary",
Expand Down
1 change: 1 addition & 0 deletions Sources/SwiftFormat/Core/RuleRegistry+Generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
@_spi(Internal) public enum RuleRegistry {
public static let rules: [String: Bool] = [
"AllPublicDeclarationsHaveDocumentation": false,
"AlwaysUseLiteralForEmptyCollectionInit": false,
"AlwaysUseLowerCamelCase": true,
"AmbiguousTrailingClosureOverload": true,
"BeginDocumentationCommentWithOneLineSummary": false,
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftFormat/PrettyPrint/PrettyPrint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ public class PrettyPrinter {
// We never want to add a trailing comma in an initializer so we disable trailing commas on
// single element collections.
let shouldHaveTrailingComma =
startLineNumber != openCloseBreakCompensatingLineNumber && !isSingleElement
startLineNumber != openCloseBreakCompensatingLineNumber && !isSingleElement && configuration.multiElementCollectionTrailingCommas
if shouldHaveTrailingComma && !hasTrailingComma {
diagnose(.addTrailingComma, category: .trailingComma)
} else if !shouldHaveTrailingComma && hasTrailingComma {
Expand Down
73 changes: 71 additions & 2 deletions Sources/SwiftFormat/PrettyPrint/TokenStreamCreator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1799,8 +1799,23 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {

override func visit(_ node: AvailabilityLabeledArgumentSyntax) -> SyntaxVisitorContinueKind {
before(node.label, tokens: .open)
after(node.colon, tokens: .break(.continue, newlines: .elective(ignoresDiscretionary: true)))
after(node.value.lastToken(viewMode: .sourceAccurate), tokens: .close)

let tokensAfterColon: [Token]
let endTokens: [Token]

if case .string(let string) = node.value,
string.openingQuote.tokenKind == .multilineStringQuote
{
tokensAfterColon =
[.break(.open(kind: .block), newlines: .elective(ignoresDiscretionary: true))]
endTokens = [.break(.close(mustBreak: false), size: 0), .close]
} else {
tokensAfterColon = [.break(.continue, newlines: .elective(ignoresDiscretionary: true))]
endTokens = [.close]
}

after(node.colon, tokens: tokensAfterColon)
after(node.value.lastToken(viewMode: .sourceAccurate), tokens: endTokens)
return .visitChildren
}

Expand Down Expand Up @@ -2293,6 +2308,7 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {

override func visit(_ node: GenericParameterSyntax) -> SyntaxVisitorContinueKind {
before(node.firstToken(viewMode: .sourceAccurate), tokens: .open)
after(node.eachKeyword, tokens: .break)
after(node.colon, tokens: .break)
if let trailingComma = node.trailingComma {
after(trailingComma, tokens: .close, .break(.same))
Expand All @@ -2312,6 +2328,28 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
return .visitChildren
}

override func visit(_ node: PackElementExprSyntax) -> SyntaxVisitorContinueKind {
// `each` cannot be separated from the following token, or it is parsed as an identifier itself.
after(node.eachKeyword, tokens: .space)
return .visitChildren
}

override func visit(_ node: PackElementTypeSyntax) -> SyntaxVisitorContinueKind {
// `each` cannot be separated from the following token, or it is parsed as an identifier itself.
after(node.eachKeyword, tokens: .space)
return .visitChildren
}

override func visit(_ node: PackExpansionExprSyntax) -> SyntaxVisitorContinueKind {
after(node.repeatKeyword, tokens: .break)
return .visitChildren
}

override func visit(_ node: PackExpansionTypeSyntax) -> SyntaxVisitorContinueKind {
after(node.repeatKeyword, tokens: .break)
return .visitChildren
}

override func visit(_ node: ExpressionPatternSyntax) -> SyntaxVisitorContinueKind {
return .visitChildren
}
Expand Down Expand Up @@ -2353,6 +2391,16 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
return .visitChildren
}

override func visit(_ node: SimpleStringLiteralExprSyntax) -> SyntaxVisitorContinueKind {
if node.openingQuote.tokenKind == .multilineStringQuote {
after(node.openingQuote, tokens: .break(.same, size: 0, newlines: .hard(count: 1)))
if !node.segments.isEmpty {
before(node.closingQuote, tokens: .break(.same, newlines: .hard(count: 1)))
}
}
return .visitChildren
}

override func visit(_ node: StringSegmentSyntax) -> SyntaxVisitorContinueKind {
// Looks up the correct break kind based on prior context.
func breakKind() -> BreakKind {
Expand Down Expand Up @@ -2481,6 +2529,27 @@ fileprivate final class TokenStreamCreator: SyntaxVisitor {
return .visitChildren
}

override func visit(_ node: ConsumeExprSyntax) -> SyntaxVisitorContinueKind {
// The `consume` keyword cannot be separated from the following token or it will be parsed as
// an identifier.
after(node.consumeKeyword, tokens: .space)
return .visitChildren
}

override func visit(_ node: CopyExprSyntax) -> SyntaxVisitorContinueKind {
// The `copy` keyword cannot be separated from the following token or it will be parsed as an
// identifier.
after(node.copyKeyword, tokens: .space)
return .visitChildren
}

override func visit(_ node: DiscardStmtSyntax) -> SyntaxVisitorContinueKind {
// The `discard` keyword cannot be separated from the following token or it will be parsed as
// an identifier.
after(node.discardKeyword, tokens: .space)
return .visitChildren
}

override func visit(_ node: InheritanceClauseSyntax) -> SyntaxVisitorContinueKind {
// Normally, the open-break is placed before the open token. In this case, it's intentionally
// ordered differently so that the inheritance list can start on the current line and only
Expand Down
Loading