sugarcane 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 584226c2dcce2cb64f8634a831906986f21f92f2
4
+ data.tar.gz: 6a906ebfd9c1088440dfc76fd2db8ca621bac061
5
+ SHA512:
6
+ metadata.gz: 40e65acb33a378c9e7f779750dee561d982c6aedeb19a24141313657e53b6a8407ec876b23aa6cafbdc9911087758152f5a04d8ba7aeb129a800ec5e801cc5c3
7
+ data.tar.gz: 78dfc2e99724f66855473ae69c06923989dbc5266d1daf4819e3ceec99039feb28be21ea170a3d769c57ab6141e0ab71399b018a11f81de7188a9805fec19a0c
data/HISTORY.md ADDED
@@ -0,0 +1,126 @@
1
+ # SugarCane History
2
+
3
+ ## 0.0.1 - 6 February 2014
4
+
5
+ * Feature: Menu that takes you from a violation to the line in a text editor
6
+ * Change: expect .sugarcane or .cane configuration files
7
+ * Change: old cane functionality with --report
8
+
9
+ # Cane History
10
+
11
+ ## 2.6.1 - 30 October 2013 (2ea008)
12
+
13
+ * Feature: Don't require doc for one-line class w/out method.
14
+ * Bugfix: JsonFormatter initializer needs to take an options hash.
15
+ * Doc: Add license definition to gemspec.
16
+
17
+ ## 2.6.0 - 7 June 2013 (616bb8a5)
18
+
19
+ * Feature: classes with no methods do not require documentation.
20
+ * Feature: modules with methods require documentation.
21
+ * Feature: support all README extensions.
22
+ * Feature: --color option.
23
+ * Bugfix: fix false positive on class matching for doc check.
24
+ * Bugfix: better handling of invalid strings.
25
+ * Compat: fix Ruby 2.0 deprecations.
26
+
27
+ ## 2.5.2 - 26 January 2013 (a0cf38ba)
28
+
29
+ * Feature: support operators beside `>=` in threshold check.
30
+
31
+ ## 2.5.1 - 26 January 2013 (93819f19)
32
+
33
+ * Feature: documentation check supports `.mdown` and `.rdoc` extensions.
34
+ * Feature: expanded threshold regex to support `coverage/.last_run.json` from
35
+ `SimpleCov`.
36
+ * Compat: Ruby 2.0 compatibility.
37
+
38
+ ## 2.5.0 - 17 November 2012 (628cc1e9)
39
+
40
+ * Feature: `--doc-exclude` option to exclude globs from documentation checks.
41
+ * Feature: `--style-exclude` supports globbing.
42
+
43
+ ## 2.4.0 - 21 October 2012 (46949e77)
44
+
45
+ * Feature: Rake task can load configuration from a `.cane` file.
46
+ * Feature: Coverage threshold can be specifed in a file.
47
+ * Feature: Provide `--all` option for working with single files.
48
+ * Bugfix: Allow README file to be lowercase.
49
+
50
+ ## 2.3.0 - 16 September 2012 (229252ff)
51
+
52
+ * Feature: `--json` option for machine-readable output.
53
+ * Feature: absence of a README will cause a failure.
54
+ * Bugfix: `--no-style` option actually works now.
55
+
56
+ ## 2.2.3 - 3 September 2012 (e4fe90ee)
57
+
58
+ * Bugfix: Allow multiple spaces before class name. (#34)
59
+ * Bugfix: Remove wacky broken conditional in AbcCheck. (#33)
60
+ * Doc: Better guidance on class level comments. (#35)
61
+
62
+ ## 2.2.2 - 29 August 2012 (3a9be454)
63
+
64
+ * Bugfix: Stricter magic comment regex to avoid false positives (#31)
65
+
66
+ ## 2.2.1 - 26 August 2012 (b5e5a362)
67
+
68
+ * Bugfix: parallel option can be set in rake tasks
69
+
70
+ ## 2.2.0 - 26 August 2012 (f4198619)
71
+
72
+ * Gracefully handle ambiguous options like `-abc-max` (#27)
73
+ * Provide the `--parallel` option to use all processors. This will be faster on
74
+ larger projects, but slower on smaller ones (#28)
75
+
76
+ ## 2.1.0 - 26 August 2012 (2962d8fb)
77
+
78
+ * Support for user-defined checks (#30)
79
+
80
+ ## 2.0.0 - 19 August 2012 (35cae086)
81
+
82
+ * ABC check labels `MyClass = Struct.new {}` and `Class.new` correctly (#20)
83
+ * Magic comments (`# encoding: utf-8`) are not recognized as appropriate class documentation (#21)
84
+ * Invalid UTF-8 is handled correctly (#22)
85
+ * Gracefully handle unknown options
86
+ * ABC check output uses a standard format (`Foo::Bar#method` rather than `Foo > Bar > method`)
87
+ * **BREAKING** Add `--abc-exclude`, `--style-exclude` CLI flags, remove YAML support
88
+ * **BREAKING-INTERNAL** Use hashes rather than explicit violation classes
89
+ * **BREAKING-INTERNAL** Remove translator class, pass CLI args direct to checks
90
+ * **INTERNAL** Wiring in a new check only requires changing one file (#15)
91
+
92
+ This snippet will convert your YAML exclusions file to the new CLI syntax:
93
+
94
+ y = YAML.load(File.read('exclusions.yml'))
95
+ puts (
96
+ y.fetch('abc', []).map {|x| %|--abc-exclude "#{x}"| } +
97
+ y.fetch('style', []).map {|x| %|--style-exclude "#{x}"| }
98
+ ).join("\n")
99
+
100
+ ## 1.4.0 - 2 July 2012 (1afc999d)
101
+
102
+ * Allow files and methods to be whitelisted (#16)
103
+ * Show total number of violations in output (#14)
104
+
105
+ ## 1.3.0 - 20 April 2012 (c166dfa0)
106
+
107
+ * Remove dependency on tailor. Fewer styles checks are performed, but the three
108
+ remaining are the only ones I've found useful.
109
+
110
+ ## 1.2.0 - 31 March 2012 (adce51b9)
111
+
112
+ * Gracefully handle files with invalid syntax (#1)
113
+ * Included class methods in ABC check (#8)
114
+ * Can disable style and doc checks from rake task (#9)
115
+
116
+ ## 1.1.0 - 24 March 2012 (ba8a74fc)
117
+
118
+ * `app` added to default globs
119
+ * Added `cane/rake_task`
120
+ * `class << obj` syntax ignore by documentation check
121
+ * Line length checks no longer include trailing new lines
122
+ * Add support for a `.cane` file for setting per-project default options.
123
+
124
+ ## 1.0.0 - 14 January 2012 (4e400534)
125
+
126
+ * Initial release.
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+
2
+ Copyright 2012 Square Inc.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,235 @@
1
+ [![Build Status](https://travis-ci.org/rlqualls/sugarcane.png?branch=master)](https://travis-ci.org/rlqualls/sugarcane)
2
+ [![Coverage Status](https://coveralls.io/repos/rlqualls/sugarcane/badge.png)](https://coveralls.io/r/rlqualls/sugarcane)
3
+ [![Code Climate](https://codeclimate.com/github/rlqualls/sugarcane.png)](https://codeclimate.com/github/rlqualls/sugarcane)
4
+
5
+ ![sugarcane screenshot](http://i.imgur.com/RP7xDLU.png)
6
+
7
+ > It's best to get beat with something sweet...
8
+
9
+ **Sugarcane** is an enhancement of the **cane** code quality tool. It makes various
10
+ minor changes, but most importantly, it closes the gap between the text editor
11
+ and cane.
12
+
13
+ You can find the original cane project at [square/cane](https://github.com/square/cane)
14
+
15
+ ## Features
16
+
17
+ - Go straight from violations to their lines in a text editor
18
+ - Otherwise does what cane does
19
+ - Editors supported: sublimetext (untested), vim, gedit, nano
20
+
21
+ ## Controls
22
+
23
+ - K,W, UP - up
24
+ - J,S, DOWN - down
25
+ - Q,X - quit
26
+ - O, Enter, Space - open file in text editor at the violation
27
+
28
+ ## Installation
29
+
30
+ $ gem install sugarcane
31
+
32
+ ## Installation (development)
33
+
34
+ $ git clone https://github.com/rlqualls/sugarcane
35
+ $ cd sugarcane
36
+ $ bundle
37
+ $ rake install
38
+
39
+ ## Usage Examples
40
+
41
+ To run the default checks on all files in your project, navigate to the
42
+ project root and run sugarcane
43
+
44
+ $ sugarcane
45
+
46
+ If you just want to run all checks on a specific file:
47
+
48
+ $ sugarcane -f README.md
49
+
50
+ If you want to run checks on files matching a pattern:
51
+
52
+ $ sugarcane --abc-glob '{lib,spec}/**/*.rb' --abc-max 15
53
+
54
+ Sugarcane tries to find an editor in your PATH, choosing sublime then vim
55
+ first if one is available. You can specify a different editor with `--editor`.
56
+
57
+ $ sugarcane --editor nano
58
+ $ sugarcane --editor=gedit
59
+
60
+ **NOTE**: Right now, navigating to a line number relies on the convention
61
+ of `+<num_lines>` as an argument (sublimetext is included as an exception).
62
+
63
+ ## Not far from the Tree
64
+
65
+ For original `cane` functionality, add the --report option
66
+
67
+ $ sugarcane --report
68
+
69
+ Methods exceeded maximum allowed ABC complexity (2):
70
+
71
+ lib/sugarcane.rb Cane#sample 23
72
+ lib/sugarcane.rb Cane#sample_2 17
73
+
74
+ Lines violated style requirements (2):
75
+
76
+ lib/sugarcane.rb:20 Line length >80
77
+ lib/sugarcane.rb:42 Trailing whitespace
78
+
79
+ Class definitions require explanatory comments on preceding line (1):
80
+ lib/sugarcane:3 SomeClass
81
+
82
+ ## Options
83
+
84
+ $ sugarcane --help
85
+ Usage: sugarcane [options]
86
+
87
+ Default options are loaded from a .sugarcane file in the current directory.
88
+
89
+ -r, --require FILE Load a Ruby file containing user-defined checks
90
+ -c, --check CLASS Use the given user-defined check
91
+
92
+ --abc-glob GLOB Glob to run ABC metrics over (default: {app,lib}/**/*.rb)
93
+ --abc-max VALUE Ignore methods under this complexity (default: 15)
94
+ --abc-exclude METHOD Exclude method from analysis (eg. Foo::Bar#method)
95
+ --no-abc Disable ABC checking
96
+
97
+ --style-glob GLOB Glob to run style checks over (default: {app,lib,spec}/**/*.rb)
98
+ --style-measure VALUE Max line length (default: 80)
99
+ --style-exclude GLOB Exclude file or glob from style checking
100
+ --no-style Disable style checking
101
+
102
+ --doc-glob GLOB Glob to run doc checks over (default: {app,lib}/**/*.rb)
103
+ --doc-exclude GLOB Exclude file or glob from documentation checking
104
+ --no-readme Disable readme checking
105
+ --no-doc Disable documentation checking
106
+
107
+ --lt FILE,THRESHOLD Check the number in FILE is < to THRESHOLD (a number or another file name)
108
+ --lte FILE,THRESHOLD Check the number in FILE is <= to THRESHOLD (a number or another file name)
109
+ --eq FILE,THRESHOLD Check the number in FILE is == to THRESHOLD (a number or another file name)
110
+ --gte FILE,THRESHOLD Check the number in FILE is >= to THRESHOLD (a number or another file name)
111
+ --gt FILE,THRESHOLD Check the number in FILE is > to THRESHOLD (a number or another file name)
112
+
113
+ -f, --all FILE Apply all checks to given file
114
+ --max-violations VALUE Max allowed violations (default: 0)
115
+ --editor PROGRAM Text editor to use
116
+ --json Output as JSON
117
+ --report Original cane output
118
+ --parallel Use all processors. Slower on small projects, faster on large.
119
+ --color Colorize output
120
+
121
+ -v, --version Show version
122
+ -h, --help Show this message
123
+
124
+ ## Configuration Files
125
+
126
+ Set default options using a `.cane` or '.sugarcane'. This is easier than telling
127
+ sugarcane what editor you want to use every time.
128
+
129
+ $ cat .sugarcane
130
+ --no-doc
131
+ --abc-glob **/*.rb
132
+ --editor gedit
133
+
134
+ It works exactly the same as specifying the options on the command-line.
135
+ Command-line arguments will override arguments specified in the configuration
136
+ file. Sugarcane will ignore a `.cane` file if it sees a `.sugarcane` file.
137
+
138
+ ## Integrating with Rake
139
+
140
+ Sugarcane retains the ability to create rake tasks. The tasks will look for
141
+ configuration files the same way running sugarcane normally does. The build
142
+ will fail if the task finds more than `max_violations` violations which is 0
143
+ by default. Keep this in mind if using sugarcane tasks in continuous
144
+ integration.
145
+
146
+ ```ruby
147
+ require 'sugarcane/rake_task'
148
+
149
+ desc "Run sugarcane to check quality metrics"
150
+ SugarCane::RakeTask.new(:quality)
151
+
152
+ task :default => :quality
153
+ end
154
+ ```
155
+
156
+ Instead of using a configuration file, you can specify options in a block.
157
+ Rescuing `LoadError` is a good idea, since `rake -T` failing is totally
158
+ frustrating.
159
+
160
+ ```ruby
161
+ begin
162
+ require 'sugarcane/rake_task'
163
+
164
+ desc "Run sugarcane to check quality metrics"
165
+ SugarCane::RakeTask.new(:quality) do |cane|
166
+ cane.abc_max = 10
167
+ cane.no_style = true
168
+ cane.max_violations = 3
169
+ cane.abc_exclude = %w(Foo::Bar#some_method)
170
+ end
171
+
172
+ task :default => :quality
173
+ rescue LoadError
174
+ warn "sugarcane not available, quality task not provided."
175
+ end
176
+ ```
177
+
178
+ If you have multiple configuration files, you can specify which one to use
179
+ with `SugarCane::RakeTask#canefile=`. For that, the name does not matter.
180
+
181
+ ## Implementing your own checks
182
+
183
+ Checks must implement:
184
+
185
+ * A class level `options` method that returns a hash of available options. This
186
+ will be included in help output if the check is added before `--help`. If
187
+ your check does not require any configuration, return an empty hash.
188
+ * A one argument constructor, into which will be passed the options specified
189
+ for your check.
190
+ * A `violations` method that returns an array of violations.
191
+
192
+ See existing checks for guidance. Create your check in a new file:
193
+
194
+ ```ruby
195
+ # unhappy.rb
196
+ class UnhappyCheck < Struct.new(:opts)
197
+ def self.options
198
+ {
199
+ unhappy_file: ["File to check", default: [nil]]
200
+ }
201
+ end
202
+
203
+ def violations
204
+ [
205
+ description: "Files are unhappy",
206
+ file: opts.fetch(:unhappy_file),
207
+ label: ":("
208
+ ]
209
+ end
210
+ end
211
+ ```
212
+
213
+ Include your check either using command-line options:
214
+
215
+ sugarcane -r unhappy.rb --check UnhappyCheck --unhappy-file myfile
216
+
217
+ Or in your rake task:
218
+
219
+ ```ruby
220
+ require 'unhappy'
221
+
222
+ SugarCane::RakeTask.new(:quality) do |c|
223
+ c.use UnhappyCheck, unhappy_file: 'myfile'
224
+ end
225
+ ```
226
+ ## Compatibility
227
+
228
+ Requires MRI 1.9, since it depends on the `ripper` library to calculate
229
+ complexity metrics. This only applies to the Ruby used to run SugarCane, not the
230
+ project it is being run against. In other words, you can run Cane against your
231
+ 1.8 or JRuby project.
232
+
233
+ ## Support
234
+
235
+ Make a [new github issue](https://github.com/rlqualls/sugarcane/issues/new).
data/bin/sugarcane ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'sugarcane/cli'
4
+
5
+ result = SugarCane::CLI.run(ARGV)
6
+
7
+ exit(1) unless result
data/lib/cane.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'ncursesw'
2
+ require 'cane/menu'
3
+ require 'cane/cli'
4
+ require 'cane/version'
@@ -0,0 +1,216 @@
1
+ require 'ripper'
2
+ require 'set'
3
+
4
+ require 'sugarcane/file'
5
+ require 'sugarcane/ext/array'
6
+ require 'sugarcane/task_runner'
7
+
8
+ module SugarCane
9
+
10
+ # Creates violations for methods that are too complicated using a simple
11
+ # algorithm run against the parse tree of a file to count assignments,
12
+ # branches, and conditionals. Borrows heavily from metric_abc.
13
+ class AbcCheck < Struct.new(:opts)
14
+
15
+ def self.key; :abc; end
16
+ def self.name; "ABC check"; end
17
+ def self.options
18
+ {
19
+ abc_glob: ['Glob to run ABC metrics over',
20
+ default: '{app,lib}/**/*.rb',
21
+ variable: 'GLOB',
22
+ clobber: :no_abc],
23
+ abc_max: ['Ignore methods under this complexity',
24
+ default: 15,
25
+ cast: :to_i,
26
+ clobber: :no_abc],
27
+ abc_exclude: ['Exclude method from analysis (eg. Foo::Bar#method)',
28
+ variable: 'METHOD',
29
+ type: Array,
30
+ default: [],
31
+ clobber: :no_abc],
32
+ no_abc: ['Disable ABC checking',
33
+ cast: ->(x) { !x }]
34
+ }
35
+ end
36
+
37
+ def violations
38
+ return [] if opts[:no_abc]
39
+
40
+ order worker.map(file_names) {|file_name|
41
+ find_violations(file_name)
42
+ }.flatten
43
+ end
44
+
45
+ protected
46
+
47
+ def find_violations(file_name)
48
+ ast = Ripper::SexpBuilder.new(SugarCane::File.contents(file_name)).parse
49
+ case ast
50
+ when nil
51
+ ast_type = InvalidAst.new(file_name)
52
+ else
53
+ ast_type = RubyAst.new(file_name, max_allowed_complexity,
54
+ ast, exclusions)
55
+ end
56
+ ast_type.violations
57
+ end
58
+
59
+ # Null object for when the file cannot be parsed.
60
+ class InvalidAst < Struct.new(:file_name)
61
+ def violations
62
+ [{file: file_name, description: "File contained invalid syntax"}]
63
+ end
64
+ end
65
+
66
+ # Wrapper object around sexps returned from ripper.
67
+ class RubyAst < Struct.new(:file_name, :max_allowed_complexity,
68
+ :sexps, :exclusions)
69
+
70
+ def initialize(*args)
71
+ super
72
+ self.anon_method_add = true
73
+ end
74
+
75
+ def violations
76
+ process_ast(sexps).
77
+ select do
78
+ |nesting, complexity| complexity[:value] > max_allowed_complexity
79
+ end.
80
+ map do |violation|
81
+ {
82
+ # Here, a violation is an array, like:
83
+ # ["Class#method", {:value => xx, :line => xx}]
84
+ file: file_name,
85
+ line: violation.last[:line],
86
+ label: violation.first,
87
+ value: violation.last[:value],
88
+ description: "Methods exceeded maximum allowed ABC complexity",
89
+ menu_description: "#{violation.first} exceeded maximum "\
90
+ "ABC complexity"
91
+ }
92
+ end
93
+ end
94
+
95
+ protected
96
+
97
+ # Stateful flag used to determine whether we are currently parsing an
98
+ # anonymous class. See #container_label.
99
+ attr_accessor :anon_method_add
100
+
101
+ # Recursive function to process an AST. The `complexity` variable mutates,
102
+ # which is a bit confusing. `nesting` does not.
103
+ def process_ast(node, complexity = {}, nesting = [])
104
+ if method_nodes.include?(node[0])
105
+ nesting = nesting + [label_for(node)]
106
+ desc = method_description(node, *nesting)
107
+ unless excluded?(desc)
108
+ complexity[desc] = {
109
+ :value => calculate_abc(node),
110
+ :line => node.line_number
111
+ }
112
+ end
113
+ elsif parent = container_label(node)
114
+ nesting = nesting + [parent]
115
+ end
116
+
117
+ if node.is_a? Array
118
+ node[1..-1].each {|n| process_ast(n, complexity, nesting) if n }
119
+ end
120
+ complexity
121
+ end
122
+
123
+ def calculate_abc(method_node)
124
+ a = count_nodes(method_node, assignment_nodes)
125
+ b = count_nodes(method_node, branch_nodes) + 1
126
+ c = count_nodes(method_node, condition_nodes)
127
+ abc = Math.sqrt(a**2 + b**2 + c**2).round
128
+ abc
129
+ end
130
+
131
+ def container_label(node)
132
+ if container_nodes.include?(node[0])
133
+ # def foo, def self.foo
134
+ node[1][-1][1]
135
+ elsif node[0] == :method_add_block
136
+ if anon_method_add
137
+ # Class.new do ...
138
+ "(anon)"
139
+ else
140
+ # MyClass = Class.new do ...
141
+ # parent already added when processing a parent node
142
+ anon_method_add = true
143
+ nil
144
+ end
145
+ elsif node[0] == :assign && node[2][0] == :method_add_block
146
+ # MyClass = Class.new do ...
147
+ self.anon_method_add = false
148
+ node[1][-1][1]
149
+ end
150
+ end
151
+
152
+ def label_for(node)
153
+ # A default case is deliberately omitted since I know of no way this
154
+ # could fail and want it to fail fast.
155
+ node.detect {|x|
156
+ [:@ident, :@op, :@kw, :@const, :@backtick].include?(x[0])
157
+ }[1]
158
+ end
159
+
160
+ def count_nodes(node, types)
161
+ node.flatten.select {|n| types.include?(n) }.length
162
+ end
163
+
164
+ def assignment_nodes
165
+ [:assign, :opassign]
166
+ end
167
+
168
+ def method_nodes
169
+ [:def, :defs]
170
+ end
171
+
172
+ def container_nodes
173
+ [:class, :module]
174
+ end
175
+
176
+ def branch_nodes
177
+ [:call, :fcall, :brace_block, :do_block]
178
+ end
179
+
180
+ def condition_nodes
181
+ [:==, :===, :"<>", :"<=", :">=", :"=~", :>, :<, :else, :"<=>"]
182
+ end
183
+
184
+ METH_CHARS = { def: '#', defs: '.' }
185
+
186
+ def excluded?(method_description)
187
+ exclusions.include?(method_description)
188
+ end
189
+
190
+ def method_description(node, *modules, meth_name)
191
+ separator = METH_CHARS.fetch(node.first)
192
+ description = [modules.join('::'), meth_name].join(separator)
193
+ end
194
+ end
195
+
196
+ def file_names
197
+ Dir[opts.fetch(:abc_glob)]
198
+ end
199
+
200
+ def order(result)
201
+ result.sort_by {|x| x[:value].to_i }.reverse
202
+ end
203
+
204
+ def max_allowed_complexity
205
+ opts.fetch(:abc_max)
206
+ end
207
+
208
+ def exclusions
209
+ opts.fetch(:abc_exclude, []).flatten.to_set
210
+ end
211
+
212
+ def worker
213
+ SugarCane.task_runner(opts)
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,30 @@
1
+ require 'sugarcane/default_checks'
2
+
3
+ module SugarCane
4
+ # Default options for command line interface
5
+ module CLI
6
+ def defaults(check)
7
+ check.options.each_with_object({}) {|(k, v), h|
8
+ option_opts = v[1] || {}
9
+ if option_opts[:type] == Array
10
+ h[k] = []
11
+ else
12
+ h[k] = option_opts[:default]
13
+ end
14
+ }
15
+ end
16
+ module_function :defaults
17
+
18
+ def default_options
19
+ {
20
+ max_violations: 0,
21
+ parallel: false,
22
+ exclusions_file: nil,
23
+ checks: SugarCane.default_checks
24
+ }.merge(SugarCane.default_checks.inject({}) {|a, check|
25
+ a.merge(defaults(check))
26
+ })
27
+ end
28
+ module_function :default_options
29
+ end
30
+ end