module Danger # # This is a danger plugin to detect any TODO/FIXME entries left in the code. # # @example Ensure, by warning, there are no TODOS left in the modified code # # todoist.warn_for_todos # # @example Ensure, by failing the build, no TODOS left in the modified code # # todoist.fail_for_todos # # @example Set custom warning message for warning # # todoist.message = "Please fix all TODOS" # todoist.warn_for_todos # # @example List every todo item # # todoist.warn_for_todos # todoist.print_todos_table # # @example Do anything with the todos. Todos have `text` and `file` properties # # todoist.todos.each { |todo| puts todo.text } # # @see hanneskaeufler/danger-todoist # @tags todos, fixme # class DangerTodoist < Plugin DEFAULT_MESSAGE = "There remain todo items in the modified code.".freeze DEFAULT_KEYWORDS = %w(TODO FIXME).freeze # # Message to be shown # # @attr_writer [String] message Custom message shown when todos were found # @return [void] # attr_writer :message # # Keywords to recognize as todos # # @attr_writer [Array] keywords Custom array of strings to identify todos # @return [void] attr_writer :keywords # # Adds a warning if there are todos found in the modified code # # @return [void] # def warn_for_todos call_method_for_todos(:warn) end # # Adds an error if there are todos found in the modified code # # @return [void] # def fail_for_todos call_method_for_todos(:fail) end # # Adds a list of offending files to the danger comment # # @return [void] # def print_todos_table find_todos if @todos.nil? return if @todos.empty? markdown("#### Todos left in files") @todos .group_by(&:file) .each { |file, todos| print_todos_per_file(file, todos) } end # # Returns the list of todos in the current diff set # # @return [Array of todos] # def todos find_todos if @todos.nil? @todos end private def print_todos_per_file(file, todos) markdown("- #{file}") todos .select(&:text) .each { |todo| markdown(" - Line #{todo.line_number}: #{todo.text}") } end def call_method_for_todos(method) find_todos if @todos.nil? public_send(method, message, sticky: false) unless @todos.empty? end def find_todos @todos = [] return if files_of_interest.empty? @todos = finders .map { |finder_class| finder_class.new(keywords) } .map { |finder| finder.call(diffs_of_interest) } .flatten end def keywords @keywords || DEFAULT_KEYWORDS end def message @message || DEFAULT_MESSAGE end def files_of_interest git.modified_files + git.added_files end # for whatever reason nils/false weird things creep # into the files_of_interest. We have to make sure to only # try to look up diffs for actual filepaths (strings) def diffs_of_interest files_of_interest.map do |file| diff = EmptyDiff.new begin diff = git.diff_for_file(file) rescue NoMethodError log_unable_to_find_diff(file.inspect) end diff end end def log_unable_to_find_diff(file) markdown("* danger-todoist was unable to determine diff for \"#{file}\".") end def finders [DiffTodoFinder] end end # Null object incase a diff cannot be determined class EmptyDiff def patch "" end end end