# encoding: utf-8 require 'rails_best_practices/reviews/review' module RailsBestPractices module Reviews # Check ruby 1.8 style hash and suggest to change hash syntax to 1.9. # # Review process: # check hash nodes in all files, # if the sexp type of hash key nodes is not :@lable, # then the hash is ruby 1.8 style. class HashSyntaxReview < Review interesting_nodes :hash, :bare_assoc_hash interesting_files ALL_FILES VALID_SYMBOL_KEY = /\A[@$_A-Za-z]([_\w]*[!_=?\w])?\z/ def initialize(options = {}) super() @only_symbol = options[:only_symbol] @only_string = options[:only_string] end # check hash node to see if it is ruby 1.8 style. def start_hash(node) if !empty_hash?(node) && hash_is_18?(node) && valid_keys?(node) && !haml_class_node?(node) add_error "change Hash Syntax to 1.9" end end alias_method :start_bare_assoc_hash, :start_hash protected # check if hash node is empty. def empty_hash?(node) s(:hash, nil) == node || s(:bare_assoc_hash, nil) == node end # check if hash key/value pairs are ruby 1.8 style. def hash_is_18?(node) pair_nodes = :hash == node.sexp_type ? node[1][1] : node[1] return false if pair_nodes.blank? pair_nodes.size.times do |i| if @only_symbol return true if :symbol_literal == pair_nodes[i][1].sexp_type elsif @only_string return true if :string_literal == pair_nodes[i][1].sexp_type elsif :symbol_literal == pair_nodes[i][1].sexp_type || :string_literal == pair_nodes[i][1].sexp_type return true end end false end # check if the hash keys are valid to be converted to ruby 1.9 # syntax. def valid_keys?(node) node.hash_keys.all? { |key| key =~ VALID_SYMBOL_KEY } end # check if hash is generated by haml class or id nodes. def haml_class_node?(node) node.hash_size == 1 && (node.hash_keys.first == "class" || node.hash_keys.first == "id") end end end end