Rename noFileID rule to fileMacro, support preferring either #file or #fileID

This commit is contained in:
Cal Stephens
2024-09-28 09:28:32 -07:00
parent 9b8d131d43
commit f10bc6f374
9 changed files with 157 additions and 110 deletions
+25 -19
View File
@@ -23,6 +23,7 @@
* [enumNamespaces](#enumNamespaces)
* [extensionAccessControl](#extensionAccessControl)
* [fileHeader](#fileHeader)
* [fileMacro](#fileMacro)
* [genericExtensions](#genericExtensions)
* [headerFileName](#headerFileName)
* [hoistAwait](#hoistAwait)
@@ -34,7 +35,6 @@
* [linebreakAtEndOfFile](#linebreakAtEndOfFile)
* [linebreaks](#linebreaks)
* [modifierOrder](#modifierOrder)
* [noFileID](#noFileID)
* [numberFormatting](#numberFormatting)
* [opaqueGenericParameters](#opaqueGenericParameters)
* [preferForLoop](#preferForLoop)
@@ -1019,6 +1019,30 @@ standard library.
</details>
<br/>
## fileMacro
Prefer either #file or #fileID, which have the same behavior in Swift 6 and later.
Option | Description
--- | ---
`--filemacro` | File macro to prefer: "#file" (default) or "#fileID".
<details>
<summary>Examples</summary>
```diff
// --filemacro #file
- func foo(file: StaticString = #fileID) { ... }
+ func foo(file: StaticString = #file) { ... }
// --filemacro #fileID
- func foo(file: StaticString = #file) { ... }
+ func foo(file: StaticString = #fileID) { ... }
```
</details>
<br/>
## genericExtensions
Use angle brackets (`extension Array<Foo>`) for generic type extensions
@@ -1392,24 +1416,6 @@ Don't use explicit ownership modifiers (borrowing / consuming).
</details>
<br/>
## noFileID
Prefer #file over #fileID.
<details>
<summary>Examples</summary>
In the Swift 6 language mode and later, #file has the same behavior as #fileID.
In the Swift 5 language mode, #file matches the behavior of #filePath.
```diff
- func foo(file: StaticString = #fileID) { ... }
+ func foo(file: StaticString = #file) { ... }
```
</details>
<br/>
## numberFormatting
Use consistent grouping for numeric literals. Groups will be separated by `_`
+8
View File
@@ -1253,6 +1253,14 @@ struct _Descriptors {
help: "For example: \"@Equatable,EquatableMacroLib\"",
keyPath: \.equatableMacroInfo
)
let preferFileMacro = OptionDescriptor(
argumentName: "filemacro",
displayName: "Preferred File Macro",
help: "File macro to prefer: \"#file\" (default) or \"#fileID\".",
keyPath: \.preferFileMacro,
trueValues: ["#file", "file"],
falseValues: ["#fileID", "fileID"]
)
// MARK: - Internal
+3
View File
@@ -718,6 +718,7 @@ public struct FormatOptions: CustomStringConvertible {
public var nilInit: NilInitType
public var preservedPrivateDeclarations: Set<String>
public var equatableMacroInfo: EquatableMacroInfo?
public var preferFileMacro: Bool
/// Deprecated
public var indentComments: Bool
@@ -845,6 +846,7 @@ public struct FormatOptions: CustomStringConvertible {
nilInit: NilInitType = .remove,
preservedPrivateDeclarations: Set<String> = [],
equatableMacroInfo: EquatableMacroInfo? = nil,
preferFileMacro: Bool = true,
// Doesn't really belong here, but hard to put elsewhere
fragment: Bool = false,
ignoreConflictMarkers: Bool = false,
@@ -962,6 +964,7 @@ public struct FormatOptions: CustomStringConvertible {
self.nilInit = nilInit
self.preservedPrivateDeclarations = preservedPrivateDeclarations
self.equatableMacroInfo = equatableMacroInfo
self.preferFileMacro = preferFileMacro
// Doesn't really belong here, but hard to put elsewhere
self.fragment = fragment
self.ignoreConflictMarkers = ignoreConflictMarkers
+1 -1
View File
@@ -37,6 +37,7 @@ let ruleRegistry: [String: FormatRule] = [
"enumNamespaces": .enumNamespaces,
"extensionAccessControl": .extensionAccessControl,
"fileHeader": .fileHeader,
"fileMacro": .fileMacro,
"genericExtensions": .genericExtensions,
"headerFileName": .headerFileName,
"hoistAwait": .hoistAwait,
@@ -51,7 +52,6 @@ let ruleRegistry: [String: FormatRule] = [
"markTypes": .markTypes,
"modifierOrder": .modifierOrder,
"noExplicitOwnership": .noExplicitOwnership,
"noFileID": .noFileID,
"numberFormatting": .numberFormatting,
"opaqueGenericParameters": .opaqueGenericParameters,
"organizeDeclarations": .organizeDeclarations,
+43
View File
@@ -0,0 +1,43 @@
//
// FileMacro.swift
// SwiftFormat
//
// Created by Cal Stephens on 9/14/24.
// Copyright © 2024 Nick Lockwood. All rights reserved.
//
import Foundation
public extension FormatRule {
static let fileMacro = FormatRule(
help: "Prefer either #file or #fileID, which have the same behavior in Swift 6 and later.",
options: ["filemacro"]
) { formatter in
// In the Swift 6 lanaguage mode and later, `#file` and `#fileID` have the same behavior.
guard formatter.options.languageMode >= "6" else {
return
}
if formatter.options.preferFileMacro {
formatter.forEach(.keyword("#fileID")) { index, _ in
formatter.replaceToken(at: index, with: .keyword("#file"))
}
} else {
formatter.forEach(.keyword("#file")) { index, _ in
formatter.replaceToken(at: index, with: .keyword("#fileID"))
}
}
} examples: {
"""
```diff
// --filemacro #file
- func foo(file: StaticString = #fileID) { ... }
+ func foo(file: StaticString = #file) { ... }
// --filemacro #fileID
- func foo(file: StaticString = #file) { ... }
+ func foo(file: StaticString = #fileID) { ... }
```
"""
}
}
-34
View File
@@ -1,34 +0,0 @@
//
// NoFileID.swift
// SwiftFormat
//
// Created by Cal Stephens on 9/14/24.
// Copyright © 2024 Nick Lockwood. All rights reserved.
//
import Foundation
public extension FormatRule {
static let noFileID = FormatRule(
help: "Prefer #file over #fileID.")
{ formatter in
// In the Swift 6 lanaguage mode and later, `#file` and `#fileID` have the same behavior.
guard formatter.options.languageMode >= "6" else {
return
}
formatter.forEach(.keyword("#fileID")) { index, _ in
formatter.replaceToken(at: index, with: .keyword("#file"))
}
} examples: {
"""
In the Swift 6 language mode and later, #file has the same behavior as #fileID.
In the Swift 5 language mode, #file matches the behavior of #filePath.
```diff
- func foo(file: StaticString = #fileID) { ... }
+ func foo(file: StaticString = #file) { ... }
```
"""
}
}
+16 -16
View File
@@ -626,11 +626,11 @@
2E8DE7602C57FEB30032BF25 /* InitCoderUnavailableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E8DE6F52C57FEB30032BF25 /* InitCoderUnavailableTests.swift */; };
2E8DE7612C57FEB30032BF25 /* RedundantFileprivateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E8DE6F62C57FEB30032BF25 /* RedundantFileprivateTests.swift */; };
2E8DE7622C57FEB30032BF25 /* WrapSingleLineCommentsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E8DE6F72C57FEB30032BF25 /* WrapSingleLineCommentsTests.swift */; };
2E9DE5062C95F9A1000FEDF8 /* NoFileID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E9DE5052C95F9A1000FEDF8 /* NoFileID.swift */; };
2E9DE5072C95F9A1000FEDF8 /* NoFileID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E9DE5052C95F9A1000FEDF8 /* NoFileID.swift */; };
2E9DE5082C95F9A1000FEDF8 /* NoFileID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E9DE5052C95F9A1000FEDF8 /* NoFileID.swift */; };
2E9DE5092C95F9A1000FEDF8 /* NoFileID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E9DE5052C95F9A1000FEDF8 /* NoFileID.swift */; };
2E9DE50F2C95FBB6000FEDF8 /* NoFileIDTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E9DE50A2C95FB4F000FEDF8 /* NoFileIDTests.swift */; };
2E9DE5062C95F9A1000FEDF8 /* FileMacro.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E9DE5052C95F9A1000FEDF8 /* FileMacro.swift */; };
2E9DE5072C95F9A1000FEDF8 /* FileMacro.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E9DE5052C95F9A1000FEDF8 /* FileMacro.swift */; };
2E9DE5082C95F9A1000FEDF8 /* FileMacro.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E9DE5052C95F9A1000FEDF8 /* FileMacro.swift */; };
2E9DE5092C95F9A1000FEDF8 /* FileMacro.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E9DE5052C95F9A1000FEDF8 /* FileMacro.swift */; };
2E9DE50F2C95FBB6000FEDF8 /* FileMacroTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E9DE50A2C95FB4F000FEDF8 /* FileMacroTests.swift */; };
2EF737522C5E881C00128F91 /* CodeOrganizationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EF737512C5E881C00128F91 /* CodeOrganizationTests.swift */; };
2EF737542C5E897800128F91 /* ProjectFilePaths.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EF737532C5E897800128F91 /* ProjectFilePaths.swift */; };
2EF737562C5ED19600128F91 /* DocCommentsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EF737552C5ED19600128F91 /* DocCommentsTests.swift */; };
@@ -1010,8 +1010,8 @@
2E8DE6F52C57FEB30032BF25 /* InitCoderUnavailableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InitCoderUnavailableTests.swift; sourceTree = "<group>"; };
2E8DE6F62C57FEB30032BF25 /* RedundantFileprivateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RedundantFileprivateTests.swift; sourceTree = "<group>"; };
2E8DE6F72C57FEB30032BF25 /* WrapSingleLineCommentsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WrapSingleLineCommentsTests.swift; sourceTree = "<group>"; };
2E9DE5052C95F9A1000FEDF8 /* NoFileID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoFileID.swift; sourceTree = "<group>"; };
2E9DE50A2C95FB4F000FEDF8 /* NoFileIDTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoFileIDTests.swift; sourceTree = "<group>"; };
2E9DE5052C95F9A1000FEDF8 /* FileMacro.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMacro.swift; sourceTree = "<group>"; };
2E9DE50A2C95FB4F000FEDF8 /* FileMacroTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMacroTests.swift; sourceTree = "<group>"; };
2EF737512C5E881C00128F91 /* CodeOrganizationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeOrganizationTests.swift; sourceTree = "<group>"; };
2EF737532C5E897800128F91 /* ProjectFilePaths.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectFilePaths.swift; sourceTree = "<group>"; };
2EF737552C5ED19600128F91 /* DocCommentsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DocCommentsTests.swift; sourceTree = "<group>"; };
@@ -1225,7 +1225,6 @@
2E2BAB902C57F6DD00590239 /* Rules */ = {
isa = PBXGroup;
children = (
082D644A2CA4719B0072DA14 /* RedundantEquatable.swift */,
2E2BABF02C57F6DD00590239 /* Acronyms.swift */,
2E2BABE22C57F6DD00590239 /* AndOperator.swift */,
2E2BABE82C57F6DD00590239 /* AnyObjectProtocol.swift */,
@@ -1254,6 +1253,7 @@
2E2BABD92C57F6DD00590239 /* EnumNamespaces.swift */,
2E2BABC72C57F6DD00590239 /* ExtensionAccessControl.swift */,
2E2BABC02C57F6DD00590239 /* FileHeader.swift */,
2E9DE5052C95F9A1000FEDF8 /* FileMacro.swift */,
2E2BABCA2C57F6DD00590239 /* GenericExtensions.swift */,
2E2BABC32C57F6DD00590239 /* HeaderFileName.swift */,
2E2BABEB2C57F6DD00590239 /* HoistAwait.swift */,
@@ -1268,7 +1268,6 @@
2E2BABE12C57F6DD00590239 /* MarkTypes.swift */,
2E2BABD82C57F6DD00590239 /* ModifierOrder.swift */,
2E2BABB92C57F6DD00590239 /* NoExplicitOwnership.swift */,
2E9DE5052C95F9A1000FEDF8 /* NoFileID.swift */,
2E2BABF62C57F6DD00590239 /* NumberFormatting.swift */,
2E2BABED2C57F6DD00590239 /* OpaqueGenericParameters.swift */,
2E2BABBF2C57F6DD00590239 /* OrganizeDeclarations.swift */,
@@ -1279,6 +1278,7 @@
2E2BABE92C57F6DD00590239 /* RedundantBackticks.swift */,
2E2BAB922C57F6DD00590239 /* RedundantBreak.swift */,
2E2BABBE2C57F6DD00590239 /* RedundantClosure.swift */,
082D644A2CA4719B0072DA14 /* RedundantEquatable.swift */,
2E2BAB982C57F6DD00590239 /* RedundantExtensionACL.swift */,
2E2BABA82C57F6DD00590239 /* RedundantFileprivate.swift */,
2E2BABA22C57F6DD00590239 /* RedundantGet.swift */,
@@ -1347,7 +1347,6 @@
2E8DE68C2C57FEB30032BF25 /* Rules */ = {
isa = PBXGroup;
children = (
082D644F2CA471F00072DA14 /* RedundantEquatableTests.swift */,
2E8DE6D02C57FEB30032BF25 /* AcronymsTests.swift */,
2E8DE6F02C57FEB30032BF25 /* AndOperatorTests.swift */,
2E8DE6BB2C57FEB30032BF25 /* AnyObjectProtocolTests.swift */,
@@ -1376,6 +1375,7 @@
2E8DE6972C57FEB30032BF25 /* EnumNamespacesTests.swift */,
2E8DE6992C57FEB30032BF25 /* ExtensionAccessControlTests.swift */,
2E8DE6962C57FEB30032BF25 /* FileHeaderTests.swift */,
2E9DE50A2C95FB4F000FEDF8 /* FileMacroTests.swift */,
2E8DE6AF2C57FEB30032BF25 /* GenericExtensionsTests.swift */,
2E8DE6DE2C57FEB30032BF25 /* HeaderFileNameTests.swift */,
2E8DE6C62C57FEB30032BF25 /* HoistAwaitTests.swift */,
@@ -1390,7 +1390,6 @@
2E8DE6E72C57FEB30032BF25 /* MarkTypesTests.swift */,
2E8DE6A02C57FEB30032BF25 /* ModifierOrderTests.swift */,
2E8DE6D42C57FEB30032BF25 /* NoExplicitOwnershipTests.swift */,
2E9DE50A2C95FB4F000FEDF8 /* NoFileIDTests.swift */,
2E8DE6B02C57FEB30032BF25 /* NumberFormattingTests.swift */,
2E8DE69E2C57FEB30032BF25 /* OpaqueGenericParametersTests.swift */,
2E8DE6E22C57FEB30032BF25 /* OrganizeDeclarationsTests.swift */,
@@ -1401,6 +1400,7 @@
2E8DE6C42C57FEB30032BF25 /* RedundantBackticksTests.swift */,
2E8DE6BC2C57FEB30032BF25 /* RedundantBreakTests.swift */,
2E8DE68D2C57FEB30032BF25 /* RedundantClosureTests.swift */,
082D644F2CA471F00072DA14 /* RedundantEquatableTests.swift */,
2E8DE6DF2C57FEB30032BF25 /* RedundantExtensionACLTests.swift */,
2E8DE6F62C57FEB30032BF25 /* RedundantFileprivateTests.swift */,
2E8DE6DD2C57FEB30032BF25 /* RedundantGetTests.swift */,
@@ -1933,7 +1933,7 @@
2E2BAC0F2C57F6DD00590239 /* WrapMultilineConditionalAssignment.swift in Sources */,
2E2BAD072C57F6DD00590239 /* RedundantPattern.swift in Sources */,
2E2BACE72C57F6DD00590239 /* TrailingSpace.swift in Sources */,
2E9DE5062C95F9A1000FEDF8 /* NoFileID.swift in Sources */,
2E9DE5062C95F9A1000FEDF8 /* FileMacro.swift in Sources */,
2E2BACEF2C57F6DD00590239 /* ConditionalAssignment.swift in Sources */,
9BDB4F1E2C9477FF00C93995 /* PrivateStateVariables.swift in Sources */,
2E2BAD172C57F6DD00590239 /* BlankLineAfterImports.swift in Sources */,
@@ -1961,7 +1961,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
2E9DE50F2C95FBB6000FEDF8 /* NoFileIDTests.swift in Sources */,
2E9DE50F2C95FBB6000FEDF8 /* FileMacroTests.swift in Sources */,
2E8DE74A2C57FEB30032BF25 /* RedundantExtensionACLTests.swift in Sources */,
01A0EAB41D5DB4D000A0A8E3 /* XCTestCase+testFormatting.swift in Sources */,
2E8DE7602C57FEB30032BF25 /* InitCoderUnavailableTests.swift in Sources */,
@@ -2223,7 +2223,7 @@
2E2BACAC2C57F6DD00590239 /* RedundantLetError.swift in Sources */,
01045A9A2119979400D2BE3D /* Arguments.swift in Sources */,
580496D62C584E8F004B7DBF /* EmptyExtensions.swift in Sources */,
2E9DE5072C95F9A1000FEDF8 /* NoFileID.swift in Sources */,
2E9DE5072C95F9A1000FEDF8 /* FileMacro.swift in Sources */,
2E2BAD482C57F6DD00590239 /* WrapLoopBodies.swift in Sources */,
2E2BAD082C57F6DD00590239 /* RedundantPattern.swift in Sources */,
2E2BAD042C57F6DD00590239 /* SpaceInsideBraces.swift in Sources */,
@@ -2282,7 +2282,7 @@
2E2BACED2C57F6DD00590239 /* RedundantObjc.swift in Sources */,
2E2BAC692C57F6DD00590239 /* LinebreakAtEndOfFile.swift in Sources */,
E487211D201D885A0014845E /* RulesViewController.swift in Sources */,
2E9DE5082C95F9A1000FEDF8 /* NoFileID.swift in Sources */,
2E9DE5082C95F9A1000FEDF8 /* FileMacro.swift in Sources */,
2E2BAC212C57F6DD00590239 /* RedundantOptionalBinding.swift in Sources */,
01045A9B2119979400D2BE3D /* Arguments.swift in Sources */,
2E2BAC712C57F6DD00590239 /* AssertionFailures.swift in Sources */,
@@ -2429,7 +2429,7 @@
2E2BACEE2C57F6DD00590239 /* RedundantObjc.swift in Sources */,
2E2BAC6A2C57F6DD00590239 /* LinebreakAtEndOfFile.swift in Sources */,
0142C77023C3FB6D005D5832 /* LintFileCommand.swift in Sources */,
2E9DE5092C95F9A1000FEDF8 /* NoFileID.swift in Sources */,
2E9DE5092C95F9A1000FEDF8 /* FileMacro.swift in Sources */,
2E2BAC222C57F6DD00590239 /* RedundantOptionalBinding.swift in Sources */,
E4E4D3CC2033F17C000D7CB1 /* EnumAssociable.swift in Sources */,
2E2BAC722C57F6DD00590239 /* AssertionFailures.swift in Sources */,
+61
View File
@@ -0,0 +1,61 @@
//
// FileMacroTests.swift
// SwiftFormat
//
// Created by Cal Stephens on 9/14/24.
// Copyright © 2024 Nick Lockwood. All rights reserved.
//
import XCTest
@testable import SwiftFormat
final class FileMacroTests: XCTestCase {
func testPreservesFileMacroInSwift5Mode() {
let input = """
func foo(file: StaticString = #fileID) {
print(file)
}
func bar(file: StaticString = #file) {
print(file)
}
"""
let options = FormatOptions(languageMode: "5")
testFormatting(for: input, rule: .fileMacro, options: options)
}
func testUpdatesFileIDInSwift6Mode() {
let input = """
func foo(file: StaticString = #fileID) {
print(file)
}
"""
let output = """
func foo(file: StaticString = #file) {
print(file)
}
"""
let options = FormatOptions(preferFileMacro: true, languageMode: "6")
testFormatting(for: input, output, rule: .fileMacro, options: options)
}
func testPreferFileID() {
let input = """
func foo(file: StaticString = #file) {
print(file)
}
"""
let output = """
func foo(file: StaticString = #fileID) {
print(file)
}
"""
let options = FormatOptions(preferFileMacro: false, languageMode: "6")
testFormatting(for: input, output, rule: .fileMacro, options: options)
}
}
-40
View File
@@ -1,40 +0,0 @@
//
// NoFileIDTests.swift
// SwiftFormat
//
// Created by Cal Stephens on 9/14/24.
// Copyright © 2024 Nick Lockwood. All rights reserved.
//
import XCTest
@testable import SwiftFormat
final class NoFileIDTests: XCTestCase {
func testPreservesFileIDInSwift5Mode() {
let input = """
func foo(file: StaticString = #fileID) {
print(file)
}
"""
let options = FormatOptions(languageMode: "5")
testFormatting(for: input, rule: .noFileID, options: options)
}
func testUpdatesFileIDInSwift6Mode() {
let input = """
func foo(file: StaticString = #fileID) {
print(file)
}
"""
let output = """
func foo(file: StaticString = #file) {
print(file)
}
"""
let options = FormatOptions(languageMode: "6")
testFormatting(for: input, output, rule: .noFileID, options: options)
}
}