require 'find' module SlimLint # Finds Slim files that should be linted given a specified list of paths, glob # patterns, and configuration. class FileFinder # List of extensions of files to include under a directory when a directory # is specified instead of a file. VALID_EXTENSIONS = %w[.slim] # Create a file finder using the specified configuration. # # @param config [SlimLint::Configuration] def initialize(config) @config = config end # Return list of files to lint given the specified set of paths and glob # patterns. # @param patterns [Array] # @param excluded_patterns [Array] # @raise [SlimLint::Exceptions::InvalidFilePath] # @return [Array] list of actual files def find(patterns, excluded_patterns) extract_files_from(patterns).reject do |file| excluded_patterns.any? do |exclusion_glob| SlimLint::Utils.any_glob_matches?(exclusion_glob, file) end end end private # Extract the list of matching files given the list of glob patterns, file # paths, and directories. # # @param patterns [Array] # @return [Array] def extract_files_from(patterns) # rubocop:disable MethodLength files = [] patterns.each do |pattern| if File.file?(pattern) files << pattern else begin ::Find.find(pattern) do |file| files << file if slim_file?(file) end rescue ::Errno::ENOENT # File didn't exist; it might be a file glob pattern matches = ::Dir.glob(pattern) if matches.any? files += matches else # One of the paths specified does not exist; raise a more # descriptive exception so we know which one raise SlimLint::Exceptions::InvalidFilePath, "File path '#{pattern}' does not exist" end end end end files.uniq.sort end # Whether the given file should be treated as a Slim file. # # @param file [String] # @return [Boolean] def slim_file?(file) return false unless ::FileTest.file?(file) VALID_EXTENSIONS.include?(::File.extname(file)) end end end