-
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
Recursive Configs #301
Recursive Configs #301
Conversation
public func queuedPrintError(string: String) { | ||
dispatch_async(outputQueue) { | ||
fputs(string + "\n", stderr) | ||
public func queuedPrintError(string: String, silent: Bool = 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.
Instead of a silent
parameter that just bypasses the function like this, I'd rather just not call the function in the first place. Could you please revert this change?
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 because the new code results in a new configuration load for every file under a nested configuration, reverting this will result in dozens of "Loading configuration from " messages when using nested configs. I found this really obfuscates the logs. Another option would be to suppress the logging inside the init
function, but that didn't seem right to me. My intention here was to centralize the logging logic in one place so that the logger could decide how to process. Because we wouldn't have to hunt down selective logging in methods, this could potentially ease the transition to more robust logging if needed. So let me know which of the three solutions you'd like:
- Revert to original, which is the simplest but logs will be muddled with new load messages
- Put the selective logging logic in the
init
function which requires no change to logging functions, but makesinit
more complicated and sets the precedent of distributing logging logic to non-logging objects. - Put the selective logging logic in the logger which solves the above problems but results in a degenerative trivial silent logging case
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.
Put the selective logging logic in the init function which requires no change to logging functions, but makes init more complicated and sets the precedent of distributing logging logic to non-logging objects.
This is what I was trying to say. The logging in Configuration's initializer is already unfortunate but in fact, it should be relatively straightforward to move it to the swiftlint
CLI app instead, which would address the need to silence some configuration loads without polluting the model object with logging code.
Ideally, all logs would be in swiftlint
with none in SwiftLintFramework
.
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.
Ok, I will revert this and instead put the conditional logging inside of Configuration.init
. Stay tuned! :)
Logging is now suppressed in |
queuedPrintError("Loading configuration from '\(path)'") | ||
self.init(yaml: yamlContents)! | ||
if let yamlConfig = Configuration.loadYaml(yamlContents) { | ||
if !silent { |
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 IMO
This is looking quite good, @scottrhoyt! Please don't let my many comments discourage you 😉. It would be nice to have some tests for this. The rest of the project is pretty well tested IMO, so it'd be nice to keep that up here. It might make sense to introduce a |
…RuleParameter conform to Equatable. Wrote tests to verify. All done in support of testing recursive configuration file search.
@jpsim No worries. I can definitely sympathize with being a test nut. I wrote some tests for for this in the best way I could come up with. All in all, writing the tests took longer than the code (I hate when that happens), but that was mostly because of the things I needed to support the tests. This is what I did:
Let me know what you think. |
|
||
func == (lhs: [Rule], rhs: [Rule]) -> Bool { | ||
if lhs.count == rhs.count { | ||
return zip(lhs, rhs).map { $0.isEqualTo($1) }.reduce(true) { $0 && $1 } |
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 you can avoid creating the intermediate closures here:
zip(lhs, rhs).map(Rule.isEqualTo).reduce(true, &&)
- "the place where i commited many coding sins" | ||
line_length: 10000000000 | ||
reporter: "json" | ||
use_nested_configs: true |
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.
missing trailing newline here
This is looking really good, could you please add an entry to the CHANGELOG following these guidelines and add some basic documentation in the README? |
@jpsim CHANGELOG and README updated. Let me know if you need anything else. |
* realm/master: use SourceKitten 0.7.3 release [README] `excluded` overrides `included` only generate violations once for triggering examples in verifyRule() Support command comment modifiers [CHANGELOG] Fix entry [CHANGELOG] add entry Fix realm#295 Add failing test to ValidDocsRule.swift [CHANGELOG] Fix entry test violation locations [CHANGELOG] add entry Fix realm#294 # Conflicts: # CHANGELOG.md # README.md
I pulled master into my branch to resolve the conflicts in |
@@ -1 +1 @@ | |||
Subproject commit 0ed186552d8f9f3e128ab382581102c55c2d3c73 |
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.
@jpsim might want to make sure this is as intended? Seems to have been switched during merging master.
Many many thanks for this work @scottrhoyt! I made a few tweaks and merged in #307. |
Closes #299
Ok, so here is my first stab at the recursive folder configurations. I think that using a recursive folder search method for the entire linting process would greatly optimize nested configurations, but I implemented this using the simplest algorithm with the current linting search method.
Basically, the configuration to use in linting a file is now a function of the file. To find this configuration, we recursively search backwards from directory of the file until we either find the current config file, reach the root of the lint search, or we find a configuration file to
merge
with. In this initial implementation,merge
is simply overriding the config.NOTE I primarily put the additional code in an extension to avoid exceeding the line limit for the
Configuration
type, though I suppose it has some encapsulation value to it.Here are the things that I am still planning to add to this PR:
Configuration
from a yml to be more efficient (it's getting called a lot more)Let me know what you think so far and I'll continue adding commits to this PR.