Skip to content

Instantly share code, notes, and snippets.

@tommeier
Created April 29, 2013 01:46
Show Gist options
  • Save tommeier/5479260 to your computer and use it in GitHub Desktop.
Save tommeier/5479260 to your computer and use it in GitHub Desktop.
Check for timezone aware rails code (using Cane: https://github.com/square/cane)
require 'set'
require 'cane/file'
require 'cane/task_runner'
module CaneExt
# Creates violations for files that do not meet code requirements.
class CodeCheck < Struct.new(:opts)
include Cane::CLI
def initialize(*args)
options = args.first.merge!(defaults(self.class))
super(options)
end
def self.key; :code; end
def self.name; "code checking"; end
def self.options
{
code_glob: [ 'Glob to run code checks over',
default: '{app,lib,spec}/**/*.rb',
variable: 'GLOB',
clobber: :no_code
],
code_exclude: [ 'Exclude from code check',
variable: 'GLOB',
default: ['lib/cane_ext/*'],
clobber: :no_code
],
code_timezones: [ 'Time zone aware commands',
default: {
'Date.today' => 'Time.zone.today',
'Time.now' => 'Time.zone.now',
'DateTime.now' => 'Time.zone.now',
'Time.at' => 'Time.zone.at',
'Time.parse' => 'Time.zone.parse',
'Time.new' => 'Time.zone.local',
'DateTime.new' => 'Time.zone.local',
'DateTime.strptime' => 'Time.zone.strptime'
},
variable: 'FILE',
clobber: :no_zone
],
no_code: ['Disable code checking', cast: ->(x) { !x }]
}
end
def violations
return [] if opts[:no_code]
worker.map(file_list) do |file_path|
map_lines(file_path) do |line, line_number|
violations_for_line(line.chomp).map {|message| {
file: file_path,
line: line_number + 1,
label: message,
description: "Lines violated code requirements"
}}
end
end.flatten
end
protected
def violations_for_line(line)
result = []
matched_zone_violation = /#{escaped_timezone_aware_violations.join('|')}/i.match(line)
result << "Line contains code that is not timezone aware: '#{matched_zone_violation}' should be '#{timezone_aware_violations[matched_zone_violation.to_s]}'" if matched_zone_violation
result
end
def timezone_aware_violations
opts.fetch(:code_timezones)
end
def escaped_timezone_aware_violations
timezone_aware_violations.keys.map { |violation| Regexp.escape(violation) }
end
def file_list
Dir[opts.fetch(:code_glob)].reject {|f| excluded?(f) }
end
def exclusions
@exclusions ||= opts.fetch(:code_exclude, []).flatten.map do |i|
Dir[i]
end.flatten.to_set
end
def excluded?(file)
exclusions.include?(file)
end
def map_lines(file_path, &block)
Cane::File.iterator(file_path).map.with_index(&block)
end
def worker
Cane.task_runner(opts)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment