sugarcane 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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