def check(options = {})
      options = setup_defaults(options)
      @options = options
      @chef_version = options[:chef_version] || DEFAULT_CHEF_VERSION

      warnings = []; last_dir = nil; matched_rule_tags = Set.new
      load_rules
      paths = specified_paths!(options)

      # Loop through each file to be processed and apply the rules
      files = files_to_process(paths)

      if options[:progress]
        puts "Checking #{files.count} files"
      end

      files.each do |p|
        relevant_tags = if options[:tags].any?
                          options[:tags]
                        else
                          rule_file_tags(p[:filename])
                        end

        progress = "."

        active_rules(relevant_tags).each do |rule|
          state = {
            path_type: p[:path_type],
            file: p[:filename],
            ast: read_ast(p[:filename]),
            rule: rule,
            last_dir: last_dir,
          }

          matches = if p[:path_type] == :cookbook
                      cookbook_matches(state)
                    else
                      other_matches(state)
                    end

          matches = remove_ignored(matches, state[:rule], state[:file])

          progress = "x" if matches.any?

          # Convert the matches into warnings
          matches.each do |match|
            warnings << Warning.new(state[:rule],
                                    { filename: state[:file] }.merge(match),
                                    options)
            matched_rule_tags << state[:rule].tags
          end
        end

        putc progress if options[:progress]

        last_dir = cookbook_dir(p[:filename])
      end

      puts "" if options[:progress]

      Review.new(paths, warnings)
    end
def check(options = {})
      options = setup_defaults(options)
      @options = options
      @chef_version = options[:chef_version] || DEFAULT_CHEF_VERSION

      warnings = []; last_dir = nil; matched_rule_tags = Set.new
      load_rules
      paths = specified_paths!(options)

      # Loop through each file to be processed and apply the rules
      files = files_to_process(paths)

      if options[:progress]
        puts "Checking #{files.count} files"
      end

      files.each do |p|
        relevant_tags = if options[:tags].any?
                          options[:tags]
                        else
                          rule_file_tags(p[:filename])
                        end

        progress = "."

        active_rules(relevant_tags).each do |rule|
          state = {
            path_type: p[:path_type],
            file: p[:filename],
            ast: read_ast(p[:filename]),
            rule: rule,
            last_dir: last_dir,
          }

          matches = if p[:path_type] == :cookbook
                      cookbook_matches(state)
                    else
                      other_matches(state)
                    end

          matches = remove_ignored(matches, state[:rule], state[:file])

          progress = "x" if matches.any?

          # Convert the matches into warnings
          matches.each do |match|
            warnings << Warning.new(state[:rule],
                                    { filename: state[:file] }.merge(match),
                                    options)
            matched_rule_tags << state[:rule].tags
          end
        end

        putc progress if options[:progress]

        last_dir = cookbook_dir(p[:filename])
      end

      puts "" if options[:progress]

      Review.new(paths, warnings)
    end
Review the cookbooks at the provided path, identifying potential
 improvements.

 The `options` are a hash where the valid keys are:

 * `:cookbook_paths` - Cookbook paths to lint
 * `:role_paths` - Role paths to lint
 * `:include_rules` - Paths to additional rules to apply
 * `:search_gems - If true then search for custom rules in installed gems.
 * `:tags` - The tags to filter rules based on
 * `:fail_tags` - The tags to fail the build on
 * `:exclude_paths` - Paths to exclude from linting