-
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
Configuration Structs #391
Conversation
public protocol RuleConfig { | ||
mutating func setConfig(config: AnyObject) throws | ||
func isEqualTo(ruleConfig: RuleConfig) -> Bool | ||
} |
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 can use:
extension RuleConfig where Self: Equatable {
public func isEqualTo(ruleConfig: RuleConfig) -> Bool {
if let ruleConfig = ruleConfig as? Self {
return self == ruleConfig
}
return false
}
}
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.
Great add.
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.
Done!
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.
👍
Great! |
This might be a good time to add UPDATE I played around with notes, and it appears that while Xcode recognizes them as a special case, it does note display them anywhere in the GUI. |
Awesome! At first glance, I like this direction, but I might not be able to review in depth for a few days. I'm certainly happy to see this address so many issues users have faced regarding configuration! |
|
||
import Foundation | ||
|
||
public enum ConfigurationError: ErrorType { |
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.
Why introduce this if there's only one member, and it's never checked? ConfigurableRuleType.init(config:)
is only ever used with try?
, which type-erases the error in a sense.
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 was something I thought about for a bit. Basically what was the best way to support configuration structures failing and provide optional configuration values functionality. To use the failable initializers approach that was previously used in ConfigurableRule
would have required each rule to have its own RuleConfig
type because you could only declare the default values in the structure. The second approach was to split initialization with default values and configuration with optional values into init
and setConfig
. Since we needed a way to indicate failure in setConfig
, we could either throw or return some sort of success/failure flag (e.g. Bool, Result
, etc.). Throwing felt the most Swifty to me, and I needed something to throw, so that's how this came to be.
There's certainly a case to be made that if we use this approach, we should introduce some finer-grain errors, possibly merge this with YamlParsingError, and probably change Configuration.init?
to Configuration.init() throws
. That's all possible in this PR, but in my head I was scoping it to the rework that needs to be done on logging and errors.
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.
For the time being, I made this marginally more useful by not squashing the error in Configuration.rulesFromDict
, though nothing is really being done with it. Let me know if you want to combine this with YamlParserError
. I like that we have one less error type with that approach. But I don't like that a ConfigProviderRule
would even know about something that knows about the Yaml
subsystem.
This is pretty awesome! I'm happy with almost all of this, other than where noted, and the remaining checklist items from the original PR comment. It shouldn't be too much work to rebase this on |
Great. I'll make those changes today so we can get this in. |
c921a34
to
9a77974
Compare
@jpsim take a look at this. Only outstanding issue is the use |
FWIW, unit test took ~4 seconds before the rebase and ~16 seconds after on my computer. Probably related to the work with not counting comments and whitespace lines, but the tests don't feel like unit tests anymore. Update Just seeing #401 addresses this now. |
* If none of the provided `RuleConfig`s are applicable, you can create one | ||
specifically for your rule. | ||
|
||
See [`ForceTryRule`](https://github.com/realm/SwiftLint/blob/master/Source/SwiftLintFramework/Rules/ForceCastRule.swift) |
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.
Mentions ForceTryRule
but links to ForceCastRule
.
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.
Good catch!
Actually your explanation makes sense:
Very useful and informative 👍 Thanks for adding the opt-in segment too! Other than my last few comments, big 👍 on this! |
… Configuration.rulesFromDict.
4d9f367
to
12aba5f
Compare
@jpsim I think we are all good here now. |
👍 💯 kudos. Can you make sure to close all the issues resolved by this? |
No problem. The 3 that are 100% addressed have been closed. What do you want to do with the 3 that this provided a solid workaround for? |
I think this PR is the best way to address #191, despite not being exactly what the user wanted, so I'd close that one as resolved. The other 2 can remain open. |
Wow! 🎉 |
🍕 |
Thanks for PR! Is there anyway to set severity for all rules? I want to make sure that build fails if any SwiftLint rule is violated. |
@derpoliuk What you want would be the
|
Configuration Structs
This PR expands upon the work in #314 and #354 by providing
struct
-based configurations for the common patterns and providing default conformance toConfigurableRule
via these structures.Key Benefits
Rule
s now have some sort of configuration available.SeverityConfig
)SeverityLevelsConfig
)min_length
andmax_length
(bothwarning
anderror
) as well as withexcluded
names. (NameConfig
)master
) by foldingVariableNameMinLengthRule
andVariableNameMaxLengthRule
intoVariableNameRule
.Key Drawbacks
ConfigProviderRule
s need to access their configuration viaconfig
and it's properties. This can be somewhat mitigated with more convenience computed properties.Example YAML
The following configuration is now possible.
Open Issues Addressed
severity
)excluded
)excluded
)Design Decisions
struct
s forRuleConfig
s to encapsulate configuration viaDictionary
s and also promote maximum reusability (e.g.NameConfig
uses twoSeverityLevelsConfig
s).ConfigurableRule
in place as a catch-all for non-standard configs (e.g.MissingDocsRule
)RuleConfig.setConfig(config:) throws
instead of a failable initializer for ingesting configuration dictionaries. This is to support the coexistence of default values and configured values so that partial configurations can be provided via the YAML.ConfigurableRule.init?(config:)
toConfigurableRule.init(config:) throws
to gracefully propograte theseConfigurationError
s.TODO
/cc @realm/swiftlint