Skip to content
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

Merged
merged 4 commits into from
Aug 1, 2017

Conversation

ornithocoder
Copy link
Contributor

@ornithocoder ornithocoder commented Aug 1, 2017

Implements #1306, requested by @Noobish1.

  • Opt-in rule,
  • Implements UIDevice() and Bundle() by default,
  • Allows severity configuration (warning or error) via .swiftlint,
  • Allows overwriting types via .swiftlint.

@ornithocoder ornithocoder changed the title Add discouraged_init opt-in rule that discourages direct (issue #1306) Add discouraged_init opt-in rule that discourages direct Aug 1, 2017
@ornithocoder ornithocoder changed the title Add discouraged_init opt-in rule that discourages direct Add discouraged_init opt-in rule that discourages direct initialization of certain types Aug 1, 2017
@SwiftLintBot
Copy link

SwiftLintBot commented Aug 1, 2017

1 Warning
⚠️ Permanently added the RSA host key for IP address ‘192.30.253.113’ to the list of known hosts.
12 Messages
📖 Linting Aerial with this PR took 0.35s vs 0.33s on master (6% slower)
📖 Linting Alamofire with this PR took 2.46s vs 2.39s on master (2% slower)
📖 Linting Firefox with this PR took 10.55s vs 10.43s on master (1% slower)
📖 Linting Kickstarter with this PR took 15.71s vs 15.2s on master (3% slower)
📖 Linting Moya with this PR took 0.73s vs 0.72s on master (1% slower)
📖 Linting Nimble with this PR took 1.42s vs 1.39s on master (2% slower)
📖 Linting Quick with this PR took 0.45s vs 0.44s on master (2% slower)
📖 Linting Realm with this PR took 2.2s vs 2.15s on master (2% slower)
📖 Linting SourceKitten with this PR took 0.82s vs 0.77s on master (6% slower)
📖 Linting Sourcery with this PR took 3.64s vs 3.56s on master (2% slower)
📖 Linting Swift with this PR took 10.19s vs 10.09s on master (0% slower)
📖 Linting WordPress with this PR took 9.62s vs 9.53s on master (0% slower)

Generated by 🚫 Danger

@codecov-io
Copy link

codecov-io commented Aug 1, 2017

Codecov Report

❗ No coverage uploaded for pull request base (master@f822e1c). Click here to learn what that means.
The diff coverage is 91.04%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #1731   +/-   ##
=========================================
  Coverage          ?   87.55%           
=========================================
  Files             ?      214           
  Lines             ?    10535           
  Branches          ?        0           
=========================================
  Hits              ?     9224           
  Misses            ?     1311           
  Partials          ?        0
Impacted Files Coverage Δ
...rameworkTests/DiscouragedDirectInitRuleTests.swift 100% <100%> (ø)
...intFramework/Rules/DiscouragedDirectInitRule.swift 100% <100%> (ø)
...gurations/DiscouragedDirectInitConfiguration.swift 68.42% <68.42%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f822e1c...1726573. Read the comment docs.

let offset = dictionary.nameOffset,
let name = dictionary.name,
kind == .call,
dictionary.bodyLength == 0,
Copy link
Collaborator

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.

Copy link
Contributor Author

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)
Copy link
Collaborator

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?

Copy link
Contributor Author

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]
Copy link
Collaborator

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>?

Copy link
Contributor Author

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
Copy link
Collaborator

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)"

Copy link
Contributor Author

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
Copy link
Collaborator

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).

Copy link
Contributor Author

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() {
Copy link
Collaborator

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?

Copy link
Contributor Author

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.

Copy link
Collaborator

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.

Copy link
Contributor Author

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?

Copy link
Collaborator

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.

Copy link
Contributor Author

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.
Copy link
Collaborator

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep!

try severityConfiguration.apply(configuration: severityString)
}

if let included = [String].array(of: configuration["included"]) {
Copy link
Collaborator

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.

Copy link
Contributor Author

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() {
Copy link
Collaborator

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, removed.

@marcelofabri
Copy link
Collaborator

@ornithocoder This looks great! I just have two more small nitpicks 😅

@jpsim
Copy link
Collaborator

jpsim commented Aug 1, 2017

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"]) {
Copy link
Collaborator

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

Copy link
Contributor Author

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.

@ornithocoder
Copy link
Contributor Author

@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?

@marcelofabri
Copy link
Collaborator

I think that the chance of getting a false positive with UIDevice or Bundle is low, so 👍 on making this enabled by default.

@marcelofabri marcelofabri merged commit d916dbb into realm:master Aug 1, 2017
@jpsim
Copy link
Collaborator

jpsim commented Aug 1, 2017

@marcelofabri you merged this but it's still marked as opt-in... 🤔

did you mean to change that before merging?

@marcelofabri
Copy link
Collaborator

I'm opening a new PR to change it.

@marcelofabri
Copy link
Collaborator

Here it is: #1736. My plan was to merge it without a PR (🙈), but I've realized that actually LinuxMain.swift was outdated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants