Class: TodoLint::Todo

Inherits:
Object
  • Object
show all
Defined in:
lib/todo_lint/todo.rb

Overview

Todo represents a todo/fixme/etc comment within your source code

Constant Summary collapse

PATTERN =

The regular expression that identifies todo comments

/
(?<flag> TODO ){0}
(?<due_date> \(\d{4}-\d{2}-\d{2}\)){0}
(?<tag>\#\w+){0}
(?<task>.+){0}
\g<flag>(?:\g<due_date>|(?:\(\g<tag>\)))?: \g<task>
/x

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(line, line_number: RequiredArg.new(:line_number), path: RequiredArg.new(:path), config: RequiredArg.new(:config)) ⇒ Todo

A new Todo must know a few things

Examples:

Todo.new("#TODO: get a boat", line_number: 4)


66
67
68
69
70
71
72
73
74
75
# File 'lib/todo_lint/todo.rb', line 66

def initialize(line,
               line_number: RequiredArg.new(:line_number),
               path: RequiredArg.new(:path),
               config: RequiredArg.new(:config))
  absent_todo!(line) unless self.class.present_in?(line)
  @line = line
  @line_number = line_number
  @path = path
  @config = config
end

Instance Attribute Details

#lineString (readonly)

The content of the line of source code containing the todo comment

Examples:

todo.line #=> "# TODO: refactor me"

Returns:

  • (String)


45
46
47
# File 'lib/todo_lint/todo.rb', line 45

def line
  @line
end

#line_numberFixnum (readonly)

The 1-indexed line on which the todo was discovered

Examples:

todo.line_number #=> 4

Returns:

  • (Fixnum)


52
53
54
# File 'lib/todo_lint/todo.rb', line 52

def line_number
  @line_number
end

#pathString (readonly)

The absolute path to the file where we found this todo

Examples:

todo.path #=> "/Users/max/src/layabout/Gemfile"

Returns:

  • (String)


60
61
62
# File 'lib/todo_lint/todo.rb', line 60

def path
  @path
end

Class Method Details

.present_in?(line) ⇒ Boolean

Does this line contain a todo?

Examples:

Todo.present_in?("hello") #=> false
Todo.present_in?("TODO") #=> true

Returns:

  • (Boolean)


36
37
38
# File 'lib/todo_lint/todo.rb', line 36

def self.present_in?(line)
  line =~ PATTERN
end

.within(file, config: RequiredArg.new(:config)) ⇒ Array<Todo>

Search a file for all of the todo/fixme/etc comments within it

Examples:

Todo.within(File.open("app.rb"))

Returns:



18
19
20
21
22
23
24
25
26
27
28
# File 'lib/todo_lint/todo.rb', line 18

def self.within(file, config: RequiredArg.new(:config))
  file.each_line.with_index.map do |line, line_number|
    next unless present_in?(line)
    new(
      line,
      :line_number => line_number + 1,
      :path => file.path,
      :config => config
    )
  end.compact
end

Instance Method Details

#<=>(other) ⇒ Fixnum

Which todo is due sooner?

Examples:

[todo_one, todo_two].sort # this implicitly calls <=>

Returns:

  • (Fixnum)


168
169
170
# File 'lib/todo_lint/todo.rb', line 168

def <=>(other)
  due_date_for_sorting <=> other.due_date_for_sorting
end

#annotated?Boolean

Was this todo annotated with a due date?

Examples:

annotated_todo.line #=> "# TODO(2013-05-24): learn to fly"
annotated_todo.annotated? #=> true

not_annotated_todo.line #=> "# TODO: read a poem"
not_annotated_todo.annotated? #=> false"

Returns:

  • (Boolean)


86
87
88
# File 'lib/todo_lint/todo.rb', line 86

def annotated?
  !match[:due_date].nil? || !match[:tag].nil?
end

#character_numberFixnum

The 1-indexed character at which the todo comment is found

Examples:

todo.character_number #=> 4

Returns:

  • (Fixnum)


134
135
136
# File 'lib/todo_lint/todo.rb', line 134

def character_number
  (line =~ PATTERN) + 1
end

#due_dateDueDate, NilClass

When this todo is due

Examples:

due_todo.line #=> "# TODO(2015-05-24): go to the beach"
due_todo.due_date.to_date #=> #<Date: 2015-05-24>
not_due_todo.line #=> "# TODO: become a fish"
not_due_todo.due_date #=> nil

Returns:

  • (DueDate)

    if there is a due date

  • (NilClass)

    if there is no due date



110
111
112
113
114
115
116
117
118
# File 'lib/todo_lint/todo.rb', line 110

def due_date
  return unless annotated?
  return @due_date if defined?(@due_date)
  @due_date = if match[:due_date]
                DueDate.from_annotation(match[:due_date])
              elsif match[:tag]
                lookup_tag_due_date
              end
end

#flagString

What did the developer write to get our attention?

Examples:

todo.flag #=> "TODO"

Returns:

  • (String)


125
126
127
# File 'lib/todo_lint/todo.rb', line 125

def flag
  match[:flag]
end

#relative_pathString

The relative path to the file where this todo was found

Examples:

todo.relative #=> "spec/spec_helper.rb"

Returns:

  • (String)


179
180
181
182
# File 'lib/todo_lint/todo.rb', line 179

def relative_path
  current_dir = Pathname.new(File.expand_path("./"))
  Pathname.new(path).relative_path_from(current_dir).to_s
end

#tagString, NilClass

What tag does this todo use?

Examples:

todo.tag #=> "#shipit"
todo.tag #=> nil

Returns:

  • (String)

    if the Todo has a tag

  • (NilClass)

    if the Todo has no tag



157
158
159
# File 'lib/todo_lint/todo.rb', line 157

def tag
  match[:tag]
end

#tag?Boolean

Was this todo using a tag (as opposed to a direct due date)?

Examples:

todo.tag? #=> true

Returns:

  • (Boolean)


144
145
146
# File 'lib/todo_lint/todo.rb', line 144

def tag?
  !match[:tag].nil?
end

#taskString

What is the actual task associated with this todo?

Examples:

todo.task #=> "Wash the car"

Returns:

  • (String)


97
98
99
# File 'lib/todo_lint/todo.rb', line 97

def task
  match[:task].lstrip
end