remind_me 0.2.0 → 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
  SHA256:
3
- metadata.gz: 8ea5c318524b2dd5b11cb96b2ff7870e469a38bab9c895f3b62eb86c2e229c57
4
- data.tar.gz: ac8c013b669d56012c1a3cbac04eb7f363dfc0c1e3a22540800ef6dd7e938acf
3
+ metadata.gz: ad4645fc24e7238a0722f828cd63edac243c528dd649d52752067488a5777f72
4
+ data.tar.gz: 3ebd1346fc2391ff256fa99994aea089255ffa30692057f3b4e5bbb03dc4c0be
5
5
  SHA512:
6
- metadata.gz: f6a200f413d221cd864a1b33ea2b890fd04c4f4573575c3c48500311c02a148fc7726e50d7c2929c56071e688d609b00fdcd651517e2c5136bb8989d9cb1528b
7
- data.tar.gz: c192d2ea83b3f41e003b769d662cb5c3c1df9ee0d03404370f5033f0f8825417c2596755997ae522bc50168b2e5e4f22f4a6ea788def5e65ca401f9c95cc5a20
6
+ metadata.gz: 63ad32bbb05678a25fef45ec2bdc975d6926494b441b294ce715e187d6c0737f0ebb9dea40c34c1869091a492ebcefe0d528f39c8907ebb2ebccd399ba47970e
7
+ data.tar.gz: b7ae5dcb4acc4c4c71a02d320a1408aa167b97cf7e4c28223da1010ba8aafaf6d80da26100750ec39148b7d7f978c6d8bbe00f2d23e10c78e8235885f5fddaae
data/.gitignore CHANGED
@@ -10,3 +10,4 @@
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
12
  .ruby-version
13
+ /*.gem
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- remind_me (0.2.0)
4
+ remind_me (0.3.0)
5
+ parallel (~> 1.19.2)
5
6
  parser (~> 3.0.2.0)
6
7
 
7
8
  GEM
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Remind Me
2
2
  [![Tests](https://github.com/nikola-maric/remind_me/workflows/Tests/badge.svg?branch=master)](https://github.com/nikola-maric/remind_me/actions?query=workflow%3ATests+branch%3Amaster)
3
+ [![Gem Version](https://badge.fury.io/rb/remind_me.svg)](https://badge.fury.io/rb/remind_me)
3
4
 
4
5
  This gem's main purpose is to scan a file or directory for specific comments in the code. Comments are
5
6
  specified as a hash with `REMIND_ME:` (with a colon) prefixed to it, for example:
@@ -71,8 +72,6 @@ end
71
72
  **Important note**: in order to find and parse those comments properly, there are some limitations on how comments are used:
72
73
  - Entire `REMIND_ME: {}` comment needs to be on a single line, don't break it into multiple lines.
73
74
  - Thing after `REMIND_ME:` needs to have ruby hash structure
74
- - Both keys and values should be strings, symbols or strings/symbols, depending on reminder (for example, keys can
75
- be given as symbols, but for `version` values strings are only allowed)
76
75
 
77
76
  Each reminder type has a specific key that it "targets", for example `ruby_version`. If comment is found that does not
78
77
  match any reminder, we will print out error message specifying that + location where that reminder is found.
@@ -87,7 +86,7 @@ to any known reminder processor.
87
86
 
88
87
  Has following structure:
89
88
  `REMIND_ME: { gem: 'rails', version: '6', condition: :gte, message: 'Check this once rails 6 is available'}`.
90
- It targets all comment hash-es that have `gem/'gem'` in them as a key.
89
+ It targets all comment hash-es that have `:gem/'gem'` in them as a key.
91
90
  It will look at currently installed gems and compare that version to target version specified in comment.
92
91
 
93
92
  If version is omitted, we will only check if gem is installed or not (can be used to trigger
@@ -101,7 +100,7 @@ if message is omitted, it will default to `'Condition met!'`
101
100
 
102
101
  Has following structure:
103
102
  `REMIND_ME: { missing_gem: 'thor', message: 'Check this once we remove 'thor' gem'}`.
104
- It targets all comment hash-es that have `missing_gem/'missing_gem'` in them as a key.
103
+ It targets all comment hash-es that have `:missing_gem/'missing_gem'` in them as a key.
105
104
  It will look at currently installed gems and check to see if gem is installed, and will be triggered
106
105
  if its not.
107
106
 
@@ -111,7 +110,7 @@ if message is omitted, it will default to `'Condition met!'`
111
110
 
112
111
  Has following structure:
113
112
  `REMIND_ME: { ruby_version: '3', condition: :gte, message: 'Check this once we start using Ruby 3.0+'}`.
114
- It targets all comment hash-es that have `ruby_version/'ruby_version'` in them as a key.
113
+ It targets all comment hash-es that have `:ruby_version/'ruby_version'` in them as a key.
115
114
  It will look at currently used ruby version and compare that version to target version specified in comment.
116
115
 
117
116
  If condition is omitted, it will default to `eq`.
@@ -127,7 +126,7 @@ require 'remind_me'
127
126
 
128
127
  desc 'picks up REMIND_ME comments from codebase and checks if their conditions are met'
129
128
  task custom_check_reminders: :environment do
130
- RemindMe::Runner.new.check_reminders('/some/other/directory/')
129
+ RemindMe::Runner.new.check_reminders(check_path: '/some/other/directory/')
131
130
  end
132
131
  ```
133
132
 
@@ -138,8 +137,7 @@ is configured to work properly from within rake task.
138
137
  You can define custom reminders in your code by registering your reminder class with `RemindMe::Reminder::Generator`. For example:
139
138
  ```ruby
140
139
  # in initializers/timed_reminder.rb
141
- module Timed
142
- class Reminder < RemindMe::Reminder::BaseReminder
140
+ class TimedReminder < RemindMe::Reminder::BaseReminder
143
141
  apply_to_hash_with %i[after_time]
144
142
  validate_hash_ast key: :message, value_types: %i[str], default_value: 'Condition met!'
145
143
 
@@ -148,11 +146,10 @@ module Timed
148
146
  end
149
147
 
150
148
  def validation_errors
151
- Time.parse(hash_after_time)
149
+ Time.parse(hash_after_time) && []
152
150
  rescue StandardError => e
153
151
  ["'after_time' holds value that can't be parsed into time (#{e.message})"]
154
152
  end
155
- end
156
153
  end
157
154
  ```
158
155
  Subclassing `RemindMe::Reminder::BaseReminder` will automatically register it as one of potential reminder processors.
@@ -2,6 +2,8 @@
2
2
 
3
3
  require 'parser/current'
4
4
  require 'find'
5
+ require 'parallel/processor_count'
6
+ require 'parallel'
5
7
 
6
8
  require_relative 'version'
7
9
  require_relative 'bail_out'
@@ -11,41 +13,32 @@ require_relative 'utils/result_printer'
11
13
 
12
14
  module RemindMe
13
15
  class Runner
14
- include BailOut
15
- include Utils::Logger
16
+ extend BailOut
17
+ extend Utils::Logger
18
+ extend Parallel::ProcessorCount
16
19
 
17
- attr_reader :parser
18
-
19
- def initialize
20
- @parser = Parser::CurrentRuby.new
21
- parser.diagnostics.consumer = ->(_message) { }
22
- parser.diagnostics.ignore_warnings = true
23
- end
24
-
25
- def check_reminders(check_path: '.')
26
- log_info "Checking #{check_path} for any REMIND_ME comments..."
27
- all_reminders = collect_reminders(check_path)
28
- Utils::ResultPrinter.new(all_reminders).print_results
20
+ def self.check_reminders(check_path: '.')
21
+ Utils::ResultPrinter.new(collect_reminders(check_path)).print_results
29
22
  end
30
23
 
31
- def collect_reminders(parse_path)
32
- files = collect_ruby_files(parse_path)
24
+ def self.collect_reminders(path)
25
+ files = relevant_ruby_files(path)
33
26
  bail_out!('Need something to parse!') if files.empty?
34
- log_info "Found #{files.size} ruby files"
35
- raw_comments = collect_relevant_comments(files)
36
- raw_comments.flat_map { |raw_comment| RemindMe::Reminder::Generator.generate(raw_comment[0], raw_comment[1], parser) }
27
+ Parallel.flat_map(in_groups(files, processor_count, false)) do |files|
28
+ parser = silent_parser
29
+ raw_comments = collect_relevant_comments(files, parser)
30
+ raw_comments.flat_map { |raw_comment| RemindMe::Reminder::Generator.generate(raw_comment[0], raw_comment[1], parser) }
31
+ end
37
32
  end
38
33
 
39
- private
40
-
41
- def collect_relevant_comments(files)
42
- files.flat_map { |file| all_file_comments(file) }
43
- .map { |x| [x.location.expression.to_s, x.text.split('REMIND_ME:', 2)] }
44
- .select { |x| x[1].size == 2 }
45
- .map { |x| [x[0], x[1][1].split("\n").first] }
34
+ def self.silent_parser
35
+ parser = Parser::CurrentRuby.new
36
+ parser.diagnostics.consumer = ->(_message) {}
37
+ parser.diagnostics.ignore_warnings = true
38
+ parser
46
39
  end
47
40
 
48
- def all_file_comments(file)
41
+ def self.all_file_comments(file, parser)
49
42
  parser.reset
50
43
  source = File.read(file).force_encoding(parser.default_encoding)
51
44
  buffer = Parser::Source::Buffer.new(file)
@@ -53,7 +46,22 @@ module RemindMe
53
46
  parser.parse_with_comments(buffer).last
54
47
  end
55
48
 
56
- def collect_ruby_files(parse_path)
49
+ def self.collect_relevant_comments(files, parser)
50
+ files.flat_map { |file| all_file_comments(file, parser) }
51
+ .map { |x| [x.location.expression.to_s, x.text.split('REMIND_ME:', 2)] }
52
+ .select { |x| x[1].size == 2 }
53
+ .map { |x| [x[0], x[1][1].split("\n").first] }
54
+ end
55
+
56
+ def self.relevant_ruby_files(parse_path)
57
+ Parallel.flat_map(in_groups(collect_ruby_files(parse_path), processor_count, false)) do |files|
58
+ files.select do |file|
59
+ IO.foreach(file).any? { |line| line.include?('REMIND_ME:') }
60
+ end
61
+ end
62
+ end
63
+
64
+ def self.collect_ruby_files(parse_path)
57
65
  files = []
58
66
  if File.directory?(parse_path)
59
67
  Find.find(parse_path) do |path|
@@ -64,6 +72,24 @@ module RemindMe
64
72
  end
65
73
  files
66
74
  end
75
+
76
+ def self.in_groups(array, number, fill_with = nil)
77
+ division = array.size.div number
78
+ modulo = array.size % number
79
+ groups = []
80
+ start = 0
81
+ number.times do |index|
82
+ length = division + (modulo.positive? && modulo > index ? 1 : 0)
83
+ groups << last_group = array.slice(start, length)
84
+ last_group << fill_with if fill_with != false && modulo.positive? && length == division
85
+ start += length
86
+ end
87
+ groups
88
+ end
89
+
90
+ private_class_method :in_groups,
91
+ :collect_ruby_files,
92
+ :collect_relevant_comments
67
93
  end
68
94
  end
69
95
 
@@ -3,6 +3,6 @@ require 'remind_me'
3
3
  namespace :remind_me do
4
4
  desc 'picks up REMIND_ME comments from codebase and checks if their conditions are met'
5
5
  task check_reminders: :environment do
6
- RemindMe::Runner.new.check_reminders
6
+ RemindMe::Runner.check_reminders
7
7
  end
8
8
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RemindMe
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.0'
5
5
  end
data/remind_me.gemspec CHANGED
@@ -32,5 +32,6 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency 'rubocop'
33
33
  spec.add_development_dependency 'simplecov'
34
34
 
35
+ spec.add_dependency 'parallel', '~> 1.19.2'
35
36
  spec.add_dependency 'parser', '~> 3.0.2.0'
36
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remind_me
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nikola Marić
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-05 00:00:00.000000000 Z
11
+ date: 2021-12-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: parallel
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.19.2
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.19.2
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: parser
71
85
  requirement: !ruby/object:Gem::Requirement