codeclimate 0.29.0 → 0.30.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: efa08f642f16f2216254aad188d1e577569710cd
4
- data.tar.gz: cab24ce9e68f7cb1622d0549dc3608b8901b86c3
3
+ metadata.gz: a3f32cefb371cbbde1e958f6e6249101cd6aaba0
4
+ data.tar.gz: 63bf94a4ec496821d32a185247ab24a5b52502ba
5
5
  SHA512:
6
- metadata.gz: c8e00338ff2aed40e05240529f434a6a01f6c57a0bc2e4230079d34a653da771bf9cf3fd09abe6aec7115085da49304d813dd0460903a9141a1d1abbce21c81d
7
- data.tar.gz: 9f91b473418c645f5bcf1c78cd6cfd2e8f1e603165b5d9d97dbab3d974880d423b6eec6b86b1e6f22a9792933d3f30ee3ee344cd05e9d104ee7f6e2ca168716e
6
+ metadata.gz: b847ba8b39c19a3e5f17254271aeee4641cbc0bf95ff8c383a10ff24f354c40ad21e57de65093953cb8d334c528214c2840744d6a66018a62b1ffa8ed80c6754
7
+ data.tar.gz: d912d8ead585a16848ea2f06b35cc5dafdf3853fdcad8ab45aacb8db7de9446ec9e86e5de7b806d10c9bf2bafc008de8655965b01a5da8c7199d9a516fbc6825
@@ -1,8 +1,8 @@
1
1
  # This file lists all the engines available to be run for analysis.
2
2
  #
3
- # Each engine must have an `image` and `description`. The value in `image` will
4
- # be passed to `docker run` and so may be any value appropriate for that
5
- # (repo/name:tag, image id, etc).
3
+ # Each engine must have `channels` (with a `stable` key) and `description`. The
4
+ # values in `channels` will be passed to `docker run` and so may be any value
5
+ # appropriate for that (repo/name:tag, image id, etc).
6
6
  #
7
7
  # When a repo has files that match the `enable_regexps`, that engine will be
8
8
  # enabled by default in the codeclimate.yml file. That file will also have in it
@@ -10,7 +10,8 @@
10
10
  # which files should be rated.
11
11
  #
12
12
  brakeman:
13
- image: codeclimate/codeclimate-brakeman
13
+ channels:
14
+ stable: codeclimate/codeclimate-brakeman
14
15
  description: Static analysis tool which checks Ruby on Rails applications for security vulnerabilities.
15
16
  community: false
16
17
  upgrade_languages:
@@ -25,7 +26,8 @@ brakeman:
25
26
  - "**.rhtml"
26
27
  - "**.slim"
27
28
  bundler-audit:
28
- image: codeclimate/codeclimate-bundler-audit
29
+ channels:
30
+ stable: codeclimate/codeclimate-bundler-audit
29
31
  description: Patch-level verification for Bundler.
30
32
  community: false
31
33
  upgrade_languages:
@@ -35,7 +37,8 @@ bundler-audit:
35
37
  default_ratings_paths:
36
38
  - Gemfile.lock
37
39
  csslint:
38
- image: codeclimate/codeclimate-csslint
40
+ channels:
41
+ stable: codeclimate/codeclimate-csslint
39
42
  description: Automated linting of Cascading Stylesheets.
40
43
  community: false
41
44
  enable_regexps:
@@ -43,7 +46,8 @@ csslint:
43
46
  default_ratings_paths:
44
47
  - "**.css"
45
48
  coffeelint:
46
- image: codeclimate/codeclimate-coffeelint
49
+ channels:
50
+ stable: codeclimate/codeclimate-coffeelint
47
51
  description: A style checker for CoffeeScript.
48
52
  community: false
49
53
  enable_regexps:
@@ -51,7 +55,8 @@ coffeelint:
51
55
  default_ratings_paths:
52
56
  - "**.coffee"
53
57
  duplication:
54
- image: codeclimate/codeclimate-duplication
58
+ channels:
59
+ stable: codeclimate/codeclimate-duplication
55
60
  description: Structural duplication detection for Ruby, Python, JavaScript, and PHP.
56
61
  community: false
57
62
  enable_regexps:
@@ -77,7 +82,8 @@ duplication:
77
82
  - python
78
83
  - php
79
84
  eslint:
80
- image: codeclimate/codeclimate-eslint
85
+ channels:
86
+ stable: codeclimate/codeclimate-eslint
81
87
  description: A JavaScript/JSX linting utility.
82
88
  community: false
83
89
  upgrade_languages:
@@ -89,7 +95,8 @@ eslint:
89
95
  - "**.js"
90
96
  - "**.jsx"
91
97
  gofmt:
92
- image: codeclimate/codeclimate-gofmt
98
+ channels:
99
+ stable: codeclimate/codeclimate-gofmt
93
100
  description: Checks the formatting of Go programs.
94
101
  community: true
95
102
  enable_regexps:
@@ -97,7 +104,8 @@ gofmt:
97
104
  default_ratings_paths:
98
105
  - "**.go"
99
106
  golint:
100
- image: codeclimate/codeclimate-golint
107
+ channels:
108
+ stable: codeclimate/codeclimate-golint
101
109
  description: A linter for Go.
102
110
  community: true
103
111
  enable_regexps:
@@ -105,7 +113,8 @@ golint:
105
113
  default_ratings_paths:
106
114
  - "**.go"
107
115
  govet:
108
- image: codeclimate/codeclimate-govet
116
+ channels:
117
+ stable: codeclimate/codeclimate-govet
109
118
  description: Reports suspicious constructs in Go programs.
110
119
  community: true
111
120
  enable_regexps:
@@ -113,20 +122,23 @@ govet:
113
122
  default_ratings_paths:
114
123
  - "**.go"
115
124
  fixme:
116
- image: codeclimate/codeclimate-fixme
125
+ channels:
126
+ stable: codeclimate/codeclimate-fixme
117
127
  description: Finds FIXME, TODO, HACK, etc. comments.
118
128
  community: false
119
129
  enable_regexps:
120
130
  - .+
121
131
  default_ratings_paths: []
122
132
  foodcritic:
123
- image: codeclimate/codeclimate-foodcritic
133
+ channels:
134
+ stable: codeclimate/codeclimate-foodcritic
124
135
  description: Lint tool for Chef cookbooks.
125
136
  community: true
126
137
  enable_regexps:
127
138
  default_ratings_paths:
128
139
  gnu-complexity:
129
- image: codeclimate/codeclimate-gnu-complexity
140
+ channels:
141
+ stable: codeclimate/codeclimate-gnu-complexity
130
142
  description: Checks complexity of C code
131
143
  community: true
132
144
  enable_regexps:
@@ -134,7 +146,8 @@ gnu-complexity:
134
146
  default_ratings_paths:
135
147
  - "**.c"
136
148
  haxe-checkstyle:
137
- image: codeclimate/codeclimate-haxe-checkstyle
149
+ channels:
150
+ stable: codeclimate/codeclimate-haxe-checkstyle
138
151
  description: Checkstyle is a development library to help developers write Haxe code that adheres to a coding standard.
139
152
  community: true
140
153
  enable_regexps:
@@ -142,7 +155,8 @@ haxe-checkstyle:
142
155
  default_ratings_paths:
143
156
  - "**.hx"
144
157
  hlint:
145
- image: codeclimate/codeclimate-hlint
158
+ channels:
159
+ stable: codeclimate/codeclimate-hlint
146
160
  description: Linter for Haskell programs.
147
161
  community: true
148
162
  enable_regexps:
@@ -150,7 +164,8 @@ hlint:
150
164
  default_ratings_paths:
151
165
  - "**.hs"
152
166
  kibit:
153
- image: codeclimate/codeclimate-kibit
167
+ channels:
168
+ stable: codeclimate/codeclimate-kibit
154
169
  description: Static code analyzer for Clojure, ClojureScript, cljx and other Clojure variants.
155
170
  community: true
156
171
  enable_regexps:
@@ -162,7 +177,8 @@ kibit:
162
177
  - "**.cljc"
163
178
  - "**.cljs"
164
179
  markdownlint:
165
- image: codeclimate/codeclimate-markdownlint
180
+ channels:
181
+ stable: codeclimate/codeclimate-markdownlint
166
182
  description: Flags style issues within Markdown files.
167
183
  community: true
168
184
  enable_regexps:
@@ -172,20 +188,23 @@ markdownlint:
172
188
  - "**.markdown"
173
189
  - "**.md"
174
190
  nodesecurity:
175
- image: codeclimate/codeclimate-nodesecurity
191
+ channels:
192
+ stable: codeclimate/codeclimate-nodesecurity
176
193
  description: Security tool for Node.js dependencies.
177
194
  community: true
178
195
  enable_regexps:
179
196
  default_ratings_paths:
180
197
  pep8:
181
- image: codeclimate/codeclimate-pep8
198
+ channels:
199
+ stable: codeclimate/codeclimate-pep8
182
200
  description: Static analysis tool to check Python code against the style conventions outlined in PEP-8.
183
201
  community: false
184
202
  enable_regexps:
185
203
  default_ratings_paths:
186
204
  - "**.py"
187
205
  phan:
188
- image: codeclimate/codeclimate-phan
206
+ channels:
207
+ stable: codeclimate/codeclimate-phan
189
208
  description: Phan is a static analyzer for PHP.
190
209
  community: true
191
210
  enable_regexps:
@@ -197,7 +216,8 @@ phan:
197
216
  - "**.module"
198
217
  - "**.inc"
199
218
  phpcodesniffer:
200
- image: codeclimate/codeclimate-phpcodesniffer
219
+ channels:
220
+ stable: codeclimate/codeclimate-phpcodesniffer
201
221
  description: Detects violations of a defined set of coding standards in PHP.
202
222
  community: false
203
223
  enable_regexps:
@@ -206,7 +226,8 @@ phpcodesniffer:
206
226
  - "**.module"
207
227
  - "**.inc"
208
228
  phpmd:
209
- image: codeclimate/codeclimate-phpmd
229
+ channels:
230
+ stable: codeclimate/codeclimate-phpmd
210
231
  description: A PHP static analysis tool.
211
232
  community: false
212
233
  upgrade_languages:
@@ -220,7 +241,8 @@ phpmd:
220
241
  - "**.module"
221
242
  - "**.inc"
222
243
  radon:
223
- image: codeclimate/codeclimate-radon
244
+ channels:
245
+ stable: codeclimate/codeclimate-radon
224
246
  description: Python tool used to compute Cyclomatic Complexity.
225
247
  community: false
226
248
  upgrade_languages:
@@ -230,7 +252,8 @@ radon:
230
252
  default_ratings_paths:
231
253
  - "**.py"
232
254
  reek:
233
- image: codeclimate/codeclimate-reek
255
+ channels:
256
+ stable: codeclimate/codeclimate-reek
234
257
  description: "Reek examines Ruby classes, modules, and methods and reports any code smells it finds."
235
258
  community: true
236
259
  upgrade_languages:
@@ -240,13 +263,15 @@ reek:
240
263
  default_ratings_paths:
241
264
  - "**.rb"
242
265
  requiresafe:
243
- image: codeclimate/codeclimate-nodesecurity
266
+ channels:
267
+ stable: codeclimate/codeclimate-nodesecurity
244
268
  description: Security tool for Node.js dependencies.
245
269
  community: true
246
270
  enable_regexps:
247
271
  default_ratings_paths:
248
272
  rubocop:
249
- image: codeclimate/codeclimate-rubocop
273
+ channels:
274
+ stable: codeclimate/codeclimate-rubocop
250
275
  description: A Ruby static code analyzer, based on the community Ruby style guide.
251
276
  community: false
252
277
  upgrade_languages:
@@ -256,28 +281,32 @@ rubocop:
256
281
  default_ratings_paths:
257
282
  - "**.rb"
258
283
  rubocop-v35:
259
- image: codeclimate/codeclimate-rubocop:v35
284
+ channels:
285
+ stable: codeclimate/codeclimate-rubocop:v35
260
286
  description: A Ruby static code analyzer, based on the community Ruby style guide. Version 0.35.1 of RuboCop.
261
287
  community: false
262
288
  enable_regexps:
263
289
  default_ratings_paths:
264
290
  - "**.rb"
265
291
  rubymotion:
266
- image: codeclimate/codeclimate-rubymotion
292
+ channels:
293
+ stable: codeclimate/codeclimate-rubymotion
267
294
  description: Rubymotion-specific rubocop checks.
268
295
  community: true
269
296
  enable_regexps:
270
297
  default_ratings_paths:
271
298
  - "**.rb"
272
299
  scss-lint:
273
- image: codeclimate/codeclimate-scss-lint
300
+ channels:
301
+ stable: codeclimate/codeclimate-scss-lint
274
302
  description: Configurable tool for writing clean and consistent SCSS.
275
303
  community: true
276
304
  enable_regexps:
277
305
  default_ratings_paths:
278
306
  - "**.scss"
279
307
  shellcheck:
280
- image: codeclimate/codeclimate-shellcheck
308
+ channels:
309
+ stable: codeclimate/codeclimate-shellcheck
281
310
  description: A static analysis tool for shell scripts.
282
311
  community: true
283
312
  enable_regexps:
@@ -285,7 +314,8 @@ shellcheck:
285
314
  default_ratings_paths:
286
315
  - "**.sh"
287
316
  tailor:
288
- image: codeclimate/codeclimate-tailor
317
+ channels:
318
+ stable: codeclimate/codeclimate-tailor
289
319
  description: Cross-platform static analyzer and linter for Swift.
290
320
  community: true
291
321
  enable_regexps:
@@ -293,14 +323,16 @@ tailor:
293
323
  default_ratings_paths:
294
324
  - "**.swift"
295
325
  watson:
296
- image: codeclimate/codeclimate-watson
326
+ channels:
327
+ stable: codeclimate/codeclimate-watson
297
328
  description: A young Ember Doctor to help you fix your code.
298
329
  community: true
299
330
  enable_regexps:
300
331
  default_ratings_paths:
301
332
  - "app/**"
302
333
  vint:
303
- image: codeclimate/codeclimate-vint
334
+ channels:
335
+ stable: codeclimate/codeclimate-vint
304
336
  description: Fast and Highly Extensible Vim script Language Lint implemented by Python.
305
337
  community: true
306
338
  enable_regexps:
@@ -52,6 +52,11 @@ module CC
52
52
  container.run(container_options).tap do |result|
53
53
  CLI.debug("#{name} engine stderr: #{result.stderr}")
54
54
  end
55
+ rescue Container::ImageRequired
56
+ # Provide a clearer message given the context we have
57
+ message = "Unable to find an image for #{name}:#{@config["channel"]}."
58
+ message << " Available channels: #{@metadata["channels"].keys.inspect}."
59
+ raise Container::ImageRequired, message
55
60
  ensure
56
61
  delete_config_file
57
62
  end
@@ -3,6 +3,19 @@ require "securerandom"
3
3
  module CC
4
4
  module Analyzer
5
5
  class EnginesConfigBuilder
6
+ class RegistryAdapter < SimpleDelegator
7
+ # Calling this is guarded by Registry#key?(name) so we can assume
8
+ # metadata itself will be present. We own the YAML loaded into the
9
+ # registry, so we can also assume the "channels" key will be present. We
10
+ # can't assume it will have a key for the given channel, but the nil
11
+ # value for the returned image key will trigger the desired error
12
+ # handling.
13
+ def fetch(name, channel)
14
+ metadata = self[name]
15
+ metadata.merge("image" => metadata["channels"][channel])
16
+ end
17
+ end
18
+
6
19
  Result = Struct.new(
7
20
  :name,
8
21
  :registry_entry,
@@ -12,7 +25,7 @@ module CC
12
25
  )
13
26
 
14
27
  def initialize(registry:, config:, container_label:, source_dir:, requested_paths:)
15
- @registry = registry
28
+ @registry = RegistryAdapter.new(registry)
16
29
  @config = config
17
30
  @container_label = container_label
18
31
  @requested_paths = requested_paths
@@ -23,7 +36,8 @@ module CC
23
36
  names_and_raw_engine_configs.map do |name, raw_engine_config|
24
37
  label = @container_label || SecureRandom.uuid
25
38
  engine_config = engine_config(raw_engine_config)
26
- Result.new(name, @registry[name], @source_dir, engine_config, label)
39
+ engine_metadata = @registry.fetch(name, raw_engine_config.channel)
40
+ Result.new(name, engine_metadata, @source_dir, engine_config, label)
27
41
  end
28
42
  end
29
43
 
@@ -2,11 +2,13 @@ module CC
2
2
  module Analyzer
3
3
  module Formatters
4
4
  autoload :Formatter, "cc/analyzer/formatters/formatter"
5
+ autoload :HTMLFormatter, "cc/analyzer/formatters/html_formatter"
5
6
  autoload :JSONFormatter, "cc/analyzer/formatters/json_formatter"
6
7
  autoload :PlainTextFormatter, "cc/analyzer/formatters/plain_text_formatter"
7
8
  autoload :Spinner, "cc/analyzer/formatters/spinner"
8
9
 
9
10
  FORMATTERS = {
11
+ html: HTMLFormatter,
10
12
  json: JSONFormatter,
11
13
  text: PlainTextFormatter,
12
14
  }.freeze
@@ -0,0 +1,82 @@
1
+ require "redcarpet"
2
+ require "active_support/number_helper"
3
+
4
+ module CC
5
+ module Analyzer
6
+ module Formatters
7
+ class HTMLFormatter < Formatter
8
+ class ReportTemplate
9
+ include ERB::Util
10
+ attr_accessor :template, :issues, :issues_by_path
11
+
12
+ TEMPLATE_PATH = File.expand_path(File.join(File.dirname(__FILE__), "templates/html.erb"))
13
+
14
+ def initialize(issue_count, issues_by_path)
15
+ @template = File.read(TEMPLATE_PATH)
16
+ @issues_by_path = issues_by_path
17
+ @issue_count = issue_count
18
+ end
19
+
20
+ def render
21
+ ERB.new(@template).result(binding)
22
+ end
23
+
24
+ def pluralize(number, noun)
25
+ "#{ActiveSupport::NumberHelper.number_to_delimited(number)} #{noun.pluralize(number)}"
26
+ end
27
+ end
28
+
29
+ def write(data)
30
+ json = JSON.parse(data)
31
+ json["engine_name"] = current_engine.name
32
+
33
+ case json["type"].downcase
34
+ when "issue"
35
+ issues << json
36
+ when "warning"
37
+ warnings << json
38
+ else
39
+ raise "Invalid type found: #{json["type"]}"
40
+ end
41
+ end
42
+
43
+ def finished
44
+ template = ReportTemplate.new(issues.length, issues_by_path)
45
+ puts template.render
46
+ end
47
+
48
+ def failed(_)
49
+ exit 1
50
+ end
51
+
52
+ private
53
+
54
+ def issues
55
+ @issues ||= []
56
+ end
57
+
58
+ def issues_by_path
59
+ issues.group_by { |i| i["location"]["path"] }.sort.each do |_, file_issues|
60
+ IssueSorter.new(file_issues).by_location.map do |issue|
61
+ source_buffer = @filesystem.source_buffer_for(issue["location"]["path"])
62
+ issue["location"] = LocationDescription.new(source_buffer, issue["location"], "")
63
+ issue["description"] = render_readup_markdown(issue["description"])
64
+ if issue["content"]
65
+ issue["content"]["body"] = render_readup_markdown(issue["content"]["body"])
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ def warnings
72
+ @warnings ||= []
73
+ end
74
+
75
+ def render_readup_markdown(body)
76
+ html = Redcarpet::Render::HTML.new(escape_html: false, link_attributes: { target: "_blank" })
77
+ Redcarpet::Markdown.new(html, autolink: true, fenced_code_blocks: true, tables: true).render(body)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -83,10 +83,15 @@ module CC
83
83
 
84
84
  def add_engine_options
85
85
  engine_options.each do |engine|
86
+ name, channel = engine.split(":", 2)
87
+
86
88
  if config.engines.include?(engine)
87
- config.engines[engine].enabled = true
89
+ config.engines[name].enabled = true
90
+ config.engines[name].channel = channel if channel
88
91
  else
89
- config.engines[engine] = CC::Yaml::Nodes::Engine.new(config.engines).with_value("enabled" => true)
92
+ value = { "enabled" => true }
93
+ value["channel"] = channel if channel
94
+ config.engines[name] = CC::Yaml::Nodes::Engine.new(config.engines).with_value(value)
90
95
  end
91
96
  end
92
97
  end
@@ -16,8 +16,8 @@ module CC
16
16
  def pull_docker_images
17
17
  engine_names.each do |name|
18
18
  if engine_registry.exists?(name)
19
- image = engine_image(name)
20
- pull_engine_image(image)
19
+ images = engine_registry[name]["channels"].values
20
+ images.each { |image| pull_engine_image(image) }
21
21
  else
22
22
  warn("unknown engine name: #{name}")
23
23
  end
@@ -28,10 +28,6 @@ module CC
28
28
  @engine_names ||= parsed_yaml.engine_names
29
29
  end
30
30
 
31
- def engine_image(engine_name)
32
- engine_registry_list[engine_name]["image"]
33
- end
34
-
35
31
  def pull_engine_image(engine_image)
36
32
  unless system("docker pull #{engine_image}")
37
33
  raise ImagePullFailure, "unable to pull image #{engine_image}"
@@ -14,7 +14,7 @@ module CC
14
14
 
15
15
  def commands
16
16
  [
17
- "analyze [-f format] [-e engine] <path>",
17
+ "analyze [-f format] [-e engine(:channel)] <path>",
18
18
  "console",
19
19
  "engines:disable #{underline("engine_name")}",
20
20
  "engines:enable #{underline("engine_name")}",
@@ -234,7 +234,7 @@ module CC
234
234
  end
235
235
 
236
236
  def engine_image
237
- engine_registry[@engine_name]["image"]
237
+ engine_registry[@engine_name]["channels"]["stable"]
238
238
  end
239
239
 
240
240
  # Stolen from ActiveSupport (where it was deprecated)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codeclimate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.29.0
4
+ version: 0.30.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code Climate
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-20 00:00:00.000000000 Z
11
+ date: 2016-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: 0.8.0
53
+ version: 0.9.0
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: 0.8.0
60
+ version: 0.9.0
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: highline
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -132,6 +132,20 @@ dependencies:
132
132
  - - ">="
133
133
  - !ruby/object:Gem::Version
134
134
  version: 2.0.0
135
+ - !ruby/object:Gem::Dependency
136
+ name: redcarpet
137
+ requirement: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - "~>"
140
+ - !ruby/object:Gem::Version
141
+ version: '3.2'
142
+ type: :runtime
143
+ prerelease: false
144
+ version_requirements: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - "~>"
147
+ - !ruby/object:Gem::Version
148
+ version: '3.2'
135
149
  description: Code Climate command line tool
136
150
  email: hello@codeclimate.com
137
151
  executables:
@@ -164,6 +178,7 @@ files:
164
178
  - lib/cc/analyzer/filesystem.rb
165
179
  - lib/cc/analyzer/formatters.rb
166
180
  - lib/cc/analyzer/formatters/formatter.rb
181
+ - lib/cc/analyzer/formatters/html_formatter.rb
167
182
  - lib/cc/analyzer/formatters/json_formatter.rb
168
183
  - lib/cc/analyzer/formatters/plain_text_formatter.rb
169
184
  - lib/cc/analyzer/formatters/spinner.rb