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

Allow user to customize additional variable names to be replaced by self with the strongifiedSelf rule #523

Open
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

krunk4ever
Copy link

@krunk4ever krunk4ever commented Jan 3, 2020

Related: #521

For the strongifiedSelf rule, it would be great if the user can customize an additional list of variable names to be auto-corrected to self (e.g. ss or strongSelf).

This PR introduces a new option for the strongifiedSelf rule which is a comma-delimited list of identifiers we want to replace with self.

Sources/Rules.swift Outdated Show resolved Hide resolved
@coveralls
Copy link

coveralls commented Jan 3, 2020

Coverage Status

Coverage increased (+0.003%) to 92.973% when pulling eb771ee on krunk4ever:update-strongified-self into f50fb32 on nicklockwood:master.

@nicklockwood
Copy link
Owner

This is a great idea, but I fear the implementation may be over-simplistic, because the user might have defined another variable with the same name that shadows the first, and this would end up replacing both. I'll add some tests and see if that's a problem in practice.

@krunk4ever
Copy link
Author

krunk4ever commented Jan 3, 2020

@nicklockwood I added the option to pass in a comma delimited list of identifiers. e.g. my *.swiftformat file now includes the following line:

--strongselfids s,ss,sself,sSelf,strongself,strongSelf

Sources/Rules.swift Outdated Show resolved Hide resolved
@krunk4ever krunk4ever changed the title Replace ss, sSelf, and strongSelf with self for strongifiedSelf rule Allow user to customize additional variable names to be replaced by self with the strongifiedSelf rule Jan 3, 2020
$0 == .operator("=", .infix)
}), formatter.next(.nonSpaceOrCommentOrLinebreak, after: equalIndex) == .identifier("self") else {
return
}
Copy link
Owner

Choose a reason for hiding this comment

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

I don't think this will work. It only replaces the identifier if it appears in an expression like strongSelf = self, but it won't replace any references to strongSelf in the subsequent code.

Copy link
Author

@krunk4ever krunk4ever Jan 3, 2020

Choose a reason for hiding this comment

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

@nicklockwood, yeah, I also discussed this with my coworkers to see if autocorrect was the right thing to do here. there's actually 3 things that need to be autocorrected:

  1. Rename the disallowed variable name with self
  2. Update any references to the disallowed variable name to self
  3. Fix optionality of existing references to self which are no longer optional

Example for number 3:

{ [weak self] in 
  guard let strongSelf = self else { return }
  self?.doWork()
}

In the above example, we would also need to remove the trailing ? after self:

{ [weak self] in
  guard let self = self else { return }
  self.doWork()
}

(2) and (3) both feel really complicated for autocorrection w/o full understanding of the code graph and would be probably better off with human intervention. However, we still found it to be useful for autocorrect to complete step (1) despite the fact it might leave the code uncompilable.

thoughts?

Copy link
Owner

@nicklockwood nicklockwood Jan 4, 2020

Choose a reason for hiding this comment

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

  1. is similar in complexity to what I already do for removing implicit self. It's certainly complicated because it requires an understanding of scope and tracking variable declarations and shadowing, but it's a local problem (i.e. it doesn't require knowledge of externally-defined symbols and their types) so it can be solved.

  2. is probably too difficult since modifications from optional to non-optional may be nontrivial, but I also think it's a bad idea generally because the developer may have a good reason for referencing self? rather than strongSelf and a formatter shouldn't second-guess that. However it wouldn't be hard to detect the user of self and not replace strongSelf in those cases.

Copy link
Owner

Choose a reason for hiding this comment

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

Just doing 1) and leaving code non-compilable is not acceptable IMO. Now that SwiftFormat has fairly decent linting capability, it might make sense to introduce the concept of "lint-only" rules for cases like this, where it would warn but not actually replace the symbol.

But TBH, it would probably make more sense to make it a SwiftLint rule instead in that case.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, we have a simple SwiftLint custom rule for detecting this for now:

  reuse_self_for_strongified_self:
    name: Reuse self for strongified self
    regex: "(?i) (s|ss|sSelf|strongSelf) = self[\n ,]"
    message: "Reuse self as the variable name when strongifying self as per Airbnb Swift style guide"
    severity: error

If you have an idea of how to autocorrect for (2), that would be great! I can take a look at removing implicit self and see if I can mimic that behavior, but if you have pointers or have the bandwidth to add that, even better!

@nicklockwood nicklockwood force-pushed the master branch 3 times, most recently from 73b9f9a to dbe1144 Compare July 13, 2022 21:25
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.

3 participants