diff --git a/lib/i18n/tasks/scanners/erb_ast_processor.rb b/lib/i18n/tasks/scanners/erb_ast_processor.rb index 5a219753..1ccd2a5b 100644 --- a/lib/i18n/tasks/scanners/erb_ast_processor.rb +++ b/lib/i18n/tasks/scanners/erb_ast_processor.rb @@ -38,7 +38,9 @@ def on_code(node) # @param node [::Parser::AST::Node] # @return [::Parser::AST::Node] def handler_missing(node) - node = transform_misparsed_comment(node) + node = handle_comment(node) + return if node.nil? + node.updated( nil, node.children.map { |child| node?(child) ? process(child) : child } @@ -47,40 +49,22 @@ def handler_missing(node) private - # Works around incorrect handling of comments of the form: - # <%# ... #> - # (no space between % and #) - # - # With a space the AST is: - # - # s(:erb, nil, nil, - # s(:code, " # this should not fail: ' "), nil) + # Convert ERB-comments to ::Parser::Source::Comment and skip processing node # - # Without a space the AST is: - # - # s(:erb, - # s(:indicator, "#"), nil, - # s(:code, " this should not fail: ' "), nil) - # @param node [::Parser::AST::Node] - # @return [::Parser::AST::Node] - def transform_misparsed_comment(node) - return node unless node.type == :erb && node.children.size == 4 && - node.children[0]&.type == :indicator && node.children[0].children[0] == "#" && - node.children[1].nil? && - node.children[2]&.type == :code && - node.children[3].nil? - code_node = node.children[2] + # @param node Parser::AST::Node Potential comment node + # @return Parser::AST::Node or nil + def handle_comment(node) + if node.type == :erb && node.children.size == 4 && + node.children[0]&.type == :indicator && node.children[0].children[0] == '#' && + node.children[2]&.type == :code - # Prepend # to each line to make it a valid Ruby comment. - code = code_node.children[0].split("\n").map do |line| - next line if line =~ /^\s*#/ - "##{line}" - end.join("\n") + # Do not continue parsing this node + comment = node.children[2] + @comments << ::Parser::Source::Comment.new(comment.location.expression) + return + end - node.updated( - nil, - [nil, nil, code_node.updated(nil, [code]), nil] - ) + node end def node?(node) diff --git a/spec/fixtures/used_keys/app/views/application/comments.html.erb b/spec/fixtures/used_keys/app/views/application/comments.html.erb new file mode 100644 index 00000000..b4fd86ce --- /dev/null +++ b/spec/fixtures/used_keys/app/views/application/comments.html.erb @@ -0,0 +1,37 @@ + +<%= Translate.ignore_html_comment %> + +<% # i18n-tasks-use t('ruby.comment.works') %> +<%= Translate.ruby_comment_works %> + +<%# i18n-tasks-use t('erb.comment.works') %> +<%= Translate.erb_comment_works %> + + +============================================= +============================================= +============================================= +============================================= + + +<%# Do not fail while parsing these: %> + +<%# this should not fail: ' %> + +<%# this is a multiline comment +it's totally fine +nothing should fail %> + +<% # https://github.com/glebm/i18n-tasks/issues/434 %> + + +<%# + +%> diff --git a/spec/fixtures/used_keys/app/views/application/show.html.erb b/spec/fixtures/used_keys/app/views/application/show.html.erb index b8b95fcd..edcb2aba 100644 --- a/spec/fixtures/used_keys/app/views/application/show.html.erb +++ b/spec/fixtures/used_keys/app/views/application/show.html.erb @@ -4,12 +4,11 @@ I18n.t("this_should_not")

<% # i18n-tasks-use t('activerecord.models.first.one') %> <%= First.model_name.human(count: 1) %> - - <%= NotARealComment.model_name.human %>

<%= t('with_parameter', parameter: "erb is the best") %> <%= t 'with_scope', scope: "scope_a.scope_b", default: t(".nested_call") %> + <% # https://github.com/glebm/i18n-tasks/issues/424 %> <%= link_to(edit_foo_path(foo), title: t(".edit")) do %> @@ -21,10 +20,4 @@ I18n.t("this_should_not") <%= render Blacklight::Document::CitationComponent.with_collection(@documents) if @documents.present? %> <% end %> - - <%# this should not fail: ' %> - - <%# this is a multiline comment - it's totally fine - nothing should fail %>

diff --git a/spec/used_keys_erb_spec.rb b/spec/used_keys_erb_spec.rb index 6a849c6d..4c97a53b 100644 --- a/spec/used_keys_erb_spec.rb +++ b/spec/used_keys_erb_spec.rb @@ -48,8 +48,8 @@ [ { path: 'app/views/application/show.html.erb', - pos: 318, - line_num: 11, line_pos: 5, + pos: 202, + line_num: 9, line_pos: 5, line: " <%= t('with_parameter', parameter: \"erb is the best\") %>", raw_key: 'with_parameter' } @@ -63,8 +63,8 @@ [ { path: 'app/views/application/show.html.erb', - pos: 377, - line_num: 12, line_pos: 5, + pos: 261, + line_num: 10, line_pos: 5, line: " <%= t 'with_scope', scope: \"scope_a.scope_b\", default: t(\".nested_call\") %>", raw_key: 'scope_a.scope_b.with_scope' } @@ -79,8 +79,8 @@ [ { path: 'app/views/application/show.html.erb', - pos: 429, - line_num: 12, line_pos: 57, + pos: 313, + line_num: 10, line_pos: 57, line: " <%= t 'with_scope', scope: \"scope_a.scope_b\", default: t(\".nested_call\") %>", raw_key: '.nested_call' } @@ -95,8 +95,8 @@ [ { path: 'app/views/application/show.html.erb', - pos: 548, - line_num: 14, line_pos: 41, + pos: 433, + line_num: 13, line_pos: 41, line: ' <%= link_to(edit_foo_path(foo), title: t(".edit")) do %>', raw_key: '.edit' } @@ -111,8 +111,8 @@ [ { path: 'app/views/application/show.html.erb', - pos: 770, - line_num: 20, line_pos: 25, + pos: 655, + line_num: 19, line_pos: 25, line: " <% component.title { t('blacklight.tools.citation') } %>", raw_key: 'blacklight.tools.citation' } @@ -136,4 +136,49 @@ ) ) end + + describe 'comments' do + let(:paths) { + %w[app/views/application/comments.html.erb] + } + + it '#used_keys' do + used_keys = task.used_tree + expect(used_keys.size).to eq(1) + leaves = used_keys.leaves.to_a + expect(leaves.size).to eq(2) + + expect_node_key_data( + leaves[0], + 'ruby.comment.works', + occurrences: make_occurrences( + [ + { + path: 'app/views/application/comments.html.erb', + pos: 90, + line_num: 4, line_pos: 2, + line: "<% # i18n-tasks-use t('ruby.comment.works') %>", + raw_key: 'ruby.comment.works' + } + ] + ) + ) + + expect_node_key_data( + leaves[1], + 'erb.comment.works', + occurrences: make_occurrences( + [ + { + path: 'app/views/application/comments.html.erb', + pos: 174, + line_num: 7, line_pos: 4, + line: "<%# i18n-tasks-use t('erb.comment.works') %>", + raw_key: 'erb.comment.works' + } + ] + ) + ) + end + end end