Skip to content

Commit

Permalink
Migrate emptyExtension rule to DeclarationV2
Browse files Browse the repository at this point in the history
  • Loading branch information
calda authored and nicklockwood committed Nov 26, 2024
1 parent 0698f0e commit 07661d2
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 17 deletions.
5 changes: 5 additions & 0 deletions Sources/DeclarationV2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ extension DeclarationV2 {
return formatter.parsePropertyDeclaration(atIntroducerIndex: keywordIndex)
}

/// The `TypeDeclaration` for this declaration, if it's a type with a body.
var asTypeDeclaration: TypeDeclaration? {
self as? TypeDeclaration
}

/// A list of all declarations that are a parent of this declaration
var parentDeclarations: [DeclarationV2] {
guard let parent = parent else { return [] }
Expand Down
27 changes: 10 additions & 17 deletions Sources/Rules/EmptyExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,24 @@ public extension FormatRule {
help: "Remove empty, non-conforming, extensions.",
orderAfter: [.unusedPrivateDeclarations]
) { formatter in
var emptyExtensions = [Declaration]()
var emptyExtensions = [TypeDeclaration]()

formatter.forEachRecursiveDeclaration { declaration, _ in
let declarationModifiers = Set(declaration.modifiers)
for declaration in formatter.parseDeclarationsV2() {
guard declaration.keyword == "extension",
let declarationBody = declaration.body,
declarationBody.isEmpty,
let extensionDeclaration = declaration.asTypeDeclaration,
extensionDeclaration.body.isEmpty,
// Ensure that it is not a macro
!declarationModifiers.contains(where: { $0.first == "@" })
else { return }
!extensionDeclaration.modifiers.contains(where: { $0.first == "@" })
else { continue }

// Ensure that the extension does not conform to any protocols
let parser = Formatter(declaration.openTokens)
guard let extensionIndex = parser.index(of: .keyword("extension"), after: -1),
let typeNameIndex = parser.index(of: .nonSpaceOrLinebreak, after: extensionIndex),
let type = parser.parseType(at: typeNameIndex),
let indexAfterType = parser.index(of: .nonSpaceOrCommentOrLinebreak, after: type.range.upperBound),
parser.tokens[indexAfterType] != .delimiter(":")
else { return }
guard extensionDeclaration.conformances.isEmpty else { continue }

emptyExtensions.append(declaration)
emptyExtensions.append(extensionDeclaration)
}

for declaration in emptyExtensions.reversed() {
formatter.removeTokens(in: declaration.originalRange)
for emptyExtension in emptyExtensions {
emptyExtension.remove()
}
} examples: {
"""
Expand Down

0 comments on commit 07661d2

Please sign in to comment.