codeclimate 0.24.3 → 0.25.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: d5ba7e27f0c2fcc953c2f14dc15ca0055ddf4d25
4
- data.tar.gz: 919f9784e1f9c9f22eb82168d6bdb8213082e8b3
3
+ metadata.gz: c732584b6855ac426cc7e0a19b4fb55375f7fcf5
4
+ data.tar.gz: 1678f0e4a32a532a7e871412e681ddaf7cc0f59a
5
5
  SHA512:
6
- metadata.gz: 9069df8ef0b536687fbac616f775b8e6723820dfc36f424eb49ef31e2ffef19b34bf8ecf172bc7947344b1328a116da992feecf20ef42ca9f6b8872083051676
7
- data.tar.gz: 87096921939b8b13fc5b00278cfc11d73dc74479878524712d5e955667a42ee05e3d18d9184cf99f4faa3a62d4d2900a6784277ee3c7c8dfa71f75a86c99a45c
6
+ metadata.gz: b091b7d2457a3aa89666baba5b3c789f1284854edc95c25a96a96571202aa3b2a35462568f8c93e924f1bced4cf90825864685d24e14988fed77a7d0a0e54afa
7
+ data.tar.gz: 4c2cc51abd7534ac166daffb627ce7a099118d18beb6816222d8b87060d2ed020d6a0d9283813aca5d7a556903206f9cc706dbe30fc806f79fa0c8066c700b94
data/lib/cc/analyzer.rb CHANGED
@@ -15,13 +15,22 @@ module CC
15
15
  autoload :Filesystem, "cc/analyzer/filesystem"
16
16
  autoload :Formatters, "cc/analyzer/formatters"
17
17
  autoload :Issue, "cc/analyzer/issue"
18
+ autoload :IssueCategoryValidation, "cc/analyzer/issue_category_validation"
19
+ autoload :IssueCheckNamePresenceValidation, "cc/analyzer/issue_check_name_presence_validation"
20
+ autoload :IssueDescriptionPresenceValidation, "cc/analyzer/issue_description_presence_validation"
21
+ autoload :IssuePathExistenceValidation, "cc/analyzer/issue_path_existence_validation"
22
+ autoload :IssuePathPresenceValidation, "cc/analyzer/issue_path_presence_validation"
23
+ autoload :IssueRelativePathValidation, "cc/analyzer/issue_relative_path_validation"
18
24
  autoload :IssueSorter, "cc/analyzer/issue_sorter"
25
+ autoload :IssueTypeValidation, "cc/analyzer/issue_type_validation"
26
+ autoload :IssueValidator, "cc/analyzer/issue_validator"
19
27
  autoload :LocationDescription, "cc/analyzer/location_description"
20
28
  autoload :LoggingContainerListener, "cc/analyzer/logging_container_listener"
21
29
  autoload :MountedPath, "cc/analyzer/mounted_path"
22
30
  autoload :RaisingContainerListener, "cc/analyzer/raising_container_listener"
23
31
  autoload :SourceBuffer, "cc/analyzer/source_buffer"
24
32
  autoload :StatsdContainerListener, "cc/analyzer/statsd_container_listener"
33
+ autoload :Validation, "cc/analyzer/validation"
25
34
 
26
35
  class DummyStatsd
27
36
  def method_missing(*)
@@ -5,11 +5,11 @@ module CC
5
5
  module Analyzer
6
6
  class Container
7
7
  ContainerData = Struct.new(
8
- :image, # image used to create the container
9
- :name, # name given to the container when created
10
- :duration, # duration, for a finished event
11
- :status, # status, for a finished event
12
- :stderr, # stderr, for a finished event
8
+ :image, # image used to create the container
9
+ :name, # name given to the container when created
10
+ :duration, # duration, for a finished event
11
+ :status, # status, for a finished event
12
+ :stderr, # stderr, for a finished event
13
13
  )
14
14
  ImageRequired = Class.new(StandardError)
15
15
  Result = Struct.new(
@@ -37,6 +37,11 @@ module CC
37
37
  CLI.debug("#{name} engine output: #{raw_output.strip}")
38
38
  output = EngineOutput.new(raw_output)
39
39
 
40
+ unless output.valid?
41
+ stdout_io.failed("#{name} produced invalid output: #{output.error[:message]}")
42
+ container.stop
43
+ end
44
+
40
45
  unless output_filter.filter?(output)
41
46
  stdout_io.write(output.to_json) || container.stop
42
47
  end
@@ -18,15 +18,27 @@ module CC
18
18
  Issue.new(raw_output)
19
19
  end
20
20
 
21
+ def valid?
22
+ validator.valid?
23
+ end
24
+
25
+ def error
26
+ validator.error
27
+ end
28
+
21
29
  private
22
30
 
23
31
  attr_accessor :raw_output
24
32
 
25
33
  def parsed_output
26
- JSON.parse(raw_output)
34
+ @parsed_output ||= JSON.parse(raw_output)
27
35
  rescue JSON::ParserError
28
36
  nil
29
37
  end
38
+
39
+ def validator
40
+ IssueValidator.new(parsed_output)
41
+ end
30
42
  end
31
43
  end
32
44
  end
@@ -12,7 +12,7 @@ module CC
12
12
  }.freeze
13
13
 
14
14
  def self.resolve(name)
15
- FORMATTERS[name.to_sym] or raise Formatter::InvalidFormatterError, "'#{name}' is not a valid formatter. Valid options are: #{FORMATTERS.keys.join(', ')}"
15
+ FORMATTERS[name.to_sym] or raise Formatter::InvalidFormatterError, "'#{name}' is not a valid formatter. Valid options are: #{FORMATTERS.keys.join(", ")}"
16
16
  end
17
17
  end
18
18
  end
@@ -20,7 +20,7 @@ module CC
20
20
  when "warning"
21
21
  warnings << json
22
22
  else
23
- raise "Invalid type found: #{json['type']}"
23
+ raise "Invalid type found: #{json["type"]}"
24
24
  end
25
25
  end
26
26
 
@@ -28,7 +28,7 @@ module CC
28
28
  puts
29
29
 
30
30
  issues_by_path.each do |path, file_issues|
31
- puts colorize("== #{path} (#{pluralize(file_issues.size, 'issue')}) ==", :yellow)
31
+ puts colorize("== #{path} (#{pluralize(file_issues.size, "issue")}) ==", :yellow)
32
32
 
33
33
  IssueSorter.new(file_issues).by_location.each do |issue|
34
34
  if (location = issue["location"])
@@ -37,15 +37,15 @@ module CC
37
37
  end
38
38
 
39
39
  print(issue["description"])
40
- print(colorize(" [#{issue['engine_name']}]", "#333333"))
40
+ print(colorize(" [#{issue["engine_name"]}]", "#333333"))
41
41
  puts
42
42
  end
43
43
  puts
44
44
  end
45
45
 
46
- print(colorize("Analysis complete! Found #{pluralize(issues.size, 'issue')}", :green))
46
+ print(colorize("Analysis complete! Found #{pluralize(issues.size, "issue")}", :green))
47
47
  if warnings.size > 0
48
- print(colorize(" and #{pluralize(warnings.size, 'warning')}", :green))
48
+ print(colorize(" and #{pluralize(warnings.size, "warning")}", :green))
49
49
  end
50
50
  puts(colorize(".", :green))
51
51
  end
@@ -0,0 +1,30 @@
1
+ module CC
2
+ module Analyzer
3
+ class IssueCategoryValidation < Validation
4
+ CATEGORIES = [
5
+ "Bug Risk".freeze,
6
+ "Clarity".freeze,
7
+ "Compatibility".freeze,
8
+ "Complexity".freeze,
9
+ "Duplication".freeze,
10
+ "Performance".freeze,
11
+ "Security".freeze,
12
+ "Style".freeze,
13
+ ].freeze
14
+
15
+ def valid?
16
+ object["categories"].present? && no_invalid_categories?
17
+ end
18
+
19
+ def message
20
+ "Category must be at least one of #{CATEGORIES.join(", ")}"
21
+ end
22
+
23
+ private
24
+
25
+ def no_invalid_categories?
26
+ (CATEGORIES | object["categories"]) == CATEGORIES
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ module CC
2
+ module Analyzer
3
+ class IssueCheckNamePresenceValidation < Validation
4
+ def valid?
5
+ object["check_name"].present?
6
+ end
7
+
8
+ def message
9
+ "Check name must be present"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module CC
2
+ module Analyzer
3
+ class IssueDescriptionPresenceValidation < Validation
4
+ def valid?
5
+ object["description"].present?
6
+ end
7
+
8
+ def message
9
+ "Description must be present"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ module CC
2
+ module Analyzer
3
+ class IssuePathExistenceValidation < Validation
4
+ def valid?
5
+ File.exist?(path)
6
+ end
7
+
8
+ def message
9
+ "File does not exist: '#{path}'"
10
+ end
11
+
12
+ private
13
+
14
+ def path
15
+ object.fetch("location", {}).fetch("path", "")
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module CC
2
+ module Analyzer
3
+ class IssuePathPresenceValidation < Validation
4
+ def valid?
5
+ path.present?
6
+ end
7
+
8
+ def message
9
+ "Path must be present"
10
+ end
11
+
12
+ private
13
+
14
+ def path
15
+ object.fetch("location", {})["path"]
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module CC
2
+ module Analyzer
3
+ class IssueRelativePathValidation < Validation
4
+ def valid?
5
+ path && !path.start_with?("/")
6
+ end
7
+
8
+ def message
9
+ "Path must be relative"
10
+ end
11
+
12
+ private
13
+
14
+ def path
15
+ object.fetch("location", {})["path"]
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module CC
2
+ module Analyzer
3
+ class IssueTypeValidation < Validation
4
+ def valid?
5
+ type && type.casecmp("issue").zero?
6
+ end
7
+
8
+ def message
9
+ "Type must be 'issue' but was '#{type}'"
10
+ end
11
+
12
+ private
13
+
14
+ def type
15
+ object["type"]
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,46 @@
1
+ module CC
2
+ module Analyzer
3
+ class IssueValidator
4
+ CHECKS = [
5
+ IssueCategoryValidation,
6
+ IssueCheckNamePresenceValidation,
7
+ IssueDescriptionPresenceValidation,
8
+ IssuePathExistenceValidation,
9
+ IssuePathPresenceValidation,
10
+ IssueRelativePathValidation,
11
+ IssueTypeValidation,
12
+ ].freeze
13
+
14
+ attr_reader :error
15
+
16
+ def initialize(issue)
17
+ @issue = issue
18
+ end
19
+
20
+ def valid?
21
+ return @valid unless @valid.nil?
22
+
23
+ if issue && invalid_messages.any?
24
+ @error = {
25
+ message: "#{invalid_messages.join("; ")}: `#{issue}`.",
26
+ issue: issue,
27
+ }
28
+ @valid = false
29
+ else
30
+ @valid = true
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :issue
37
+
38
+ def invalid_messages
39
+ @invalid_messages ||= CHECKS.each_with_object([]) do |check, result|
40
+ validator = check.new(issue)
41
+ result << validator.message unless validator.valid?
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,21 @@
1
+ module CC
2
+ module Analyzer
3
+ class Validation
4
+ def initialize(object)
5
+ @object = object
6
+ end
7
+
8
+ def valid?
9
+ raise NotImplementedError
10
+ end
11
+
12
+ def message
13
+ raise NotImplementedError
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :object
19
+ end
20
+ end
21
+ end
@@ -13,7 +13,7 @@ module CC
13
13
  end
14
14
 
15
15
  def run
16
- $stderr.puts "unknown command #{self.class.name.split('::').last.underscore}"
16
+ $stderr.puts "unknown command #{self.class.name.split("::").last.underscore}"
17
17
  end
18
18
 
19
19
  def self.command_name
@@ -59,7 +59,7 @@ module CC
59
59
 
60
60
  def filesystem
61
61
  @filesystem ||= CC::Analyzer::Filesystem.new(
62
- CC::Analyzer::MountedPath.code.container_path
62
+ CC::Analyzer::MountedPath.code.container_path,
63
63
  )
64
64
  end
65
65
 
@@ -5,7 +5,7 @@ module CC
5
5
  def run
6
6
  say "Available engines:"
7
7
  engine_registry_list.sort_by { |name, _| name }.each do |name, attributes|
8
- say "- #{name}: #{attributes['description']}"
8
+ say "- #{name}: #{attributes["description"]}"
9
9
  end
10
10
  end
11
11
  end
data/lib/cc/cli/help.rb CHANGED
@@ -16,11 +16,11 @@ module CC
16
16
  [
17
17
  "analyze [-f format] [-e engine] <path>",
18
18
  "console",
19
- "engines:disable #{underline('engine_name')}",
20
- "engines:enable #{underline('engine_name')}",
19
+ "engines:disable #{underline("engine_name")}",
20
+ "engines:enable #{underline("engine_name")}",
21
21
  "engines:install",
22
22
  "engines:list",
23
- "engines:remove #{underline('engine_name')}",
23
+ "engines:remove #{underline("engine_name")}",
24
24
  "help",
25
25
  "init",
26
26
  "validate-config",
data/lib/cc/cli/runner.rb CHANGED
@@ -39,7 +39,7 @@ module CC
39
39
  def command_name
40
40
  case command
41
41
  when nil, "-h", "-?", "--help" then "Help"
42
- when "-v", "--version" then "Version"
42
+ when "-v", "--version" then "Version"
43
43
  else command.sub(":", "::").underscore.camelize
44
44
  end
45
45
  end
data/lib/cc/cli/test.rb CHANGED
@@ -72,7 +72,7 @@ module CC
72
72
  @engine_name = @args.first
73
73
 
74
74
  if @engine_name.blank?
75
- fatal "Usage: codeclimate test #{rainbow.wrap('engine_name').underline}"
75
+ fatal "Usage: codeclimate test #{rainbow.wrap("engine_name").underline}"
76
76
  end
77
77
 
78
78
  test_engine
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.24.3
4
+ version: 0.25.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-04-10 00:00:00.000000000 Z
11
+ date: 2016-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -168,13 +168,22 @@ files:
168
168
  - lib/cc/analyzer/formatters/plain_text_formatter.rb
169
169
  - lib/cc/analyzer/formatters/spinner.rb
170
170
  - lib/cc/analyzer/issue.rb
171
+ - lib/cc/analyzer/issue_category_validation.rb
172
+ - lib/cc/analyzer/issue_check_name_presence_validation.rb
173
+ - lib/cc/analyzer/issue_description_presence_validation.rb
174
+ - lib/cc/analyzer/issue_path_existence_validation.rb
175
+ - lib/cc/analyzer/issue_path_presence_validation.rb
176
+ - lib/cc/analyzer/issue_relative_path_validation.rb
171
177
  - lib/cc/analyzer/issue_sorter.rb
178
+ - lib/cc/analyzer/issue_type_validation.rb
179
+ - lib/cc/analyzer/issue_validator.rb
172
180
  - lib/cc/analyzer/location_description.rb
173
181
  - lib/cc/analyzer/logging_container_listener.rb
174
182
  - lib/cc/analyzer/mounted_path.rb
175
183
  - lib/cc/analyzer/raising_container_listener.rb
176
184
  - lib/cc/analyzer/source_buffer.rb
177
185
  - lib/cc/analyzer/statsd_container_listener.rb
186
+ - lib/cc/analyzer/validation.rb
178
187
  - lib/cc/cli.rb
179
188
  - lib/cc/cli/analyze.rb
180
189
  - lib/cc/cli/command.rb