rubocop-sane 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46577dac32dde6106d874ce5fa85e7a54a94d589e075b54d281d7b68d9649e19
4
- data.tar.gz: 8e1280ecc3bee57ed3cb65924ee86ce9b02c6032e74ee58864989fdf9b4cdac9
3
+ metadata.gz: dd899cb79b69d5e80e9712f16cff748e59565061964ee199ee948413acadb4ae
4
+ data.tar.gz: d5199b3b74466a2ad62c7fc0b6c15633e3c07b3e4aa67a9465b65293c51917f3
5
5
  SHA512:
6
- metadata.gz: 70e429be341dc7b52167483547162dcf4f52a99f278c98782eec989d0a8a061b72f40cd8dfd5d8b9d56cdfd79b9eb3c1934c353e1de29b435f46790b9c1586eb
7
- data.tar.gz: 58dc631f79eb2cb9a022359fe0ba690ae55607b927b840113f469f648909f205619d5ef15fd427d88a24ed1ddac43fd7156b0aa7c1576385585951b5228706ea
6
+ metadata.gz: f0a243dbd2dab34f2907cf9dd18abf84226ff2cc70992ca7a84faa04a700c8be0c307b07767a7df073a5d52a05d4d21f3aa4868b9acb06c464d84c05a4723a46
7
+ data.tar.gz: 403df07bdb9611e535edf8aa868c84bd80c7c62c643380d7e9f1dfc0d2c4a102969c83a2f42ee0f7f7b0cf5f45ec235850de31a2e9cac3a03e91006aaa9e06c1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2025-12-20
4
+
5
+ - Add `Sane/OutdatedComments` cop
6
+
7
+ ## [0.2.0] - 2025-12-20
8
+
9
+ - Add `Sane/NoMethodCallAfterEnd` cop
10
+ - Improve `Sane/EmptyLineBeforeComment` cop
11
+
3
12
  ## [0.1.0] - 2025-12-19
4
13
 
5
14
  - Initial release
data/config/default.yml CHANGED
@@ -31,3 +31,8 @@ Sane/NoMethodCallAfterEnd:
31
31
  Description: "Prohibits calling methods directly after `end`."
32
32
  Enabled: true
33
33
  VersionAdded: "0.1.0"
34
+
35
+ Sane/OutdatedComments:
36
+ Description: "Detects TODO/NOTE/FIXME comments with dates in the past."
37
+ Enabled: true
38
+ VersionAdded: "0.2.0"
@@ -48,6 +48,7 @@ module RuboCop
48
48
  private
49
49
 
50
50
  def check_comment(comment)
51
+ return if rubocop_directive?(comment)
51
52
  return if inline_comment?(comment)
52
53
  return if first_line?(comment)
53
54
  return if preceded_by_empty_line?(comment)
@@ -64,6 +65,10 @@ module RuboCop
64
65
  end
65
66
  end
66
67
 
68
+ def rubocop_directive?(comment)
69
+ comment.text.match?(/\A#\s*rubocop:(enable|disable|todo)\b/)
70
+ end
71
+
67
72
  def inline_comment?(comment)
68
73
  # Check if there's code before the comment on the same line
69
74
  comment_line = processed_source.lines[comment.loc.line - 1]
@@ -106,26 +111,26 @@ module RuboCop
106
111
  def block_start_pattern?(line)
107
112
  stripped = line.strip
108
113
 
109
- # Class, module, method definitions
110
- return true if stripped.match?(/\A(class|module|def)\s/)
114
+ # Class, module, method definitions (including decorated methods like `memoize def`)
115
+ return true if stripped.match?(/\A(class|module)\s/) || stripped.match?(/\bdef\s/)
111
116
 
112
117
  # Control structures
113
- return true if stripped.match?(/\A(if|unless|case|while|until|for|begin)\s/)
114
- return true if stripped == "begin"
118
+ return true if stripped.match?(/\A(if|unless|case|while|until|for|begin)\b/)
115
119
 
116
120
  # Block openers (do or {)
117
- return true if stripped.end_with?(" do", " do |", "\tdo")
118
- return true if stripped.match?(/do\s*\|[^|]*\|\s*\z/)
119
- return true if stripped.end_with?("{")
120
- return true if stripped.match?(/\{\s*\|[^|]*\|\s*\z/)
121
+ return true if block_opener?(stripped)
121
122
 
122
123
  # Rescue/ensure/else/elsif/when inside blocks
123
124
  return true if stripped.match?(/\A(rescue|ensure|else|elsif|when)\b/)
124
125
 
125
126
  # Private/protected/public access modifiers
126
- return true if stripped.match?(/\A(private|protected|public)\s*\z/)
127
+ stripped.match?(/\A(private|protected|public)\s*\z/)
128
+ end
127
129
 
128
- false
130
+ def block_opener?(line)
131
+ line.end_with?(" do", " do |", "\tdo", "{", "[") ||
132
+ line.match?(/do\s*\|[^|]*\|\s*\z/) ||
133
+ line.match?(/\{\s*\|[^|]*\|\s*\z/)
129
134
  end
130
135
  end
131
136
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "date"
4
+
5
+ module RuboCop
6
+ module Cop
7
+ module Sane
8
+ # Detects TODO/NOTE/FIXME comments with dates that are in the past.
9
+ #
10
+ # This cop helps ensure that dated comments are reviewed when their
11
+ # target date has passed.
12
+ #
13
+ # @example
14
+ # # bad (when date is in the past)
15
+ # # TODO[2024-01-01]: Remove this after migration
16
+ # # NOTE[2023-06-15]: Temporary workaround
17
+ # # FIXME[2024-03-01]: Fix this bug
18
+ #
19
+ # # good (when date is in the future or today)
20
+ # # TODO[2025-12-31]: Remove this after migration
21
+ #
22
+ class OutdatedComments < Base
23
+ COMMENT_PATTERN = /^#\s*(NOTE|TODO|FIXME)\[(\d{4}-\d{2}-\d{2})\]:/i
24
+ MSG = "Review or remove this outdated comment dated %<date>s"
25
+
26
+ def on_new_investigation
27
+ return unless processed_source.valid_syntax?
28
+
29
+ processed_source.comments.each do |comment|
30
+ check_comment(comment)
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def check_comment(comment)
37
+ match = comment.text.match(COMMENT_PATTERN)
38
+ return unless match
39
+
40
+ date_str = match[2]
41
+ parsed_date = Date.parse(date_str)
42
+
43
+ return if parsed_date >= Date.today
44
+
45
+ message = format(MSG, date: date_str)
46
+ add_offense(comment.source_range, severity: :warning, message:)
47
+ rescue Date::Error
48
+ # Invalid date format, ignore
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -5,3 +5,4 @@ require_relative "sane/conditional_assignment_allow_ternary"
5
5
  require_relative "sane/empty_line_before_comment"
6
6
  require_relative "sane/empty_lines_around_multiline_block"
7
7
  require_relative "sane/no_method_call_after_end"
8
+ require_relative "sane/outdated_comments"
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Sane
5
- VERSION = "0.1.0"
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-sane
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kodkod
@@ -67,6 +67,7 @@ files:
67
67
  - lib/rubocop/cop/sane/empty_line_before_comment.rb
68
68
  - lib/rubocop/cop/sane/empty_lines_around_multiline_block.rb
69
69
  - lib/rubocop/cop/sane/no_method_call_after_end.rb
70
+ - lib/rubocop/cop/sane/outdated_comments.rb
70
71
  - lib/rubocop/cop/sane_cops.rb
71
72
  - lib/rubocop/sane.rb
72
73
  - lib/rubocop/sane/plugin.rb