From 1b7081882cfcc3a283877cac43b4df617ea6bad2 Mon Sep 17 00:00:00 2001 From: David Wessman Date: Sat, 9 Apr 2022 14:22:51 +0200 Subject: [PATCH] Allows configure ast_matchers with classes --- lib/i18n/tasks.rb | 11 +++++++++++ .../tasks/scanners/ast_matchers/base_matcher.rb | 4 ++++ lib/i18n/tasks/scanners/ruby_ast_scanner.rb | 7 ++++--- lib/i18n/tasks/used_keys.rb | 2 +- spec/used_keys_erb_spec.rb | 13 +++++++++---- spec/used_keys_ruby_spec.rb | 13 +++++++++---- templates/config/i18n-tasks.yml | 5 +++-- 7 files changed, 41 insertions(+), 14 deletions(-) diff --git a/lib/i18n/tasks.rb b/lib/i18n/tasks.rb index 5d0d31cc..f7af80ca 100644 --- a/lib/i18n/tasks.rb +++ b/lib/i18n/tasks.rb @@ -34,6 +34,17 @@ def add_commands(commands_module) ::I18n::Tasks::Commands.send :include, commands_module self end + + # Add AST-matcher to i18n-tasks + # + # @param matcher_class_name + # @return self + def add_ast_matcher(matcher_class_name) + matchers = I18n::Tasks::Configuration::DEFAULTS[:search][:ast_matchers] + matchers << matcher_class_name + matchers.uniq! + self + end end @verbose = !ENV['VERBOSE'].nil? diff --git a/lib/i18n/tasks/scanners/ast_matchers/base_matcher.rb b/lib/i18n/tasks/scanners/ast_matchers/base_matcher.rb index f8513260..29fd7d76 100644 --- a/lib/i18n/tasks/scanners/ast_matchers/base_matcher.rb +++ b/lib/i18n/tasks/scanners/ast_matchers/base_matcher.rb @@ -6,6 +6,10 @@ def initialize(scanner:) @scanner = scanner end + def convert_to_key_occurrences(send_node, method_name, location: send_node.loc) + raise("Not implemented") + end + protected # If the node type is of `%i(sym str int false true)`, return the value as a string. diff --git a/lib/i18n/tasks/scanners/ruby_ast_scanner.rb b/lib/i18n/tasks/scanners/ruby_ast_scanner.rb index 853218bd..2daab4c8 100644 --- a/lib/i18n/tasks/scanners/ruby_ast_scanner.rb +++ b/lib/i18n/tasks/scanners/ruby_ast_scanner.rb @@ -4,7 +4,6 @@ require 'i18n/tasks/scanners/relative_keys' require 'i18n/tasks/scanners/ruby_ast_call_finder' require 'i18n/tasks/scanners/ast_matchers/message_receivers_matcher' -require 'i18n/tasks/scanners/ast_matchers/rails_model_matcher' require 'parser/current' module I18n::Tasks::Scanners @@ -133,9 +132,11 @@ def setup_matchers scanner: self ) end - if Array(config[:extra_matchers]).include?('rails_model') - matchers << AstMatchers::RailsModelMatcher.new(scanner: self) + + Array(config[:ast_matchers]).each do |class_name| + matchers << ActiveSupport::Inflector.constantize(class_name).new(scanner: self) end + matchers end end diff --git a/lib/i18n/tasks/used_keys.rb b/lib/i18n/tasks/used_keys.rb index af0cf8e7..44efa4b7 100644 --- a/lib/i18n/tasks/used_keys.rb +++ b/lib/i18n/tasks/used_keys.rb @@ -24,7 +24,7 @@ module UsedKeys # rubocop:disable Metrics/ModuleLength ['::I18n::Tasks::Scanners::ErbAstScanner', { only: %w[*.erb] }], ['::I18n::Tasks::Scanners::PatternWithScopeScanner', { exclude: %w[*.erb *.rb] }] ], - extra_matchers: [], + ast_matchers: [], strict: true }.freeze diff --git a/spec/used_keys_erb_spec.rb b/spec/used_keys_erb_spec.rb index 94fb435c..9d2eb26c 100644 --- a/spec/used_keys_erb_spec.rb +++ b/spec/used_keys_erb_spec.rb @@ -1,11 +1,16 @@ # frozen_string_literal: true require 'spec_helper' +require 'i18n/tasks/scanners/ast_matchers/rails_model_matcher' RSpec.describe 'UsedKeysErb' do let!(:task) { I18n::Tasks::BaseTask.new } around do |ex| - task.config[:search] = { paths: paths, extra_matchers: extra_matchers } + I18n::Tasks::Configuration::DEFAULTS[:search][:ast_matchers].clear + ast_matchers.each do |matcher| + I18n::Tasks.add_ast_matcher(matcher) + end + task.config[:search] = { paths: paths } TestCodebase.in_test_app_dir(directory: 'spec/fixtures/used_keys') { ex.run } end @@ -13,8 +18,8 @@ %w[app/views/application/show.html.erb] } - let(:extra_matchers) { - %w[rails_model] + let(:ast_matchers) { + %w[I18n::Tasks::Scanners::AstMatchers::RailsModelMatcher] } it '#used_keys' do @@ -319,7 +324,7 @@ end describe 'without rails_model matcher' do - let(:extra_matchers) { [] } + let(:ast_matchers) { [] } it '#used_keys' do used_keys = task.used_tree diff --git a/spec/used_keys_ruby_spec.rb b/spec/used_keys_ruby_spec.rb index 12ee8066..6c02c435 100644 --- a/spec/used_keys_ruby_spec.rb +++ b/spec/used_keys_ruby_spec.rb @@ -1,11 +1,16 @@ # frozen_string_literal: true require 'spec_helper' +require 'i18n/tasks/scanners/ast_matchers/rails_model_matcher' RSpec.describe 'UsedKeysRuby' do let!(:task) { I18n::Tasks::BaseTask.new } around do |ex| - task.config[:search] = { paths: paths, extra_matchers: extra_matchers }.compact + I18n::Tasks::Configuration::DEFAULTS[:search][:ast_matchers].clear + ast_matchers.each do |matcher| + I18n::Tasks.add_ast_matcher(matcher) + end + task.config[:search] = {paths: paths}.compact TestCodebase.in_test_app_dir(directory: 'spec/fixtures/used_keys') { ex.run } end @@ -13,8 +18,8 @@ %w[a.rb] } - let(:extra_matchers) { - %w[rails_model] + let(:ast_matchers) { + %w[I18n::Tasks::Scanners::AstMatchers::RailsModelMatcher] } it '#used_keys - ruby' do @@ -104,7 +109,7 @@ end describe 'without rails_model matcher' do - let(:extra_matchers) { [] } + let(:ast_matchers) { [] } it '#used_keys - ruby' do used_keys = task.used_tree diff --git a/templates/config/i18n-tasks.yml b/templates/config/i18n-tasks.yml index f564fc7f..8198bb6d 100644 --- a/templates/config/i18n-tasks.yml +++ b/templates/config/i18n-tasks.yml @@ -85,13 +85,14 @@ search: ## If `strict` is `false`, guess usages such as t("categories.#{category}.title"). The default is `true`. # strict: true - ## Allows adding extra matchers for finding translations using the AST-scanners + ## Allows adding ast_matchers for finding translations using the AST-scanners ## The available matchers are: ## - RailsModelMatcher ## Matches ActiveRecord translations like ## User.human_attribute_name(:email) and User.model_name.human ## - # extra_matchers: ['rails_model'] + ## To implement your own, please see `I18n::Tasks::Scanners::AstMatchers::BaseMatcher`. + <%# I18n::Tasks.add_ast_matcher('I18n::Tasks::Scanners::AstMatchers::RailsModelMatcher') %> ## Multiple scanners can be used. Their results are merged. ## The options specified above are passed down to each scanner. Per-scanner options can be specified as well.