todo_lint 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8cfbc707bf83355d703a91f8d939cb5ff22a9909
4
- data.tar.gz: 9511008b2ac6197a9d310f9f2948a187ef806501
3
+ metadata.gz: 3d925d1749e411f4de9fc8c753060ab43ef53937
4
+ data.tar.gz: b8c5e5db3ca4f210b752ede2a47c43e451e72fab
5
5
  SHA512:
6
- metadata.gz: 50f3de4d47e85788b3b7d179c2834655c04515df9539b0e809ebacd4073e117b85dd86777ae338ae600ee0f57fcb0190763d984fbf88b6a8b7203e36be4f2b61
7
- data.tar.gz: d0bda1517784ce548ee12f3a7c9ef33c61460b40f9be95c78929e3fcd91876422138304d279c476530bd62afdc4d4ffddd834c6070577b33f024cf9c1e656a9e
6
+ metadata.gz: 99c1e602b9ef8577c0cd984b772a1417b4c1b658a026d6183d2420d1bf4f2a3e63b80c625d525f46221cd9ab61a29a853e9af6598a6c9cd7c6e9b3984af087e6
7
+ data.tar.gz: 45caf05a85101b675925986157b573ccf8d2ff7230435b448711d0078ef9141d6fbe90e426aad8fe878ee9070d1cca31e5d9f65bec811802fb6116b5c09465eb
data/.rubocop.yml CHANGED
@@ -1,3 +1,6 @@
1
+ AllCops:
2
+ DisplayCopNames: true
3
+
1
4
  Style/StringLiterals:
2
5
  EnforcedStyle: double_quotes
3
6
 
@@ -6,3 +9,12 @@ Style/SignalException:
6
9
 
7
10
  Style/HashSyntax:
8
11
  EnforcedStyle: hash_rockets
12
+
13
+ Metrics/AbcSize:
14
+ Exclude:
15
+ - lib/todo_lint/cli.rb
16
+
17
+ Metrics/MethodLength:
18
+ Exclude:
19
+ - lib/todo_lint/cli.rb
20
+ - lib/todo_lint/options.rb
data/.travis.yml CHANGED
@@ -1,7 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 2.0.0
4
- - 2.2.2
4
+ - 2.2.4
5
+ - 2.3.0
5
6
  before_install: gem install bundler -v 1.10.5
6
7
  script:
7
8
  - bundle exec rake form
data/Gemfile CHANGED
@@ -1,4 +1,11 @@
1
1
  source "https://rubygems.org"
2
2
 
3
+ gem "rake", "~> 10.0"
4
+ gem "rspec"
5
+ gem "timecop"
6
+ gem "rubocop"
7
+ gem "yardstick"
8
+ gem "pry"
9
+
3
10
  # Specify your gem's dependencies in todo_lint.gemspec
4
11
  gemspec
data/lib/todo_lint/cli.rb CHANGED
@@ -7,7 +7,7 @@ module TodoLint
7
7
  # @example
8
8
  # Cli.new(["-i", ".rb,.js"])
9
9
  # @api public
10
- def initialize(args) # rubocop:disable Metrics/AbcSize
10
+ def initialize(args) # rubocop:disable
11
11
  @options = Options.new.parse(args)
12
12
  if @options[:config_file]
13
13
  @options.merge!(ConfigFile.new.read_config_file(@options[:config_file]))
@@ -18,12 +18,48 @@ module TodoLint
18
18
  add_default_extensions unless @options.fetch(:files, []).any?
19
19
  end
20
20
 
21
+ # Perform the actions requested based on the options specified
22
+ #
21
23
  # @example
22
24
  # Cli.new(["-i", ".rb"]).run!
23
25
  # @return exit code 0 for success, 1 for failure
24
26
  # @api public
25
- # rubocop:disable Metrics/AbcSize
26
- def run! # rubocop:disable Metrics/MethodLength
27
+ def run!
28
+ if options[:report]
29
+ print_report
30
+ else
31
+ lint_codebase
32
+ end
33
+ end
34
+
35
+ # Loads the files to be read
36
+ # @return [Array<String>]
37
+ # @example cli.load_files(file_finder)
38
+ # @api public
39
+ def load_files(file_finder)
40
+ if file_finder.options.fetch(:files).empty?
41
+ file_finder.list(*options[:extensions])
42
+ else
43
+ file_finder.options.fetch(:files, [])
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ # Where are we looking for files?
50
+ # @return [String]
51
+ # @api private
52
+ attr_reader :path
53
+
54
+ # Options hash for all configurations
55
+ # @return [Hash]
56
+ # @api private
57
+ attr_reader :options
58
+
59
+ # Check requested files for problematic TODO comments
60
+ # @return exit code 0 for success, 1 for failure
61
+ # @api private
62
+ def lint_codebase
27
63
  finder = FileFinder.new(path, options)
28
64
  files = load_files(finder)
29
65
  files_count = files.count
@@ -52,29 +88,28 @@ module TodoLint
52
88
  end
53
89
  end
54
90
 
55
- # Loads the files to be read
56
- # @return [Array<String>]
57
- # @example cli.load_files(file_finder)
58
- # @api public
59
- def load_files(file_finder)
60
- if file_finder.options.fetch(:files).empty?
61
- file_finder.list(*options[:extensions])
62
- else
63
- file_finder.options.fetch(:files, [])
64
- end
65
- end
66
-
67
- private
68
-
69
- # Where are we looking for files?
70
- # @return [String]
91
+ # Print report of todos in codebase, then exit
92
+ #
93
+ # @return by exiting with 0
71
94
  # @api private
72
- attr_reader :path
95
+ def print_report
96
+ todos = []
97
+ finder = FileFinder.new(path, options)
98
+ files = load_files(finder)
99
+ files.each do |file|
100
+ todos += Todo.within(File.open(file))
101
+ end
102
+ todos.sort.each.with_index do |todo, num|
103
+ due_date = if todo.due_date
104
+ Rainbow(" (due #{todo.due_date.to_date})").blue
105
+ else
106
+ Rainbow(" (missing due date)").red
107
+ end
108
+ puts "#{num + 1}. #{todo.task}#{due_date}"
109
+ end
73
110
 
74
- # Options hash for all configurations
75
- # @return [Hash]
76
- # @api private
77
- attr_reader :options
111
+ exit 0
112
+ end
78
113
 
79
114
  # Pluralize a word based on the count
80
115
  # @return [String]
@@ -9,7 +9,7 @@ module TodoLint
9
9
  # @param args [Array<String>] arguments passed via the command line
10
10
  # @return [Hash] parsed options
11
11
  def parse(args)
12
- @options = {}
12
+ @options = { :report => false }
13
13
 
14
14
  OptionParser.new do |parser|
15
15
  parser.banner = "Usage: todo_lint [options] [files]"
@@ -17,6 +17,7 @@ module TodoLint
17
17
  exclude_file_options parser
18
18
  include_extension_options parser
19
19
  report_version parser
20
+ report_report_options parser
20
21
  end.parse!(args)
21
22
 
22
23
  # Any remaining arguments are assumed to be files
@@ -71,6 +72,15 @@ module TodoLint
71
72
  end
72
73
  end
73
74
 
75
+ # Checks if the user requested a report on the todos in their codebase
76
+ # @api private
77
+ # @return [Hash]
78
+ def report_report_options(parser)
79
+ parser.on("-r", "--report") do
80
+ options[:report] = true
81
+ end
82
+ end
83
+
74
84
  # Options hash for all configurations
75
85
  # @return [Hash]
76
86
  # @api private
@@ -24,7 +24,7 @@ module TodoLint
24
24
  return if judge.charge.nil?
25
25
 
26
26
  "#{todo_location} #{problem}\n" \
27
- "#{todo.line.chomp}\n" \
27
+ "#{todo.line.chomp.lstrip}\n" \
28
28
  "#{spaces}#{carets}"
29
29
  end
30
30
 
@@ -63,14 +63,21 @@ module TodoLint
63
63
  # @return [String]
64
64
  # @api private
65
65
  def spaces
66
- " " * (todo.character_number - 1)
66
+ " " * number_of_spaces
67
+ end
68
+
69
+ # How many spaces before the carets should there be?
70
+ # @return [Fixnum]
71
+ # @api private
72
+ def number_of_spaces
73
+ todo.character_number - 1 - (todo.line.length - todo.line.lstrip.length)
67
74
  end
68
75
 
69
76
  # Generate the ^^^^ characters to point at the flag
70
77
  # @return [String]
71
78
  # @api private
72
79
  def carets
73
- "^" * (todo.flag.length)
80
+ "^" * todo.flag.length
74
81
  end
75
82
  end
76
83
  end
@@ -4,8 +4,9 @@ module TodoLint
4
4
  # The regular expression that identifies todo comments
5
5
  PATTERN = /
6
6
  (?<flag> TODO ){0}
7
- (?<due_date> \(\d{4}-\d{2}-\d{2}\) ){0}
8
- \g<flag>\g<due_date>?
7
+ (?<due_date> \(\d{4}-\d{2}-\d{2}\)){0}
8
+ (?<task>.+){0}
9
+ \g<flag>\g<due_date>?: \g<task>
9
10
  /x
10
11
 
11
12
  # Search a file for all of the todo/fixme/etc comments within it
@@ -66,6 +67,17 @@ module TodoLint
66
67
  !match[:due_date].nil?
67
68
  end
68
69
 
70
+ # What is the actual task associated with this todo?
71
+ #
72
+ # @example
73
+ # todo.task #=> "Wash the car"
74
+ #
75
+ # @return [String]
76
+ # @api public
77
+ def task
78
+ match[:task].lstrip
79
+ end
80
+
69
81
  # When this todo is due
70
82
  # @example
71
83
  # due_todo.line #=> "# TODO(2015-05-24): go to the beach"
@@ -97,6 +109,31 @@ module TodoLint
97
109
  (line =~ PATTERN) + 1
98
110
  end
99
111
 
112
+ # Which todo is due sooner?
113
+ #
114
+ # @example
115
+ # [todo_one, todo_two].sort # this implicitly calls <=>
116
+ #
117
+ # @return [Fixnum]
118
+ # @api public
119
+ def <=>(other)
120
+ due_date_for_sorting <=> other.due_date_for_sorting
121
+ end
122
+
123
+ protected
124
+
125
+ # Helper for sorting todos
126
+ #
127
+ # @example
128
+ # todo.due_date_for_sorting #=> #<Date: 2016-02-06>
129
+ #
130
+ # @return [Date]
131
+ # @api semipublic
132
+ def due_date_for_sorting
133
+ # Date.new is like the beginning of time
134
+ due_date ? due_date.to_date : Date.new
135
+ end
136
+
100
137
  private
101
138
 
102
139
  # Analyze the line to help identify when the todo is due
@@ -2,5 +2,5 @@
2
2
  # it's in its own file so it can be required in the gemspec without requiring
3
3
  # everything else as well
4
4
  module TodoLint
5
- VERSION = "0.2.3"
5
+ VERSION = "0.3.0".freeze
6
6
  end
data/todo_lint.gemspec CHANGED
@@ -26,13 +26,8 @@ Gem::Specification.new do |spec|
26
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
27
  spec.require_paths = ["lib"]
28
28
 
29
+ spec.add_development_dependency "bundler", "~> 1.10"
30
+
29
31
  spec.add_runtime_dependency "required_arg", "~> 1.0"
30
32
  spec.add_runtime_dependency "rainbow", "~> 2.0.0"
31
- spec.add_development_dependency "bundler", "~> 1.10"
32
- spec.add_development_dependency "rake", "~> 10.0"
33
- spec.add_development_dependency "rspec"
34
- spec.add_development_dependency "timecop"
35
- spec.add_development_dependency "rubocop"
36
- spec.add_development_dependency "yardstick"
37
- spec.add_development_dependency "pry"
38
33
  end
metadata CHANGED
@@ -1,43 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: todo_lint
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max Jacobson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-07-11 00:00:00.000000000 Z
11
+ date: 2016-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: required_arg
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.0'
27
- - !ruby/object:Gem::Dependency
28
- name: rainbow
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: 2.0.0
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: 2.0.0
41
13
  - !ruby/object:Gem::Dependency
42
14
  name: bundler
43
15
  requirement: !ruby/object:Gem::Requirement
@@ -53,89 +25,33 @@ dependencies:
53
25
  - !ruby/object:Gem::Version
54
26
  version: '1.10'
55
27
  - !ruby/object:Gem::Dependency
56
- name: rake
28
+ name: required_arg
57
29
  requirement: !ruby/object:Gem::Requirement
58
30
  requirements:
59
31
  - - "~>"
60
32
  - !ruby/object:Gem::Version
61
- version: '10.0'
62
- type: :development
33
+ version: '1.0'
34
+ type: :runtime
63
35
  prerelease: false
64
36
  version_requirements: !ruby/object:Gem::Requirement
65
37
  requirements:
66
38
  - - "~>"
67
39
  - !ruby/object:Gem::Version
68
- version: '10.0'
69
- - !ruby/object:Gem::Dependency
70
- name: rspec
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: timecop
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: rubocop
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: yardstick
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
40
+ version: '1.0'
125
41
  - !ruby/object:Gem::Dependency
126
- name: pry
42
+ name: rainbow
127
43
  requirement: !ruby/object:Gem::Requirement
128
44
  requirements:
129
- - - ">="
45
+ - - "~>"
130
46
  - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
47
+ version: 2.0.0
48
+ type: :runtime
133
49
  prerelease: false
134
50
  version_requirements: !ruby/object:Gem::Requirement
135
51
  requirements:
136
- - - ">="
52
+ - - "~>"
137
53
  - !ruby/object:Gem::Version
138
- version: '0'
54
+ version: 2.0.0
139
55
  description: todo_lint can be integrated into a continuous integration workflow to
140
56
  keep todo comments from becoming stagnant over time. Just annotate the comment with
141
57
  a date, and if that date has passed, your build will fail, and you'll be reminded
@@ -190,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
106
  version: '0'
191
107
  requirements: []
192
108
  rubyforge_project:
193
- rubygems_version: 2.4.5
109
+ rubygems_version: 2.5.2
194
110
  signing_key:
195
111
  specification_version: 4
196
112
  summary: Linter to help you remember your todos