-
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 discouraged_init opt-in rule that discourages direct initialization of certain types #1731
Conversation
Generated by 🚫 Danger |
Codecov Report
@@ Coverage Diff @@
## master #1731 +/- ##
=========================================
Coverage ? 87.55%
=========================================
Files ? 214
Lines ? 10535
Branches ? 0
=========================================
Hits ? 9224
Misses ? 1311
Partials ? 0
Continue to review full report at Codecov.
|
let offset = dictionary.nameOffset, | ||
let name = dictionary.name, | ||
kind == .call, | ||
dictionary.bodyLength == 0, |
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.
so, this rule actually just works for inits without parameters, right?
In this case, I'd rename the rule and try to improve the description as well.
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.
Precisely, it's meant to direct initialization only. I'll update the rule name and description.
let name = dictionary.name, | ||
kind == .call, | ||
dictionary.bodyLength == 0, | ||
configuration.discouragedInits.contains(name) |
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.
what do you think about also checking for Bundle.init()
for example?
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.
Sure, I'll do that.
return severityConfiguration.severity | ||
} | ||
|
||
private(set) public var discouragedInits: [String] |
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.
what do you think about making it a Set<String>
?
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.
Much better! Changing it.
public var severityConfiguration = SeverityConfiguration(.warning) | ||
|
||
public var consoleDescription: String { | ||
return severityConfiguration.consoleDescription |
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.
You need to include all configuration in the description.
For example:
return "severity: \(severityConfiguration.consoleDescription), included: \(discouragedInits)"
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.
Sorry about that. Updating it.
} | ||
|
||
if let included = [String].array(of: configuration["included"]) { | ||
discouragedInits += included |
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.
I think this should always override the default values. Doing that, we provide a way to opt-out from the default configuration if needed (for example, one might have a class Bundle
in their project).
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.
No problem. I'll update the code.
@@ -62,6 +62,26 @@ class RulesTests: XCTestCase { | |||
verifyRule(DiscardedNotificationCenterObserverRule.description) | |||
} | |||
|
|||
func testDiscouragedInit() { |
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.
can you add a new test class and split this in several tests, please?
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.
Sure, but I might have to disable the type_body_length rule for this file, tho.
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.
I meant making it a new file. Sorry, should have been more explicit about it.
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.
Sure, no problem. Should I leave the "default" one in this one?
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.
I think it makes sense to move everything to the new file. See FileHeaderRuleTests.swift
for example.
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.
I'll move them all. Easier to maintain ;-)
CHANGELOG.md
Outdated
@@ -92,6 +92,11 @@ | |||
[Marcelo Fabri](https://github.com/marcelofabri) | |||
[#1714](https://github.com/realm/SwiftLint/issues/1714) | |||
|
|||
* Add `discouraged_init` opt-in rule that discourages direct | |||
initialization of certain classes. |
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.
I'd use "types" instead of "classes" here.
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.
Yep!
Rule requested by @Noobish1 on issue realm#1306.
35548b1
to
13c7e6e
Compare
try severityConfiguration.apply(configuration: severityString) | ||
} | ||
|
||
if let included = [String].array(of: configuration["included"]) { |
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.
actually, on a second thought, what do you think about using "types"
as the key? I'm afraid that we already overload the term included
too much.
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.
It makes sense. Changed.
class DiscouragedDirectInitRuleTests: XCTestCase { | ||
let baseDescription = DiscouragedDirectInitRule.description | ||
|
||
func testDiscouragedDirectInitRuleWithDefaultConfiguration() { |
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 you remove the Rule
from the method names just to keep consistent with other tests?
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.
Sure, removed.
@ornithocoder This looks great! I just have two more small nitpicks 😅 |
Why is this opt-in? |
@@ -46,7 +46,7 @@ public struct DiscouragedDirectInitConfiguration: RuleConfiguration, Equatable { | |||
try severityConfiguration.apply(configuration: severityString) | |||
} | |||
|
|||
if let included = [String].array(of: configuration["included"]) { | |||
if let included = [String].array(of: configuration["types"]) { |
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.
You need to change on consoleDescription too
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.
Yep, and the variable name :-) Done.
@jpsim @marcelofabri I didn't spend much time thinking of that and went for the easy option. Should I make it a default rule instead? |
I think that the chance of getting a false positive with |
@marcelofabri you merged this but it's still marked as opt-in... 🤔 did you mean to change that before merging? |
I'm opening a new PR to change it. |
Here it is: #1736. My plan was to merge it without a PR (🙈), but I've realized that actually |
Implements #1306, requested by @Noobish1.