forked from puppetlabs/rubocop-i18n
/
decorate_string_formatting_using_interpolation.rb
57 lines (48 loc) · 1.9 KB
/
decorate_string_formatting_using_interpolation.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# frozen_string_literal: true
module RuboCop
module Cop
module I18n
module GetText
# When using an decorated string to support I18N, any strings inside the decoration should not contain
# the '#{}' interpolation string as this makes it hard to translate the strings.
#
# Check GetText.supported_decorators for a list of decorators that can be used.
#
# @example
#
# # bad
#
# _("result is #{this_is_the_result}")
# n_("a string" + "a string with a #{float_value}")
#
# @example
#
# # good
#
# _("result is %{detail}" % {detail: message})
#
class DecorateStringFormattingUsingInterpolation < Base
def on_send(node)
decorator_name = node.loc.selector.source
return unless GetText.supported_decorator?(decorator_name)
method_name = node.method_name
arg_nodes = node.arguments
return unless !arg_nodes.empty? && contains_string_formatting_with_interpolation?(arg_nodes)
message_section = arg_nodes[0]
add_offense(message_section, message: "'#{method_name}' function, message string should not contain \#{} formatting")
end
private
def string_contains_interpolation_format?(str)
str.match(/\#{[^}]+}/)
end
def contains_string_formatting_with_interpolation?(node)
return node.any? { |n| contains_string_formatting_with_interpolation?(n) } if node.is_a?(Array)
return string_contains_interpolation_format?(node.source) if node.respond_to?(:type) && (node.str_type? || node.dstr_type?)
return node.children.any? { |child| contains_string_formatting_with_interpolation?(child) } if node.respond_to?(:children)
false
end
end
end
end
end
end