mirror of
https://github.com/realm/SwiftLint.git
synced 2026-06-06 20:18:40 +00:00
Add new one_declaration_per_file rule (#5377)
This commit is contained in:
@@ -38,6 +38,7 @@ disabled_rules:
|
||||
- no_fallthrough_only
|
||||
- no_grouping_extension
|
||||
- no_magic_numbers
|
||||
- one_declaration_per_file
|
||||
- prefer_nimble
|
||||
- prefer_self_in_static_references
|
||||
- prefixed_toplevel_constant
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
|
||||
#### Enhancements
|
||||
|
||||
* Add new `one_declaration_per_file` rule that allows only a
|
||||
single class/struct/enum/protocol declaration per file.
|
||||
Extensions are an exception; more than one is allowed.
|
||||
[Muhammad Zeeshan](https://github.com/mzeeshanid)
|
||||
[#2802](https://github.com/realm/SwiftLint/issues/2802)
|
||||
|
||||
* Rewrite the following rules with SwiftSyntax:
|
||||
* `identifier_name`
|
||||
* `let_var_whitespace`
|
||||
|
||||
@@ -135,6 +135,7 @@ public let builtInRules: [any Rule.Type] = [
|
||||
NotificationCenterDetachmentRule.self,
|
||||
NumberSeparatorRule.self,
|
||||
ObjectLiteralRule.self,
|
||||
OneDelarationPerFileRule.self,
|
||||
OpeningBraceRule.self,
|
||||
OperatorFunctionWhitespaceRule.self,
|
||||
OperatorUsageWhitespaceRule.self,
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import SwiftSyntax
|
||||
|
||||
@SwiftSyntaxRule
|
||||
struct OneDelarationPerFileRule: OptInRule {
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
identifier: "one_declaration_per_file",
|
||||
name: "One Declaration per File",
|
||||
description: "Only a single declaration is allowed in a file",
|
||||
kind: .idiomatic,
|
||||
nonTriggeringExamples: [
|
||||
Example("""
|
||||
class Foo {}
|
||||
"""),
|
||||
Example("""
|
||||
class Foo {}
|
||||
extension Foo {}
|
||||
"""),
|
||||
Example("""
|
||||
struct S {
|
||||
struct N {}
|
||||
}
|
||||
""")
|
||||
],
|
||||
triggeringExamples: [
|
||||
Example("""
|
||||
class Foo {}
|
||||
↓class Bar {}
|
||||
"""),
|
||||
Example("""
|
||||
protocol Foo {}
|
||||
↓enum Bar {}
|
||||
"""),
|
||||
Example("""
|
||||
struct Foo {}
|
||||
↓struct Bar {}
|
||||
""")
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
private extension OneDelarationPerFileRule {
|
||||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
|
||||
private var declarationVisited = false
|
||||
override var skippableDeclarations: [any DeclSyntaxProtocol.Type] { .all }
|
||||
|
||||
override func visitPost(_ node: ActorDeclSyntax) {
|
||||
appendViolationIfNeeded(node: node.actorKeyword)
|
||||
}
|
||||
|
||||
override func visitPost(_ node: ClassDeclSyntax) {
|
||||
appendViolationIfNeeded(node: node.classKeyword)
|
||||
}
|
||||
|
||||
override func visitPost(_ node: StructDeclSyntax) {
|
||||
appendViolationIfNeeded(node: node.structKeyword)
|
||||
}
|
||||
|
||||
override func visitPost(_ node: EnumDeclSyntax) {
|
||||
appendViolationIfNeeded(node: node.enumKeyword)
|
||||
}
|
||||
|
||||
override func visitPost(_ node: ProtocolDeclSyntax) {
|
||||
appendViolationIfNeeded(node: node.protocolKeyword)
|
||||
}
|
||||
|
||||
func appendViolationIfNeeded(node: TokenSyntax) {
|
||||
if declarationVisited {
|
||||
violations.append(node.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
declarationVisited = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -800,6 +800,12 @@ class ObjectLiteralRuleGeneratedTests: SwiftLintTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
class OneDelarationPerFileRuleGeneratedTests: SwiftLintTestCase {
|
||||
func testWithDefaultConfiguration() {
|
||||
verifyRule(OneDelarationPerFileRule.description)
|
||||
}
|
||||
}
|
||||
|
||||
class OpeningBraceRuleGeneratedTests: SwiftLintTestCase {
|
||||
func testWithDefaultConfiguration() {
|
||||
verifyRule(OpeningBraceRule.description)
|
||||
|
||||
Reference in New Issue
Block a user