maximus 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,7 +11,6 @@ module Maximus
11
11
  module Helper
12
12
 
13
13
  # See if project linted is a Rails app
14
- #
15
14
  # This will usually be stored as a class variable in the inherited class
16
15
  # @return [Boolean]
17
16
  def is_rails?
@@ -19,7 +18,6 @@ module Maximus
19
18
  end
20
19
 
21
20
  # Get root directory of file being called
22
- #
23
21
  # @return [String] absolute path to root directory
24
22
  def root_dir
25
23
  is_rails? ? Rails.root.to_s : Dir.pwd.to_s
@@ -31,13 +29,9 @@ module Maximus
31
29
  # @param install_instructions [String] how to install the missing command
32
30
  # @return [void] aborts the action if command not found
33
31
  def node_module_exists(command, install_instructions = 'npm install -g')
34
- cmd = `if hash #{command} 2>/dev/null; then
35
- echo "true"
36
- else
37
- echo "false"
38
- fi`
32
+ cmd = `if hash #{command} 2>/dev/null; then echo "true"; else echo "false"; fi`
39
33
  if cmd.include? "false"
40
- command_msg = "Missing command #{command}".color(:red)
34
+ command_msg = "Missing command #{command}"
41
35
  abort "#{command_msg}: Please run `#{install_instructions} #{command}` And try again\n"
42
36
  exit 1
43
37
  end
@@ -49,11 +43,10 @@ module Maximus
49
43
  # @param file [String] filename with extension to search for
50
44
  # @return [String] path to default config file or file in user's directory
51
45
  def check_default_config_path(file)
52
- File.exist?(file) ? file : File.join(File.dirname(__FILE__), "config/#{file}")
46
+ File.exist?(file) ? file : File.join(File.dirname(__FILE__), file)
53
47
  end
54
48
 
55
49
  # Grab the absolute path of the reporter file
56
- #
57
50
  # @param filename [String]
58
51
  # @return [String] absolute path to the reporter file
59
52
  def reporter_path(filename)
@@ -82,16 +75,14 @@ module Maximus
82
75
  end
83
76
 
84
77
  # Convert string to boolean
85
- #
86
78
  # @param str [String] the string to evaluate
87
79
  # @return [Boolean] whether or not the string is true
88
- def truthy(str)
80
+ def truthy?(str)
89
81
  return true if str == true || str =~ (/^(true|t|yes|y|1)$/i)
90
82
  return false if str == false || str.blank? || str =~ (/^(false|f|no|n|0)$/i)
91
83
  end
92
84
 
93
85
  # Edit and save a YAML file
94
- #
95
86
  # @param yaml_location [String] YAML absolute file path
96
87
  # @return [void]
97
88
  def edit_yaml(yaml_location, &block)
@@ -101,7 +92,6 @@ module Maximus
101
92
  end
102
93
 
103
94
  # Request user input
104
- #
105
95
  # @param args [Array<String>] prompts to request
106
96
  # @return [String] user input to use elsewhere
107
97
  def prompt(*args)
@@ -115,17 +105,10 @@ module Maximus
115
105
  # @see Lint#relevant_lint
116
106
  #
117
107
  # @example typical output
118
- # lines_added = {'filename' => ['0..10', '11..14']}
108
+ # lines_added = {changes: ['0..10', '11..14']}
119
109
  # lines_added_to_range(lines_added)
120
110
  # # output
121
- # {
122
- # 'filename': {
123
- # {
124
- # [0,1,2,3,4,5,6,7,8,9,10],
125
- # [11,12,13,14]
126
- # }
127
- # }
128
- # }
111
+ # [0,1,2,3,4,5,6,7,8,9,10, 11,12,13,14]
129
112
  #
130
113
  # @todo I'm sure there's a better way of doing this
131
114
  # @todo figure out a better place to put this than in Helper
@@ -136,10 +119,9 @@ module Maximus
136
119
  end
137
120
 
138
121
  # Ensure path exists
139
- #
140
122
  # @param path [String, Array] path to files can be directory or glob
141
123
  # @return [Boolean]
142
- def path_exists(path = @path)
124
+ def path_exists?(path = @path)
143
125
  path = path.split(' ') if path.is_a?(String) && path.include?(' ')
144
126
  if path.is_a?(Array)
145
127
  path.each do |p|
@@ -20,7 +20,7 @@ module Maximus
20
20
  # lint_data = JSON.parse(`some-command-line-linter`)
21
21
  # @output[:files_inspected] ||= files_inspected(extension, delimiter, base_path_replacement)
22
22
  # refine data_from_output
23
- # end
23
+ # end
24
24
  #
25
25
  # Inherits settings from {Config#initialize}
26
26
  # @see Config#initialize
@@ -45,10 +45,10 @@ module Maximus
45
45
  end
46
46
 
47
47
  # Convert raw data into warnings, errors, conventions or refactors. Use this wisely.
48
- #
49
48
  # @param data [Hash] unfiltered lint data
50
49
  # @return [Hash] refined lint data and all the other bells and whistles
51
50
  def refine(data)
51
+
52
52
  # Prevent abortive empty JSON.parse error
53
53
  data = '{}' if data.blank?
54
54
  return puts "Error from #{@task}: #{data}" if data.is_a?(String) && data.include?('No such')
@@ -60,48 +60,19 @@ module Maximus
60
60
  data = @output[:relevant_lints]
61
61
  end
62
62
 
63
- lint_warnings = []
64
- lint_errors = []
65
- lint_conventions = []
66
- lint_refactors = []
67
- unless data.blank?
68
- data.each do |filename, error_list|
69
- error_list.each do |message|
70
- # so that :raw_data remains unaffected
71
- message = message.clone
72
- message.delete('length')
73
- message['filename'] = filename
74
- if message['severity'] == 'warning'
75
- message.delete('severity')
76
- lint_warnings << message
77
- elsif message['severity'] == 'error'
78
- message.delete('severity')
79
- lint_errors << message
80
- elsif message['severity'] == 'convention'
81
- message.delete('severity')
82
- lint_conventions << message
83
- elsif message['severity'] == 'refactor'
84
- message.delete('severity')
85
- lint_refactors << message
86
- end
87
- end
88
- end
89
- end
90
- @output[:lint_errors] = lint_errors
91
- @output[:lint_warnings] = lint_warnings
92
- @output[:lint_conventions] = lint_conventions
93
- @output[:lint_refactors] = lint_refactors
94
- lint_count = (lint_errors.length + lint_warnings.length + lint_conventions.length + lint_refactors.length)
63
+ evaluate_severities(data)
64
+
65
+ lint_count = (@output[:lint_errors].length + @output[:lint_warnings].length + @output[:lint_conventions].length + @output[:lint_refactors].length)
66
+
67
+ puts lint_summarize
68
+
95
69
  if @config.is_dev?
96
70
  puts lint_dev_format(data) unless data.blank?
97
- puts lint_summarize
98
71
  lint_ceiling lint_count
99
72
  else
100
- @config.log.info lint_summarize
101
73
  # Because this should be returned in the format it was received
102
74
  @output[:raw_data] = data.to_json
103
75
  end
104
- @config.destroy_temp(@task)
105
76
  @output
106
77
  end
107
78
 
@@ -109,7 +80,6 @@ module Maximus
109
80
  protected
110
81
 
111
82
  # List all files inspected
112
- #
113
83
  # @param ext [String] extension to search for
114
84
  # @param delimiter [String] comma or space separated
115
85
  # @param remove [String] remove from all file names
@@ -119,7 +89,6 @@ module Maximus
119
89
  end
120
90
 
121
91
  # Compare lint output with lines changed in commit
122
- #
123
92
  # @param lint [Hash] output lint data
124
93
  # @param files [Hash<String: String>] filename: filepath
125
94
  # @return [Array] lints that match the lines in commit
@@ -127,29 +96,25 @@ module Maximus
127
96
  all_files = {}
128
97
  files.each do |file|
129
98
 
130
- # sometimes data will be blank but this is good - it means no errors raised in the lint
131
- unless lint.blank?
132
- lint_file = lint[file[:filename].to_s]
133
-
134
- expanded = lines_added_to_range(file)
135
- revert_name = file[:filename].gsub("#{@settings[:root_dir]}/", '')
136
- unless lint_file.blank?
137
- all_files[revert_name] = []
138
-
139
- # @todo originally I tried .map and delete_if, but this works,
140
- # and the other method didn't cover all bases.
141
- # Gotta be a better way to write this though
142
- lint_file.each do |l|
143
- if expanded.include?(l['line'].to_i)
144
- all_files[revert_name] << l
145
- end
99
+ # sometimes data will be blank but this is good - it means no errors were raised in the lint
100
+ next if lint.blank?
101
+ lint_file = lint[file[:filename].to_s]
102
+
103
+ expanded = lines_added_to_range(file)
104
+ revert_name = file[:filename].gsub("#{@settings[:root_dir]}/", '')
105
+ unless lint_file.blank?
106
+ all_files[revert_name] = []
107
+
108
+ # @todo originally I tried .map and delete_if, but this works,
109
+ # and the other method didn't cover all bases.
110
+ # Gotta be a better way to write this though
111
+ lint_file.each do |l|
112
+ if expanded.include?(l['line'].to_i)
113
+ all_files[revert_name] << l
146
114
  end
147
- # If there's nothing there, then it definitely isn't a relevant lint
148
- all_files.delete(revert_name) if all_files[revert_name].blank?
149
115
  end
150
- else
151
- # Optionally store the filename with a blank array
152
- # @example all_files[file[:filename].to_s.gsub("#{@settings[:root_dir]}/", '')] = []
116
+ # If there's nothing there, then it definitely isn't a relevant lint
117
+ all_files.delete(revert_name) if all_files[revert_name].blank?
153
118
  end
154
119
  end
155
120
  @output[:files_linted] = all_files.keys
@@ -157,7 +122,6 @@ module Maximus
157
122
  end
158
123
 
159
124
  # Look for a config defined from Config#initialize
160
- #
161
125
  # @since 0.1.2
162
126
  # @param search_for [String]
163
127
  # @return [String, Boolean] path to temp file
@@ -166,58 +130,72 @@ module Maximus
166
130
  @settings[search_for.to_sym].blank? ? false : @settings[search_for.to_sym]
167
131
  end
168
132
 
133
+ # Add severities to @output
134
+ # @since 0.1.5
135
+ # @param data [Hash]
136
+ def evaluate_severities(data)
137
+ @output[:lint_warnings] = []
138
+ @output[:lint_errors] = []
139
+ @output[:lint_conventions] = []
140
+ @output[:lint_refactors] = []
141
+ return if data.blank?
142
+ data.each do |filename, error_list|
143
+ error_list.each do |message|
144
+ # so that :raw_data remains unaffected
145
+ message = message.clone
146
+ message.delete('length')
147
+ message['filename'] = filename.nil? ? '' : filename.gsub("#{@settings[:root_dir]}/", '')
148
+ severity = message['severity']
149
+ message.delete('severity')
150
+ @output["lint_#{severity}s".to_sym] << message
151
+ end
152
+ end
153
+ return @output
154
+ end
155
+
169
156
 
170
157
  private
171
158
 
172
159
  # Send abbreviated results to console or to the log
173
- #
174
160
  # @return [String] console message to display
175
161
  def lint_summarize
176
- puts "\n" if @config.is_dev?
177
-
178
- puts "#{'Warning'.color(:red)}: #{@output[:lint_errors].length} errors found in #{@task.to_s}" if @output[:lint_errors].length > 0
162
+ puts "#{'Warning'.color(:red)}: #{@output[:lint_errors].length} errors found in #{@task}" unless @output[:lint_errors].length
179
163
 
180
164
  success = @task.to_s.color(:green)
181
165
  success += ": "
182
166
  success += "[#{@output[:lint_warnings].length}]".color(:yellow)
183
- success += " " + "[#{@output[:lint_errors].length}]".color(:red)
167
+ success += " [#{@output[:lint_errors].length}]".color(:red)
184
168
  if @task == 'rubocop'
185
- success += " " + "[#{@output[:lint_conventions].length}]".color(:cyan)
186
- success += " " + "[#{@output[:lint_refactors].length}]".color(:white)
169
+ success += " [#{@output[:lint_conventions].length}]".color(:cyan)
170
+ success += " [#{@output[:lint_refactors].length}]".color(:white)
187
171
  end
188
172
 
189
173
  success
190
174
  end
191
175
 
192
176
  # If there's just too much to handle, through a warning.
193
- #
194
177
  # @param lint_length [Integer] count of how many lints
195
178
  # @return [String] console message to display
196
179
  def lint_ceiling(lint_length)
197
- if lint_length > 100
198
- lint_dev_format
199
- failed_task = "#{@task}".color(:green)
200
- errors = Rainbow("#{lint_length} failures.").red
201
- errormsg = ["You wouldn't stand a chance in Rome.\nResolve thy errors and train with #{failed_task} again.", "The gods frown upon you, mortal.\n#{failed_task}. Again.", "Do not embarrass the city. Fight another day. Use #{failed_task}.", "You are without honor. Replenish it with another #{failed_task}.", "You will never claim the throne with a performance like that.", "Pompeii has been lost.", "A wise choice. Do not be discouraged from another #{failed_task}."].sample
202
- errormsg += "\n\n"
203
-
204
- go_on = prompt "\n#{errors} Continue? (y/n) "
205
- abort errormsg unless truthy(go_on)
206
- end
180
+ return unless lint_length > 100
181
+ failed_task = @task.color(:green)
182
+ errors = "#{lint_length} failures.".color(:red)
183
+ errormsg = ["You wouldn't stand a chance in Rome.\nResolve thy errors and train with #{failed_task} again.", "The gods frown upon you, mortal.\n#{failed_task}. Again.", "Do not embarrass the city. Fight another day. Use #{failed_task}.", "You are without honor. Replenish it with another #{failed_task}.", "You will never claim the throne with a performance like that.", "Pompeii has been lost.", "A wise choice. Do not be discouraged from another #{failed_task}."].sample
184
+ errormsg += "\n\n"
185
+
186
+ go_on = prompt "\n#{errors} Continue? (y/n) "
187
+ abort errormsg unless truthy?(go_on)
207
188
  end
208
189
 
209
190
  # Dev display, executed only when called from command line
210
- #
211
191
  # @param errors [Hash] data from lint
212
192
  # @return [String] console message to display
213
193
  def lint_dev_format(errors = @output[:raw_data])
214
194
  return if errors.blank?
215
195
  pretty_output = ''
216
196
  errors.each do |filename, error_list|
217
- pretty_output += "\n"
218
197
  filename = filename.gsub("#{@settings[:root_dir]}/", '')
219
- pretty_output += filename.color(:cyan).underline
220
- pretty_output += "\n"
198
+ pretty_output += "\n#{filename.color(:cyan).underline} \n"
221
199
  error_list.each do |message|
222
200
  pretty_output += case message['severity']
223
201
  when 'warning' then 'W'.color(:yellow)
@@ -226,15 +204,13 @@ module Maximus
226
204
  when 'refactor' then 'R'.color(:white)
227
205
  else '?'.color(:blue)
228
206
  end
229
- pretty_output += ' '
230
- pretty_output += message['line'].to_s.color(:blue)
231
- pretty_output += " #{message['linter'].color(:green)}: "
232
- pretty_output += message['reason']
233
- pretty_output += "\n"
207
+ pretty_output += " #{message['line'].to_s.color(:blue)} #{message['linter'].color(:green)}: #{message['reason']} \n"
234
208
  end
235
209
  end
236
210
  pretty_output
237
211
  end
238
212
 
213
+
214
+
239
215
  end
240
216
  end
@@ -3,19 +3,13 @@ module Maximus
3
3
  class Brakeman < Maximus::Lint
4
4
 
5
5
  # Brakeman (requires Rails)
6
- #
7
6
  # @see Lint#initialize
8
7
  def result
9
8
 
10
- return unless is_rails?
11
-
12
9
  @task = 'brakeman'
13
-
14
- return unless temp_config(@task)
15
-
16
10
  @path = @settings[:root_dir] if @path.blank?
17
11
 
18
- return unless path_exists(@path)
12
+ return unless is_rails? && temp_config(@task) && path_exists?(@path)
19
13
 
20
14
  tmp = Tempfile.new('brakeman')
21
15
  quietly { `brakeman #{@path} -f json -o #{tmp.path} -q` }
@@ -55,12 +49,11 @@ module Maximus
55
49
  private
56
50
 
57
51
  # Convert to {file:README.md Maximus format}
58
- #
59
52
  # @param error [Hash] lint error
60
53
  # @return [Hash]
61
54
  def hash_for_brakeman(error, type)
62
55
  {
63
- linter: error['warning_type'],
56
+ linter: error['warning_type'].delete(' '),
64
57
  severity: type.chomp('s'),
65
58
  reason: error['message'],
66
59
  column: 0,
@@ -3,16 +3,12 @@ module Maximus
3
3
  class Jshint < Maximus::Lint
4
4
 
5
5
  # JSHint (requires node module)
6
- #
7
6
  # @see Lint#initialize
8
7
  def result
9
8
  @task = 'jshint'
10
-
11
- return unless temp_config(@task)
12
-
13
9
  @path = is_rails? ? "#{@settings[:root_dir]}/app/assets" : "#{@settings[:root_dir]}source/assets" if @path.blank?
14
10
 
15
- return unless path_exists(@path)
11
+ return unless temp_config(@task) && path_exists?(@path)
16
12
 
17
13
  node_module_exists(@task)
18
14
 
@@ -3,19 +3,13 @@ module Maximus
3
3
  class Railsbp < Maximus::Lint
4
4
 
5
5
  # rails_best_practice (requires Rails)
6
- #
7
6
  # @see Lint#initialize
8
7
  def result
9
8
 
10
- return unless is_rails?
11
-
12
9
  @task = 'railsbp'
13
-
14
- return unless temp_config(@task)
15
-
16
10
  @path = @settings[:root_dir] if @path.blank?
17
11
 
18
- return unless path_exists(@path)
12
+ return unless is_rails? && temp_config(@task) && path_exists?(@path)
19
13
 
20
14
  tmp = Tempfile.new('railsbp')
21
15
  `rails_best_practices #{@path} -f json --output-file #{tmp.path}`
@@ -27,15 +21,13 @@ module Maximus
27
21
  rbj = JSON.parse(railsbp).group_by { |s| s['filename'] }
28
22
  railsbp = {}
29
23
  rbj.each do |file, errors|
30
- if file
31
- # This crazy gsub grapbs scrubs the absolute path from the filename
32
- railsbp[file.gsub(Rails.root.to_s, '')[1..-1].to_sym] = errors.map { |o| hash_for_railsbp(o) }
33
- end
24
+ next unless file
25
+
26
+ # This crazy gsub scrubs the absolute path from the filename
27
+ filename = file.gsub(Rails.root.to_s, '')[1..-1]
28
+ railsbp[filename] = errors.map { |o| hash_for_railsbp(o) }
29
+
34
30
  end
35
- # The output of railsbp is a mix of strings and symbols
36
- # but resetting the JSON like this standardizes everything.
37
- # @todo Better way to get around this?
38
- railsbp = JSON.parse(railsbp.to_json)
39
31
  end
40
32
 
41
33
  @output[:files_inspected] ||= files_inspected('rb', ' ')
@@ -46,16 +38,15 @@ module Maximus
46
38
  private
47
39
 
48
40
  # Convert to {file:README.md Maximus format}
49
- #
50
41
  # @param error [Hash] lint error
51
42
  # @return [Hash]
52
43
  def hash_for_railsbp(error)
53
44
  {
54
- linter: error['message'].gsub(/\((.*)\)/, '').strip.parameterize('_').camelize,
55
- severity: 'warning',
56
- reason: error['message'],
57
- column: 0,
58
- line: error['line_number'].to_i
45
+ 'linter' => error['message'].gsub(/\((.*)\)/, '').strip.parameterize('_').camelize,
46
+ 'severity' => 'warning',
47
+ 'reason' => error['message'],
48
+ 'column' => 0,
49
+ 'line' => error['line_number'].to_i
59
50
  }
60
51
  end
61
52