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

Support configuration file #3

Closed
jpsim opened this issue May 18, 2015 · 10 comments
Closed

Support configuration file #3

jpsim opened this issue May 18, 2015 · 10 comments

Comments

@jpsim
Copy link
Collaborator

jpsim commented May 18, 2015

Something like a .swiftlint.yml or similar that could be used to override rule parameters or turn off certain rules globally. See #1.

@aarondaub
Copy link

What is the support for YAML like? Should we limit it to the JSON subset, or is YAML well enough supported?

@skywinder
Copy link

+1 👍
it will awesome to have .swiftlint.yml with custom rules.
as a good example of this approach is .rubocop.yml for ruby linter https://github.com/bbatsov/rubocop

@chriseidhof
Copy link
Contributor

I played around a bit, and came up with a possible solution. Maybe this is too complicated, so feel free to build something simpler ;).

For every Rule, we can make a separate struct which holds the configurable values. For example, for the TodoRule, we might want to configure the words:

struct TodoRuleConfiguration {
    var words = ["TODO", "FIXME"]
}

Now, if we want to capture the fact that words is an option, we can create a struct ConfigurationOption which allows us to describe the options name (e.g. this is what people specify in the YAML) and a way to apply it to a configuration of type A. Because we don't really know what type will come in, we will try to do a cast within the apply function, and return an updated A if this succeeeds. Otherwise we return nil (which means: couldn't parse option). This should probably return a Result rather than an optional.

struct ConfigurationOption<A> {
    let name: String
    let apply: (A, Any) -> A?
}

For example, one option would be the keywords option:

let keywordsOption = ConfigurationOption<TodoRuleConfiguration>(name: "keywords", apply: { (var copy, value) in
    if let words = value as? [String] {
      copy.words = words
      return copy
    }
    return nil
})

Now, to say that a configuration (e.g. TodoRuleConfiguration) has options, we can create a protocol:

protocol Configurable {
    var options: [ConfigurationOption<Self>] { get }
}

extension TodoRuleConfiguration: Configurable {
    var options = [keywordsOption]
}

And finally, now that we have all of that in place, we can write a simple applyConfiguration function, which takes a rule, a list of (untyped) option values (this can be a YAML dict, or JSON dict, or whatever) and returns a new rule with all the options applied. Again, this might also produce errors, not sure how we should handle them (hence the TODO).

func applyConfiguration<A: Configurable>(var rule: A, optionValues: [String:Any]) -> A {
    for option in rule.options {
        if let value = optionValues[option.name] {
            if let newRule = option.apply(rule, value) {
                rule = newRule
            } else {
                // TODO: option could not be parsed
            }
        }
    }
    return rule
}

I realize this might look complicated, but I think it should be easy to work with. The nice thing about making it all explicit is that we can also generate documentation for the options, and we can easily add some more fields to the ConfigurationOption struct, (e.g. a short description of the option).

@jpsim
Copy link
Collaborator Author

jpsim commented Jun 2, 2015

It does seem a bit complicated, and maybe even overlapping with the concepts of RuleParameter/ParameterizedRule, but I think that once a draft implementation is done, some of these concerns will naturally go away just by getting to a working state.

So in other words, go for it! 😄

@bsrz
Copy link

bsrz commented Jun 24, 2015

@jpsim I'm coming in late in this conversation but has the option of passing parameters at the command line been looked into?

./swiftlint --max-characters 120

@jpsim
Copy link
Collaborator Author

jpsim commented Jun 24, 2015

not as command line arguments, no.

@bsrz
Copy link

bsrz commented Jun 24, 2015

Has it been rejected?

@jpsim
Copy link
Collaborator Author

jpsim commented Jun 24, 2015

No, it hasn't been considered. Really the mechanics for enabling command line arguments as rule parameters are very similar to doing so via a configuration file. Feel free to take a stab at implementing that if you'd like.

@bsrz
Copy link

bsrz commented Jun 24, 2015

Ok, sounds good!
Thanks for the information, I'll try to find some time to try this out.

@jpsim
Copy link
Collaborator Author

jpsim commented Aug 28, 2015

Done in #99.

@jpsim jpsim closed this as completed Aug 28, 2015
jpsim added a commit that referenced this issue Jan 17, 2023
This frequently crashes and I don't think it's due to a real TSan race.

E.g. https://buildkite.com/swiftlint/swiftlint/builds/4912#0185c098-a803-4525-8df1-827d1c97ed01

```
swiftlint(373,0x1ecdd3a80) malloc: nano zone abandoned due to inability to preallocate reserved vm space.
Linting Swift files in current working directory
1 of 538 [                              ] ETA: 0s (13129 files/s)
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
ThreadSanitizer:DEADLYSIGNAL
==373==ERROR: ThreadSanitizer: SEGV on unknown address 0x000000000008 (pc 0x000102cbe380 bp 0x00016f50ee00 sp 0x00016f50edc0 T30753687)
==373==The signal is caused by a UNKNOWN memory access.
==373==Hint: address points to the zero page.
    #0 __tsan::ThreadClock::release(__tsan::DenseSlabAllocCache*, __tsan::SyncClock*) <null>:46801128 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x2a380)
    #1 __tsan::Release(__tsan::ThreadState*, unsigned long, unsigned long) <null>:46801128 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x7456c)
    #2 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:46801128 (libswift_Concurrency.dylib:arm64e+0x40588)
    #3 swift_job_runImpl(swift::Job*, swift::ExecutorRef) <null>:46801128 (libswift_Concurrency.dylib:arm64e+0x41404)
    #4 _dispatch_root_queue_drain <null>:46801128 (libdispatch.dylib:arm64e+0x15f90)
    #5 _dispatch_worker_thread2 <null>:46801128 (libdispatch.dylib:arm64e+0x167bc)
    #6 _pthread_wqthread <null>:46801128 (libsystem_pthread.dylib:arm64e+0x30c0)
    #7 start_wqthread <null>:46801128 (libsystem_pthread.dylib:arm64e+0x1e1c)

==373==Register values:
 x[0] = 0x0000000102a53458   x[1] = 0x0000000000000538   x[2] = 0x0000000000000000   x[3] = 0x0000000000000000
 x[4] = 0x0000000000000001   x[5] = 0x0000000000000000   x[6] = 0x0095000004220122   x[7] = 0x0000000000000001
 x[8] = 0x0000000000000008   x[9] = 0x0000000000000000  x[10] = 0x0000000000000000  x[11] = 0x0000000000000000
x[12] = 0x0000000000000020  x[13] = 0x0000000110904040  x[14] = 0x0000000000000000  x[15] = 0x0000000106251910
x[16] = 0x0000000104190960  x[17] = 0x0000000000200018  x[18] = 0x0000000000000000  x[19] = 0x000000010f5d3488
x[20] = 0x0000000109ca03f0  x[21] = 0x0000000102a53458  x[22] = 0x0000000109ca03f0  x[23] = 0x0000000109cc0078
x[24] = 0x00040c0000fd77c4  x[25] = 0x0000010000000000  x[26] = 0x00000002287898f8  x[27] = 0x0000000000000000
x[28] = 0x000000016f50f0e0     fp = 0x000000016f50ee00     lr = 0x0000000102cbe360     sp = 0x000000016f50edc0
ThreadSanitizer can not provide additional info.
SUMMARY: ThreadSanitizer: SEGV (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x2a380) in __tsan::ThreadClock::release(__tsan::DenseSlabAllocCache*, __tsan::SyncClock*)+0x174
==373==ABORTING
```
jpsim added a commit that referenced this issue Jan 17, 2023
This frequently crashes and I don't think it's due to a real TSan race.

E.g. https://buildkite.com/swiftlint/swiftlint/builds/4912#0185c098-a803-4525-8df1-827d1c97ed01

```
swiftlint(373,0x1ecdd3a80) malloc: nano zone abandoned due to inability to preallocate reserved vm space.
Linting Swift files in current working directory
1 of 538 [                              ] ETA: 0s (13129 files/s)
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
ThreadSanitizer:DEADLYSIGNAL
==373==ERROR: ThreadSanitizer: SEGV on unknown address 0x000000000008 (pc 0x000102cbe380 bp 0x00016f50ee00 sp 0x00016f50edc0 T30753687)
==373==The signal is caused by a UNKNOWN memory access.
==373==Hint: address points to the zero page.
    #0 __tsan::ThreadClock::release(__tsan::DenseSlabAllocCache*, __tsan::SyncClock*) <null>:46801128 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x2a380)
    #1 __tsan::Release(__tsan::ThreadState*, unsigned long, unsigned long) <null>:46801128 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x7456c)
    #2 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:46801128 (libswift_Concurrency.dylib:arm64e+0x40588)
    #3 swift_job_runImpl(swift::Job*, swift::ExecutorRef) <null>:46801128 (libswift_Concurrency.dylib:arm64e+0x41404)
    #4 _dispatch_root_queue_drain <null>:46801128 (libdispatch.dylib:arm64e+0x15f90)
    #5 _dispatch_worker_thread2 <null>:46801128 (libdispatch.dylib:arm64e+0x167bc)
    #6 _pthread_wqthread <null>:46801128 (libsystem_pthread.dylib:arm64e+0x30c0)
    #7 start_wqthread <null>:46801128 (libsystem_pthread.dylib:arm64e+0x1e1c)

==373==Register values:
 x[0] = 0x0000000102a53458   x[1] = 0x0000000000000538   x[2] = 0x0000000000000000   x[3] = 0x0000000000000000
 x[4] = 0x0000000000000001   x[5] = 0x0000000000000000   x[6] = 0x0095000004220122   x[7] = 0x0000000000000001
 x[8] = 0x0000000000000008   x[9] = 0x0000000000000000  x[10] = 0x0000000000000000  x[11] = 0x0000000000000000
x[12] = 0x0000000000000020  x[13] = 0x0000000110904040  x[14] = 0x0000000000000000  x[15] = 0x0000000106251910
x[16] = 0x0000000104190960  x[17] = 0x0000000000200018  x[18] = 0x0000000000000000  x[19] = 0x000000010f5d3488
x[20] = 0x0000000109ca03f0  x[21] = 0x0000000102a53458  x[22] = 0x0000000109ca03f0  x[23] = 0x0000000109cc0078
x[24] = 0x00040c0000fd77c4  x[25] = 0x0000010000000000  x[26] = 0x00000002287898f8  x[27] = 0x0000000000000000
x[28] = 0x000000016f50f0e0     fp = 0x000000016f50ee00     lr = 0x0000000102cbe360     sp = 0x000000016f50edc0
ThreadSanitizer can not provide additional info.
SUMMARY: ThreadSanitizer: SEGV (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x2a380) in __tsan::ThreadClock::release(__tsan::DenseSlabAllocCache*, __tsan::SyncClock*)+0x174
==373==ABORTING
```
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

No branches or pull requests

5 participants