-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Add new opt-in non_final_class
rule
#6025
base: main
Are you sure you want to change the base?
Conversation
8fb103d
to
fc16f25
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice little rule that may have its use cases!
There are a few violations in SwiftLint's code base itself. They can likely be auto-fixed. However, if there is inheritance involved we shouldn't put an open
but rather disable the rule locally or globally in the configuration (in case there are too many "false" positives).
Other than that, I've added a few remarks inline.
struct NonFinalClassRule: Rule { | ||
var configuration = SeverityConfiguration<Self>(.warning) | ||
|
||
static let description = RuleDescription( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now support adding rationals to rule descriptions. This feels like a very good candidate for some more explanation, as it seems highly opinionated and project-specific considering that open
implies public
which is often not what libraries want instead.
} | ||
|
||
private final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> { | ||
override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer visitPost
instead.
let modifiers = node.modifiers | ||
if !modifiers.contains(keyword: .final), | ||
!modifiers.contains(keyword: .open) { | ||
let classToken = node.classKeyword |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let classToken = node.classKeyword | |
let classTokenPosition = node.classKeyword.positionAfterSkippingLeadingTrivia |
let classToken = node.classKeyword | ||
violations.append(.init( | ||
position: classToken.positionAfterSkippingLeadingTrivia, | ||
reason: "Classes should be marked as `final` unless they are explicitly `open`", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be more succinct and targeted to the single class being checked:
reason: "Classes should be marked as `final` unless they are explicitly `open`", | |
reason: "Class should be marked as `final` or explicitly `open`", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test isn't needed. All examples in the description are test cases by design.
Example("public final class MyClass {}"), | ||
], | ||
triggeringExamples: [ | ||
Example("class MyClass {}"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add violation markers ↓
to indicate the exact positions where the violations are expected to appear.
No description provided.