i18n-tasks 1.0.5 → 1.0.8

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: 4d600c7425116c27f5cadffdc23d6e29de6137f90cea588e1a046ca1ec5970f5
4
- data.tar.gz: 91ea505ba06486d962e7be61eb52ca6af18bc8d481fdeb6a193f715b3c2f55a2
3
+ metadata.gz: 9d1d2fc604c929450bdf96a547513004630f57a1da7e368020b0313f4e4c67f4
4
+ data.tar.gz: 4b1a226b25f08c76d92998bc8cecd37de5e698f2f805da606804b8faa3fc0203
5
5
  SHA512:
6
- metadata.gz: 0e74a51969f4a82f8fa479dc31cb9236cc9de5d6255fe99d6de9eb392fb85e8771f4b21cbaed35f8c114258ada6c88086fb6fae0f1e0d97d8eb1f2d317c4f834
7
- data.tar.gz: 4a23c041ddef63f1b798f1455af637f77f369dcfb64e93f72c9592caf2105d2e9b15531679b30d7404746674596ee70078bba3525cbc2eacdce00d9d0ebc7054
6
+ metadata.gz: aeff02b2b63a8d64a37e80342b4dcf41c1a2c0379a8792b1064c6af431e18350c3130b890ee8bb83b4cc0cc6527b0721dabd2c7eb96ea420414b749d7c1b7a35
7
+ data.tar.gz: ce61d0886ca762588e101032f2d51207742f24f30d5c8d681594ea44ae08f508ac5f032f6bad2e27b117bf349794089753cd9669aa9e25de5d72831ac5db2d63
data/README.md CHANGED
@@ -24,7 +24,7 @@ i18n-tasks can be used with any project using the ruby [i18n gem][i18n-gem] (def
24
24
  Add i18n-tasks to the Gemfile:
25
25
 
26
26
  ```ruby
27
- gem 'i18n-tasks', '~> 1.0.5'
27
+ gem 'i18n-tasks', '~> 1.0.8'
28
28
  ```
29
29
 
30
30
  Copy the default [configuration file](#configuration):
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module I18n::Tasks::Scanners::AstMatchers
4
+ class BaseMatcher
5
+ def initialize(scanner:)
6
+ @scanner = scanner
7
+ end
8
+
9
+ protected
10
+
11
+ # If the node type is of `%i(sym str int false true)`, return the value as a string.
12
+ # Otherwise, if `config[:strict]` is `false` and the type is of `%i(dstr dsym)`,
13
+ # return the source as if it were a string.
14
+ #
15
+ # @param node [Parser::AST::Node]
16
+ # @param array_join_with [String, nil] if set to a string, arrays will be processed and their elements joined.
17
+ # @param array_flatten [Boolean] if true, nested arrays are flattened,
18
+ # otherwise their source is copied and surrounded by #{}. No effect unless `array_join_with` is set.
19
+ # @param array_reject_blank [Boolean] if true, empty strings and `nil`s are skipped.
20
+ # No effect unless `array_join_with` is set.
21
+ # @return [String, nil] `nil` is returned only when a dynamic value is encountered in strict mode
22
+ # or the node type is not supported.
23
+ def extract_string(node, array_join_with: nil, array_flatten: false, array_reject_blank: false)
24
+ return if node.nil?
25
+
26
+ if %i[sym str int].include?(node.type)
27
+ node.children[0].to_s
28
+ elsif %i[true false].include?(node.type)
29
+ node.type.to_s
30
+ elsif node.type == :nil
31
+ ''
32
+ elsif node.type == :array && array_join_with
33
+ extract_array_as_string(
34
+ node,
35
+ array_join_with: array_join_with,
36
+ array_flatten: array_flatten,
37
+ array_reject_blank: array_reject_blank
38
+ ).tap do |str|
39
+ # `nil` is returned when a dynamic value is encountered in strict mode. Propagate:
40
+ return nil if str.nil?
41
+ end
42
+ elsif !@scanner.config[:strict] && %i[dsym dstr].include?(node.type)
43
+ node.children.map do |child|
44
+ if %i[sym str].include?(child.type)
45
+ child.children[0].to_s
46
+ else
47
+ child.loc.expression.source
48
+ end
49
+ end.join
50
+ end
51
+ end
52
+
53
+ # Extract a hash pair with a given literal key.
54
+ #
55
+ # @param node [AST::Node] a node of type `:hash`.
56
+ # @param key [String] node key as a string (indifferent symbol-string matching).
57
+ # @return [AST::Node, nil] a node of type `:pair` or nil.
58
+ def extract_hash_pair(node, key)
59
+ node.children.detect do |child|
60
+ next unless child.type == :pair
61
+
62
+ key_node = child.children[0]
63
+ %i[sym str].include?(key_node.type) && key_node.children[0].to_s == key
64
+ end
65
+ end
66
+
67
+ # Extract an array as a single string.
68
+ #
69
+ # @param array_join_with [String] joiner of the array elements.
70
+ # @param array_flatten [Boolean] if true, nested arrays are flattened,
71
+ # otherwise their source is copied and surrounded by #{}.
72
+ # @param array_reject_blank [Boolean] if true, empty strings and `nil`s are skipped.
73
+ # @return [String, nil] `nil` is returned only when a dynamic value is encountered in strict mode.
74
+ def extract_array_as_string(node, array_join_with:, array_flatten: false, array_reject_blank: false)
75
+ children_strings = node.children.map do |child|
76
+ if %i[sym str int true false].include?(child.type)
77
+ extract_string child
78
+ else
79
+ # ignore dynamic argument in strict mode
80
+ return nil if @scanner.config[:strict]
81
+
82
+ if %i[dsym dstr].include?(child.type) || (child.type == :array && array_flatten)
83
+ extract_string(child, array_join_with: array_join_with)
84
+ else
85
+ "\#{#{child.loc.expression.source}}"
86
+ end
87
+ end
88
+ end
89
+ if array_reject_blank
90
+ children_strings.reject! do |x|
91
+ # empty strings and nils in the scope argument are ignored by i18n
92
+ x == ''
93
+ end
94
+ end
95
+ children_strings.join(array_join_with)
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'i18n/tasks/scanners/ast_matchers/base_matcher'
4
+ require 'i18n/tasks/scanners/results/occurrence'
5
+
6
+ module I18n::Tasks::Scanners::AstMatchers
7
+ class MessageReceiversMatcher < BaseMatcher
8
+ def initialize(scanner:, receivers:, message:)
9
+ super(scanner: scanner)
10
+ @receivers = Array(receivers)
11
+ @message = message
12
+ end
13
+
14
+ # @param send_node [Parser::AST::Node]
15
+ # @param method_name [Symbol, nil]
16
+ # @param location [Parser::Source::Map]
17
+ # @return [nil, [key, Occurrence]] full absolute key name and the occurrence.
18
+ def convert_to_key_occurrences(send_node, method_name, location: send_node.loc)
19
+ return unless node_match?(send_node)
20
+
21
+ receiver = send_node.children[0]
22
+ first_arg_node = send_node.children[2]
23
+ second_arg_node = send_node.children[3]
24
+
25
+ key = extract_string(first_arg_node)
26
+ return if key.nil?
27
+
28
+ key, default_arg = process_options(node: second_arg_node, key: key)
29
+
30
+ return if key.nil?
31
+
32
+ [
33
+ full_key(receiver: receiver, key: key, location: location, calling_method: method_name),
34
+ I18n::Tasks::Scanners::Results::Occurrence.from_range(
35
+ raw_key: key,
36
+ range: location.expression,
37
+ default_arg: default_arg
38
+ )
39
+ ]
40
+ end
41
+
42
+ private
43
+
44
+ def node_match?(node)
45
+ receiver = node.children[0]
46
+ message = node.children[1]
47
+
48
+ @message == message && @receivers.any? { |r| r == receiver }
49
+ end
50
+
51
+ def full_key(receiver:, key:, location:, calling_method:)
52
+ if receiver.nil?
53
+ # Relative keys only work if called via `t()` but not `I18n.t()`:
54
+ @scanner.absolute_key(
55
+ key,
56
+ location.expression.source_buffer.name,
57
+ calling_method: calling_method
58
+ )
59
+ else
60
+ key
61
+ end
62
+ end
63
+
64
+ def process_options(node:, key:)
65
+ return [key, nil] if node&.type != :hash
66
+
67
+ scope_node = extract_hash_pair(node, 'scope')
68
+
69
+ if scope_node
70
+ scope = extract_string(
71
+ scope_node.children[1],
72
+ array_join_with: '.',
73
+ array_flatten: true,
74
+ array_reject_blank: true
75
+ )
76
+ return nil if scope.nil? && scope_node.type != :nil
77
+
78
+ key = [scope, key].join('.') unless scope == ''
79
+ end
80
+ default_arg_node = extract_hash_pair(node, 'default')
81
+ default_arg = extract_string(default_arg_node.children[1]) if default_arg_node
82
+
83
+ [key, default_arg]
84
+ end
85
+ end
86
+ end
@@ -38,7 +38,9 @@ module I18n::Tasks::Scanners
38
38
  # @param node [::Parser::AST::Node]
39
39
  # @return [::Parser::AST::Node]
40
40
  def handler_missing(node)
41
- node = transform_misparsed_comment(node)
41
+ node = handle_comment(node)
42
+ return if node.nil?
43
+
42
44
  node.updated(
43
45
  nil,
44
46
  node.children.map { |child| node?(child) ? process(child) : child }
@@ -47,40 +49,22 @@ module I18n::Tasks::Scanners
47
49
 
48
50
  private
49
51
 
50
- # Works around incorrect handling of comments of the form:
51
- # <%# ... #>
52
- # (no space between % and #)
53
- #
54
- # With a space the AST is:
55
- #
56
- # s(:erb, nil, nil,
57
- # s(:code, " # this should not fail: ' "), nil)
52
+ # Convert ERB-comments to ::Parser::Source::Comment and skip processing node
58
53
  #
59
- # Without a space the AST is:
60
- #
61
- # s(:erb,
62
- # s(:indicator, "#"), nil,
63
- # s(:code, " this should not fail: ' "), nil)
64
- # @param node [::Parser::AST::Node]
65
- # @return [::Parser::AST::Node]
66
- def transform_misparsed_comment(node)
67
- return node unless node.type == :erb && node.children.size == 4 &&
68
- node.children[0]&.type == :indicator && node.children[0].children[0] == "#" &&
69
- node.children[1].nil? &&
70
- node.children[2]&.type == :code &&
71
- node.children[3].nil?
72
- code_node = node.children[2]
54
+ # @param node Parser::AST::Node Potential comment node
55
+ # @return Parser::AST::Node or nil
56
+ def handle_comment(node)
57
+ if node.type == :erb && node.children.size == 4 &&
58
+ node.children[0]&.type == :indicator && node.children[0].children[0] == '#' &&
59
+ node.children[2]&.type == :code
73
60
 
74
- # Prepend # to each line to make it a valid Ruby comment.
75
- code = code_node.children[0].split("\n").map do |line|
76
- next line if line =~ /^\s*#/
77
- "##{line}"
78
- end.join("\n")
61
+ # Do not continue parsing this node
62
+ comment = node.children[2]
63
+ @comments << ::Parser::Source::Comment.new(comment.location.expression)
64
+ return
65
+ end
79
66
 
80
- node.updated(
81
- nil,
82
- [nil, nil, code_node.updated(nil, [code]), nil]
83
- )
67
+ node
84
68
  end
85
69
 
86
70
  def node?(node)
@@ -63,6 +63,22 @@ module I18n::Tasks
63
63
  def hash
64
64
  [@path, @pos, @line_num, @line_pos, @line, @default_arg].hash
65
65
  end
66
+
67
+ # @param raw_key [String]
68
+ # @param range [Parser::Source::Range]
69
+ # @param default_arg [String, nil]
70
+ # @return [Results::Occurrence]
71
+ def self.from_range(raw_key:, range:, default_arg: nil)
72
+ Occurrence.new(
73
+ path: range.source_buffer.name,
74
+ pos: range.begin_pos,
75
+ line_num: range.line,
76
+ line_pos: range.column,
77
+ line: range.source_line,
78
+ raw_key: raw_key,
79
+ default_arg: default_arg
80
+ )
81
+ end
66
82
  end
67
83
  end
68
84
  end
@@ -1,57 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'ast'
4
- require 'set'
5
4
 
6
5
  module I18n::Tasks::Scanners
7
6
  class RubyAstCallFinder
8
7
  include AST::Processor::Mixin
9
8
 
10
- # @param receiver_messages [Set<Pair<[nil, AST::Node>, Symbol>>] The receiver-message pairs to look for.
11
- def initialize(receiver_messages:)
12
- super()
13
- @message_receivers = receiver_messages.each_with_object({}) do |(receiver, message), t|
14
- (t[message] ||= []) << receiver
15
- end
16
- end
17
-
18
9
  # @param root_node [Parser::AST:Node]
19
- # @yieldparam send_node [Parser::AST:Node]
20
- # @yieldparam method_name [nil, String] the surrounding method's name.
21
- def find_calls(root_node, &block)
22
- @callback = block
23
- process root_node
24
- ensure
25
- @callback = nil
26
- end
27
-
28
- # @param root_node (see #find_calls)
29
- # @yieldparam (see #find_calls)
30
- # @return [Array<block return values excluding nils>]
10
+ # @return [Pair<Parser::AST::Node, method_name as string>] for all nodes with :send type
31
11
  def collect_calls(root_node)
32
- results = []
33
- find_calls root_node do |send_node, method_name|
34
- result = yield send_node, method_name
35
- results << result if result
36
- end
37
- results
12
+ @results = []
13
+ process(root_node)
14
+ @results
38
15
  end
39
16
 
40
17
  def on_def(node)
41
18
  @method_name = node.children[0]
42
- handler_missing node
19
+ handler_missing(node)
43
20
  ensure
44
21
  @method_name = nil
45
22
  end
46
23
 
47
24
  def on_send(send_node)
48
- receiver = send_node.children[0]
49
- message = send_node.children[1]
50
- valid_receivers = @message_receivers[message]
51
- # use `any?` because `include?` checks type equality, but the receiver is a Parser::AST::Node != AST::Node.
52
- @callback.call(send_node, @method_name) if valid_receivers&.any? { |r| r == receiver }
25
+ @results << [send_node, @method_name]
26
+
53
27
  # always invoke handler_missing to get nested translations in children
54
- handler_missing send_node
28
+ handler_missing(send_node)
55
29
  nil
56
30
  end
57
31
 
@@ -3,27 +3,22 @@
3
3
  require 'i18n/tasks/scanners/file_scanner'
4
4
  require 'i18n/tasks/scanners/relative_keys'
5
5
  require 'i18n/tasks/scanners/ruby_ast_call_finder'
6
+ require 'i18n/tasks/scanners/ast_matchers/message_receivers_matcher'
6
7
  require 'parser/current'
7
8
 
8
- # rubocop:disable Metrics/AbcSize,Metrics/BlockNesting,Metrics/PerceivedComplexity
9
- # TODO: make this class more readable.
10
-
11
9
  module I18n::Tasks::Scanners
12
10
  # Scan for I18n.translate calls using whitequark/parser
13
- class RubyAstScanner < FileScanner # rubocop:disable Metrics/ClassLength
11
+ class RubyAstScanner < FileScanner
14
12
  include RelativeKeys
15
13
  include AST::Sexp
16
14
 
17
15
  MAGIC_COMMENT_PREFIX = /\A.\s*i18n-tasks-use\s+/.freeze
18
- RECEIVER_MESSAGES = [nil, AST::Node.new(:const, [nil, :I18n])].product(%i[t t! translate translate!])
19
16
 
20
17
  def initialize(**args)
21
18
  super(**args)
22
19
  @parser = ::Parser::CurrentRuby.new
23
20
  @magic_comment_parser = ::Parser::CurrentRuby.new
24
- @call_finder = RubyAstCallFinder.new(
25
- receiver_messages: config[:receiver_messages] || RECEIVER_MESSAGES
26
- )
21
+ @matchers = setup_matchers
27
22
  end
28
23
 
29
24
  protected
@@ -48,141 +43,10 @@ module I18n::Tasks::Scanners
48
43
  @parser.parse_with_comments(make_buffer(path))
49
44
  end
50
45
 
51
- # @param send_node [Parser::AST::Node]
52
- # @param method_name [Symbol, nil]
53
- # @param location [Parser::Source::Map]
54
- # @return [nil, [key, Occurrence]] full absolute key name and the occurrence.
55
- def send_node_to_key_occurrence(send_node, method_name, location: send_node.loc)
56
- if (first_arg_node = send_node.children[2]) &&
57
- (key = extract_string(first_arg_node))
58
- if (second_arg_node = send_node.children[3]) &&
59
- second_arg_node.type == :hash
60
- if (scope_node = extract_hash_pair(second_arg_node, 'scope'))
61
- scope = extract_string(scope_node.children[1],
62
- array_join_with: '.', array_flatten: true, array_reject_blank: true)
63
- return nil if scope.nil? && scope_node.type != :nil
64
-
65
- key = [scope, key].join('.') unless scope == ''
66
- end
67
- default_arg = if (default_arg_node = extract_hash_pair(second_arg_node, 'default'))
68
- extract_string(default_arg_node.children[1])
69
- end
70
- end
71
- full_key = if send_node.children[0].nil?
72
- # Relative keys only work if called via `t()` but not `I18n.t()`:
73
- absolute_key(key, location.expression.source_buffer.name, calling_method: method_name)
74
- else
75
- key
76
- end
77
- [full_key, range_to_occurrence(key, location.expression, default_arg: default_arg)]
78
- end
79
- end
80
-
81
- # Extract a hash pair with a given literal key.
82
- #
83
- # @param node [AST::Node] a node of type `:hash`.
84
- # @param key [String] node key as a string (indifferent symbol-string matching).
85
- # @return [AST::Node, nil] a node of type `:pair` or nil.
86
- def extract_hash_pair(node, key)
87
- node.children.detect do |child|
88
- next unless child.type == :pair
89
-
90
- key_node = child.children[0]
91
- %i[sym str].include?(key_node.type) && key_node.children[0].to_s == key
92
- end
93
- end
94
-
95
- # If the node type is of `%i(sym str int false true)`, return the value as a string.
96
- # Otherwise, if `config[:strict]` is `false` and the type is of `%i(dstr dsym)`,
97
- # return the source as if it were a string.
98
- #
99
- # @param node [Parser::AST::Node]
100
- # @param array_join_with [String, nil] if set to a string, arrays will be processed and their elements joined.
101
- # @param array_flatten [Boolean] if true, nested arrays are flattened,
102
- # otherwise their source is copied and surrounded by #{}. No effect unless `array_join_with` is set.
103
- # @param array_reject_blank [Boolean] if true, empty strings and `nil`s are skipped.
104
- # No effect unless `array_join_with` is set.
105
- # @return [String, nil] `nil` is returned only when a dynamic value is encountered in strict mode
106
- # or the node type is not supported.
107
- def extract_string(node, array_join_with: nil, array_flatten: false, array_reject_blank: false)
108
- if %i[sym str int].include?(node.type)
109
- node.children[0].to_s
110
- elsif %i[true false].include?(node.type)
111
- node.type.to_s
112
- elsif node.type == :nil
113
- ''
114
- elsif node.type == :array && array_join_with
115
- extract_array_as_string(
116
- node,
117
- array_join_with: array_join_with,
118
- array_flatten: array_flatten,
119
- array_reject_blank: array_reject_blank
120
- ).tap do |str|
121
- # `nil` is returned when a dynamic value is encountered in strict mode. Propagate:
122
- return nil if str.nil?
123
- end
124
- elsif !config[:strict] && %i[dsym dstr].include?(node.type)
125
- node.children.map do |child|
126
- if %i[sym str].include?(child.type)
127
- child.children[0].to_s
128
- else
129
- child.loc.expression.source
130
- end
131
- end.join
132
- end
133
- end
134
-
135
- # Extract an array as a single string.
136
- #
137
- # @param array_join_with [String] joiner of the array elements.
138
- # @param array_flatten [Boolean] if true, nested arrays are flattened,
139
- # otherwise their source is copied and surrounded by #{}.
140
- # @param array_reject_blank [Boolean] if true, empty strings and `nil`s are skipped.
141
- # @return [String, nil] `nil` is returned only when a dynamic value is encountered in strict mode.
142
- def extract_array_as_string(node, array_join_with:, array_flatten: false, array_reject_blank: false)
143
- children_strings = node.children.map do |child|
144
- if %i[sym str int true false].include?(child.type)
145
- extract_string child
146
- else
147
- # ignore dynamic argument in strict mode
148
- return nil if config[:strict]
149
-
150
- if %i[dsym dstr].include?(child.type) || (child.type == :array && array_flatten)
151
- extract_string(child, array_join_with: array_join_with)
152
- else
153
- "\#{#{child.loc.expression.source}}"
154
- end
155
- end
156
- end
157
- if array_reject_blank
158
- children_strings.reject! do |x|
159
- # empty strings and nils in the scope argument are ignored by i18n
160
- x == ''
161
- end
162
- end
163
- children_strings.join(array_join_with)
164
- end
165
-
166
46
  def keys_relative_to_calling_method?(path)
167
47
  /controllers|mailers/.match(path)
168
48
  end
169
49
 
170
- # @param raw_key [String]
171
- # @param range [Parser::Source::Range]
172
- # @param default_arg [String, nil]
173
- # @return [Results::Occurrence]
174
- def range_to_occurrence(raw_key, range, default_arg: nil)
175
- Results::Occurrence.new(
176
- path: range.source_buffer.name,
177
- pos: range.begin_pos,
178
- line_num: range.line,
179
- line_pos: range.column,
180
- line: range.source_line,
181
- raw_key: raw_key,
182
- default_arg: default_arg
183
- )
184
- end
185
-
186
50
  # Create an {Parser::Source::Buffer} with the given contents.
187
51
  # The contents are assigned a {Parser::Source::Buffer#raw_source}.
188
52
  #
@@ -211,12 +75,23 @@ module I18n::Tasks::Scanners
211
75
  magic_comments.flat_map do |comment|
212
76
  @parser.reset
213
77
  associated_node = comment_to_node[comment]
214
- @call_finder.collect_calls(
215
- @parser.parse(make_buffer(path, comment.text.sub(MAGIC_COMMENT_PREFIX, '').split(/\s+(?=t)/).join('; ')))
216
- ) do |send_node, _method_name|
217
- # method_name is not available at this stage
218
- send_node_to_key_occurrence(send_node, nil, location: associated_node || comment.location)
78
+ ast = @parser.parse(make_buffer(path, comment.text.sub(MAGIC_COMMENT_PREFIX, '').split(/\s+(?=t)/).join('; ')))
79
+ calls = RubyAstCallFinder.new.collect_calls(ast)
80
+ results = []
81
+
82
+ # method_name is not available at this stage
83
+ calls.each do |send_node, _method_name|
84
+ @matchers.each do |matcher|
85
+ result = matcher.convert_to_key_occurrences(
86
+ send_node,
87
+ nil,
88
+ location: associated_node || comment.location
89
+ )
90
+ results << result if result
91
+ end
219
92
  end
93
+
94
+ results
220
95
  end
221
96
  end
222
97
 
@@ -225,10 +100,39 @@ module I18n::Tasks::Scanners
225
100
  # @param ast {Parser::Source::Comment}
226
101
  # @return [nil, [key, Occurrence]] full absolute key name and the occurrence.
227
102
  def ast_to_occurences(ast)
228
- @call_finder.collect_calls(ast) do |send_node, method_name|
229
- send_node_to_key_occurrence(send_node, method_name)
103
+ calls = RubyAstCallFinder.new.collect_calls(ast)
104
+ results = []
105
+ calls.each do |send_node, method_name|
106
+ @matchers.each do |matcher|
107
+ result = matcher.convert_to_key_occurrences(send_node, method_name)
108
+ results << result if result
109
+ end
110
+ end
111
+
112
+ results
113
+ end
114
+
115
+ def setup_matchers
116
+ if config[:receiver_messages]
117
+ config[:receiver_messages].map do |receiver, message|
118
+ AstMatchers::MessageReceiversMatcher.new(
119
+ receivers: [receiver],
120
+ message: message,
121
+ scanner: self
122
+ )
123
+ end
124
+ else
125
+ %i[t t! translate translate!].map do |message|
126
+ AstMatchers::MessageReceiversMatcher.new(
127
+ receivers: [
128
+ AST::Node.new(:const, [nil, :I18n]),
129
+ nil
130
+ ],
131
+ message: message,
132
+ scanner: self
133
+ )
134
+ end
230
135
  end
231
136
  end
232
137
  end
233
138
  end
234
- # rubocop:enable Metrics/AbcSize,Metrics/BlockNesting,Metrics/PerceivedComplexity
@@ -2,6 +2,6 @@
2
2
 
3
3
  module I18n
4
4
  module Tasks
5
- VERSION = '1.0.5'
5
+ VERSION = '1.0.8'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - glebm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-26 00:00:00.000000000 Z
11
+ date: 2022-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -371,6 +371,8 @@ files:
371
371
  - lib/i18n/tasks/references.rb
372
372
  - lib/i18n/tasks/reports/base.rb
373
373
  - lib/i18n/tasks/reports/terminal.rb
374
+ - lib/i18n/tasks/scanners/ast_matchers/base_matcher.rb
375
+ - lib/i18n/tasks/scanners/ast_matchers/message_receivers_matcher.rb
374
376
  - lib/i18n/tasks/scanners/erb_ast_processor.rb
375
377
  - lib/i18n/tasks/scanners/erb_ast_scanner.rb
376
378
  - lib/i18n/tasks/scanners/file_scanner.rb