# frozen_string_literal: true module RailsBestPractices module Core # A Check class that takes charge of checking the sexp. class Check < CodeAnalyzer::Checker ALL_FILES = /.*/ CONTROLLER_FILES = /app\/(controllers|cells)\/.*\.rb$/ MIGRATION_FILES = /db\/migrate\/.*\.rb$/ MODEL_FILES = /app\/models\/.*\.rb$/ MAILER_FILES = /app\/models\/.*mailer\.rb$|app\/mailers\/.*\.rb/ VIEW_FILES = /app\/(views|cells)\/.*\.(erb|haml|slim|builder|rxml)$/ PARTIAL_VIEW_FILES = /app\/(views|cells)\/.*\/_.*\.(erb|haml|slim|builder|rxml)$/ ROUTE_FILES = /config\/routes.*\.rb/ SCHEMA_FILE = /db\/schema\.rb/ HELPER_FILES = /app\/helpers\/.*\.rb$/ DEPLOY_FILES = /config\/deploy.*\.rb/ CONFIG_FILES = /config\/(application|environment|environments\/.*)\.rb/ INITIALIZER_FILES = /config\/initializers\/.*\.rb/ CAPFILE = /Capfile/ GEMFILE_LOCK = /Gemfile\.lock/ SKIP_FILES = /db\/schema.rb/ def initialize(options = {}) options.each do |key, value| instance_variable_set("@#{key}", value) end end # check if the check will need to parse the node file. # # @param [String] the file name of node. # @return [Boolean] true if the check will need to parse the file. def parse_file?(node_file) is_interesting_file?(node_file) and !is_ignored?(node_file) end def is_interesting_file?(node_file) interesting_files.any? do |pattern| if pattern == ALL_FILES node_file =~ pattern && node_file !~ SKIP_FILES else node_file =~ pattern end end end def is_ignored?(node_file) regex_ignored_files.map { |r| !!r.match(node_file) }.inject(:|) end def regex_ignored_files @regex_ignored_files ||= Array(@ignored_files).map { |pattern| Regexp.new(pattern) } end # add error if source code violates rails best practice. # # @param [String] message, is the string message for violation of the rails best practice # @param [String] filename, is the filename of source code # @param [Integer] line_number, is the line number of the source code which is reviewing def add_error(message, filename = @node.file, line_number = @node.line_number) errors << RailsBestPractices::Core::Error.new( filename: filename, line_number: line_number, message: message, type: self.class.to_s, url: url ) end # errors that violate the rails best practices. def errors @errors ||= [] end # default url is empty. # # @return [String] the url of rails best practice def url self.class.url end # method_missing to catch all start and end process for each node type, like # # start_def # end_def # start_call # end_call # # if there is a "debug" method defined in check, each node will be output. def method_missing(method_name, *args) if method_name.to_s =~ /^start_/ p args if respond_to?(:debug) elsif method_name.to_s =~ /^end_/ # nothing to do else super end end class <