diff --git a/.rubocop.yml b/.rubocop.yml index 340703fbe..3ae91a0ce 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -2,7 +2,7 @@ inherit_gem: rubocop-shopify: rubocop.yml -require: +plugins: - rubocop-minitest - rubocop-performance - rubocop-rake diff --git a/Gemfile.lock b/Gemfile.lock index 0dfd3b1a7..f1f3cb1ca 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -32,7 +32,7 @@ GEM mutex_m tzinfo (~> 2.0) ansi (1.5.0) - ast (2.4.2) + ast (2.4.3) base64 (0.1.1) bigdecimal (3.1.4) builder (3.2.4) @@ -44,8 +44,10 @@ GEM ruby2_keywords i18n (1.14.1) concurrent-ruby (~> 1.0) - json (2.7.1) - language_server-protocol (3.17.0.3) + json (2.18.1) + language_server-protocol (3.17.0.5) + lint_roller (1.1.0) + logger (1.7.0) method_source (1.1.0) minitest (5.17.0) minitest-focus (1.3.1) @@ -62,12 +64,12 @@ GEM racc (~> 1.4) nokogiri (1.18.9-x86_64-linux-gnu) racc (~> 1.4) - parallel (1.24.0) - parser (3.3.0.5) + parallel (1.27.0) + parser (3.3.10.2) ast (~> 2.4.1) racc phonelib (0.8.7) - prettier_print (1.2.0) + prism (1.9.0) pry (0.14.2) coderay (~> 1.1) method_source (~> 1.0) @@ -81,47 +83,52 @@ GEM rake (13.0.6) rake-compiler (1.2.1) rake - regexp_parser (2.9.0) - rexml (3.2.8) - strscan (>= 3.0.9) - rubocop (1.62.1) + rbs (3.10.3) + logger + tsort + regexp_parser (2.11.3) + rubocop (1.84.2) json (~> 2.3) - language_server-protocol (>= 3.17.0) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.31.1, < 2.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.49.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.31.2) - parser (>= 3.3.0.4) - rubocop-minitest (0.27.0) - rubocop (>= 0.90, < 2.0) - rubocop-performance (1.16.0) - rubocop (>= 1.7.0, < 2.0) - rubocop-ast (>= 0.4.0) - rubocop-rake (0.6.0) - rubocop (~> 1.0) - rubocop-shopify (2.12.0) - rubocop (~> 1.44) - ruby-lsp (0.3.8) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.49.0) + parser (>= 3.3.7.2) + prism (~> 1.7) + rubocop-minitest (0.39.1) + lint_roller (~> 1.1) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.38.0, < 2.0) + rubocop-performance (1.26.1) + lint_roller (~> 1.1) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.47.1, < 2.0) + rubocop-rake (0.7.1) + lint_roller (~> 1.1) + rubocop (>= 1.72.1) + rubocop-shopify (2.18.0) + rubocop (~> 1.62) + ruby-lsp (0.26.7) language_server-protocol (~> 3.17.0) - sorbet-runtime - syntax_tree (>= 5.0.0, < 6) + prism (>= 1.2, < 2.0) + rbs (>= 3, < 5) ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) rubyzip (2.3.2) - sorbet-runtime (0.5.10648) stringio (3.1.0) - strscan (3.1.0) - syntax_tree (5.3.0) - prettier_print (>= 1.2.0) thor (1.2.1) + tsort (0.2.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicode-display_width (2.5.0) + unicode-display_width (3.2.0) + unicode-emoji (~> 4.1) + unicode-emoji (4.2.0) PLATFORMS arm64-darwin-21 diff --git a/lib/worldwide/address.rb b/lib/worldwide/address.rb index b20002138..27421bebd 100644 --- a/lib/worldwide/address.rb +++ b/lib/worldwide/address.rb @@ -290,7 +290,7 @@ def build_address_format_array(additional_lines:, excluded_fields:) result << line unless blank?(line.join) end - result + additional_lines.map { |x| [x] } + result + additional_lines.zip end # Returns a hash containing the values for each address field @@ -348,7 +348,7 @@ def fill_in_fields(fields:, address_data:) def japan_with_non_japanese_script? text = build_formatted_address_data.values.join - country_code == "JP" && Worldwide::Scripts.identify(text: text).intersection(JAPANESE_SCRIPTS).empty? + country_code == "JP" && !Worldwide::Scripts.identify(text: text).intersect?(JAPANESE_SCRIPTS) end def normalize_city @@ -457,7 +457,7 @@ def strip_extra_chars(lines:, excluded_fields:) # - `〒` ("yuubin" mark) is a prefix that's prepended to the postal code (zip) # If the associated field is excluded/empty, we need to suppress the associated special character. def strip_extra_japanese_chars(line:, excluded_fields:) - return nil if line.nil? + return if line.nil? line.map do |field| stripped = field diff --git a/lib/worldwide/address_validator.rb b/lib/worldwide/address_validator.rb index 7ac16699a..c9dcd801e 100644 --- a/lib/worldwide/address_validator.rb +++ b/lib/worldwide/address_validator.rb @@ -9,6 +9,7 @@ class AddressValidator class << self extend Forwardable + def_delegators :instance, :errors, :valid? end diff --git a/lib/worldwide/cldr/date_format_pattern.rb b/lib/worldwide/cldr/date_format_pattern.rb index 47213fe76..aed3d9914 100644 --- a/lib/worldwide/cldr/date_format_pattern.rb +++ b/lib/worldwide/cldr/date_format_pattern.rb @@ -50,28 +50,28 @@ def tokenize(format) UNQUOTED_LITERAL = /[^a-zA-Z']+/ def parse_field(format) - return nil unless format.start_with?(PATTERN_FIELD) + return unless format.start_with?(PATTERN_FIELD) match = PATTERN_FIELD.match(format) [Field.from(match[0]), match.end(0)] end def parse_single_quote(format) - return nil unless format.start_with?(SINGLE_QUOTE_LITERAL) + return unless format.start_with?(SINGLE_QUOTE_LITERAL) match = SINGLE_QUOTE_LITERAL.match(format) [Literal.new("'"), match.end(0)] end def parse_quoted_literal(format) - return nil unless format.start_with?(QUOTED_LITERAL) + return unless format.start_with?(QUOTED_LITERAL) match = QUOTED_LITERAL.match(format) [Literal.new(match[1].gsub(SINGLE_QUOTE_LITERAL, "'")), match.end(0)] end def parse_unquoted_literal(format) - return nil unless format.start_with?(UNQUOTED_LITERAL) + return unless format.start_with?(UNQUOTED_LITERAL) match = UNQUOTED_LITERAL.match(format) [Literal.new(match[0]), match.end(0)] diff --git a/lib/worldwide/cldr/fallbacks.rb b/lib/worldwide/cldr/fallbacks.rb index dbcecf435..69a7010ac 100644 --- a/lib/worldwide/cldr/fallbacks.rb +++ b/lib/worldwide/cldr/fallbacks.rb @@ -38,7 +38,7 @@ def ancestry(locale) loop do if cldr_defined_parents[ancestors.last] ancestors << cldr_defined_parents[ancestors.last] - elsif I18n::Locale::Tag.tag(ancestors.last).parents.count > 0 + elsif I18n::Locale::Tag.tag(ancestors.last).parents.any? ancestors << I18n::Locale::Tag.tag(ancestors.last).parents.first.to_sym else break diff --git a/lib/worldwide/config.rb b/lib/worldwide/config.rb index 83c00f631..243fda379 100644 --- a/lib/worldwide/config.rb +++ b/lib/worldwide/config.rb @@ -70,7 +70,7 @@ def i18n_defined?(i18n_config, key) # we don't want to trigger the backend resolution until after we've determined whether they have set it explicitly. class_variable = "@@#{key}".to_sym instance_variable = "@#{key}".to_sym - i18n_config.class.class_variables.include?(class_variable) || i18n_config.instance_variables.include?(instance_variable) + i18n_config.class.class_variable_defined?(class_variable) || i18n_config.instance_variables.include?(instance_variable) else i18n_config.key?(key) end diff --git a/lib/worldwide/currency.rb b/lib/worldwide/currency.rb index ad46d81d9..50a6cbe2e 100644 --- a/lib/worldwide/currency.rb +++ b/lib/worldwide/currency.rb @@ -117,7 +117,7 @@ def symbol(locale: I18n.locale) raw_symbol = Worldwide::Cldr.t("currencies.#{@currency_code}.narrow_symbol", default: nil, locale: locale) || Worldwide::Cldr.t("currencies.#{@currency_code}.symbol", default: nil, locale: locale) - return nil if raw_symbol.nil? + return if raw_symbol.nil? # For some locales (e.g., HK), in-market folks have requested that we leave the CLDR behaviour untouched exceptional_symbol = EXCEPTIONS.fetch(@currency_code.to_sym, nil) @@ -154,7 +154,7 @@ def name private def combine(amount:, decimal_places:, humanize:, locale:, symbol:) - space = if has_space(locale) + space = if has_space?(locale) # This is U+00A0, the Unicode non-breaking space character [160].pack("U*") else @@ -237,7 +237,7 @@ def has_minor_symbol? end # Returns true if there should be a space between the amount and the currency symbol - def has_space(locale) + def has_space?(locale) pattern = Worldwide::Cldr.t("numbers.latn.formats.currency.patterns.default.standard", locale: locale) # Note that CLDR uses these characters in its currency formats: @@ -250,7 +250,7 @@ def has_space(locale) def minor_symbol key = @currency_code - return nil unless Currency.minor_symbols.key?(key) + return unless Currency.minor_symbols.key?(key) Currency.minor_symbols[key]["symbol"] end diff --git a/lib/worldwide/extant_outcodes.rb b/lib/worldwide/extant_outcodes.rb index 274d255f1..38dbf28d6 100644 --- a/lib/worldwide/extant_outcodes.rb +++ b/lib/worldwide/extant_outcodes.rb @@ -10,6 +10,7 @@ class ExtantOutcodes class << self extend Forwardable + def_delegators :instance, :for_country end diff --git a/lib/worldwide/fields.rb b/lib/worldwide/fields.rb index 857af5eb0..f30c0db78 100644 --- a/lib/worldwide/fields.rb +++ b/lib/worldwide/fields.rb @@ -12,6 +12,7 @@ class Fields class << self extend Forwardable + def_delegators :instance, :field end diff --git a/lib/worldwide/lists.rb b/lib/worldwide/lists.rb index 22b87ec68..e72a80523 100644 --- a/lib/worldwide/lists.rb +++ b/lib/worldwide/lists.rb @@ -3,6 +3,7 @@ module Worldwide module Lists extend self + # We assume that the data is expected to returned in the same # order as it is received. We are aware of one counter example, # Urdu, that we do not support. diff --git a/lib/worldwide/locale.rb b/lib/worldwide/locale.rb index 4679e9c54..7838187ed 100644 --- a/lib/worldwide/locale.rb +++ b/lib/worldwide/locale.rb @@ -71,7 +71,7 @@ def name(locale: I18n.locale, context: :middle_of_sentence, throw: true) if @name_cache[context].is_a?(I18n::MissingTranslation) raise @name_cache[context] if throw - return nil + return end @name_cache[context] @@ -93,7 +93,7 @@ def endonym(context: :middle_of_sentence, throw: true) if @endonym.is_a?(I18n::MissingTranslation) raise @endonym if throw - return nil + return end @endonym @@ -113,7 +113,7 @@ def exonym(target_locale:, context:) result = lookup(language, locale: target_locale) if result transformed = Worldwide::Cldr::ContextTransforms.transform(result, :languages, context, locale: target_locale) - break "#{transformed}#{i > 0 ? territories_suffix(code.to_s) : ""}" + break "#{transformed}#{territories_suffix(code.to_s) if i > 0}" end end end diff --git a/lib/worldwide/region.rb b/lib/worldwide/region.rb index 3eaedf806..8b3faa715 100644 --- a/lib/worldwide/region.rb +++ b/lib/worldwide/region.rb @@ -375,7 +375,7 @@ def deprecated? # An Worldwide::Field that can be used to ask about the field, including # labels, error messages, and an autofill value if there is one. def field(key:) - return nil unless country? + return unless country? Worldwide::Fields.field(country_code: iso_code, field_key: key) end @@ -479,7 +479,7 @@ def zip_required? # # @return [String, nil] One of "ALPHANUMERIC", "NUMERIC", "NUMERIC_AND_PUNCTUATION", or nil if no zip_example def zip_type - return nil if zip_example.nil? + return if zip_example.nil? if zip_example.match?(/[A-Za-z]/) FORMAT_TYPES[:ALPHANUMERIC] @@ -554,7 +554,7 @@ def additional_field_required?(field_name) field ? !!field["required"] : false end - def answers_to_cldr_code(search_code) + def answers_to_cldr_code?(search_code) return false if Util.blank?(search_code) || Util.blank?(cldr_code) return true if search_code.casecmp(cldr_code).zero? @@ -562,7 +562,7 @@ def answers_to_cldr_code(search_code) "#{pc&.cldr_code&.downcase}#{cldr_code.downcase}" == search_code.downcase end - def answers_to_iso_code(search_code) + def answers_to_iso_code?(search_code) return true if search_code == iso_code pc = parent_country @@ -616,9 +616,9 @@ def passes_country_zip_regexp?(value:, partial_match: false) # # Returns the Region in which the zip belongs based on the prefix, or `nil` if no match is found. def search_prefixes_by_normalized_zip(prefixes:, zip:, allow_partial_zip: false) - return nil if Worldwide::Util.blank?(prefixes) - return nil if Worldwide::Util.blank?(zip) - return nil unless allow_partial_zip || passes_country_zip_regexp?(value: zip) + return if Worldwide::Util.blank?(prefixes) + return if Worldwide::Util.blank?(zip) + return unless allow_partial_zip || passes_country_zip_regexp?(value: zip) stripped = Zip.strip_optional_country_prefix(country_code: iso_code, zip: zip) diff --git a/lib/worldwide/regions.rb b/lib/worldwide/regions.rb index 0706849d3..119e59e07 100644 --- a/lib/worldwide/regions.rb +++ b/lib/worldwide/regions.rb @@ -12,6 +12,7 @@ class Regions class << self extend Forwardable + def_delegators :instance, :all, :region_by_cldr_code, :region end diff --git a/lib/worldwide/regions_loader.rb b/lib/worldwide/regions_loader.rb index 4f4c01e47..f67c4d108 100644 --- a/lib/worldwide/regions_loader.rb +++ b/lib/worldwide/regions_loader.rb @@ -225,8 +225,6 @@ def load_territory(filename) spec = YAML.safe_load_file(filename) code = spec["code"] - loaded_regions = [] - region = Region.new( alpha_three: country_codes.dig(code, "alpha3"), continent: false, diff --git a/lib/worldwide/zip.rb b/lib/worldwide/zip.rb index 801047da4..dbb76a375 100644 --- a/lib/worldwide/zip.rb +++ b/lib/worldwide/zip.rb @@ -50,7 +50,7 @@ def gb_style?(country_code:) # @param min_confidence [Integer] The minimum confidence level (between 0-100) that is accepted from a suggestion (optional) # @return [Region] which is a "country" if we have a suggestion, or `nil` if we do not. def find_country(country_code: nil, zip:, min_confidence: 0) - return nil unless Util.present?(zip) + return unless Util.present?(zip) country = Worldwide.region(code: country_code) unless country_code.nil? return country if country&.valid_zip?(zip) @@ -62,7 +62,7 @@ def find_country(country_code: nil, zip:, min_confidence: 0) return suggestion unless suggestion.nil? || confidence.nil? || confidence < min_confidence # If our postal code is wholly numeric, we can't make an intelligent suggestion without an alleged country. - return nil unless adjusted_zip.match?(/[A-Z]/) + return unless adjusted_zip.match?(/[A-Z]/) # Try a broader-ranging match without considering the alleged country # We'll see if we have only a single suggestion and, if so, return it. @@ -95,7 +95,7 @@ def normalize(country_code:, zip:, allow_autofill: true, strip_extraneous_charac return autofill if Util.present?(autofill) end - return nil if zip.nil? + return if zip.nil? # Convert to uppercase # Convert numeric and romaji full-width to half-width diff --git a/rake/cldr/cleaner.rb b/rake/cldr/cleaner.rb index 4ac56b7c7..b942fba54 100644 --- a/rake/cldr/cleaner.rb +++ b/rake/cldr/cleaner.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require "fileutils" require "worldwide/paths" diff --git a/rake/cldr/flatten_hash.rb b/rake/cldr/flatten_hash.rb index 56d263949..2fdf85ca6 100644 --- a/rake/cldr/flatten_hash.rb +++ b/rake/cldr/flatten_hash.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true module FlattenHash - NotHashError = Class.new(StandardError) + class NotHashError < StandardError + end class << self def run(hash, output = {}, parent_key = []) diff --git a/rake/cldr/locale_generator.rb b/rake/cldr/locale_generator.rb index b1746a14b..744f5b80b 100644 --- a/rake/cldr/locale_generator.rb +++ b/rake/cldr/locale_generator.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require "fileutils" require "worldwide" @@ -1001,7 +1001,7 @@ def ordinal_pluralization_keys # END OF AUTO-GENERATED CONTENT CONTENTS - contents = contents.split("\n").map { |line| "#{line.strip.empty? ? "" : indentation_of_starting_line}#{line}" }.join("\n") + contents = contents.split("\n").map { |line| "#{indentation_of_starting_line unless line.strip.empty?}#{line}" }.join("\n") new_file_contents = existing_file_contents[0...start_of_auto_generated_content.begin(0)] + contents + existing_file_contents[end_of_auto_generated_content.end(0)..] diff --git a/rake/cldr/patch.rb b/rake/cldr/patch.rb index 9ce5dcc0a..34c6d61b5 100644 --- a/rake/cldr/patch.rb +++ b/rake/cldr/patch.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require "i18n" require "parser/current" @@ -1357,7 +1357,7 @@ def patch_file(locale, file_name, key_path, existing_value, value, **options) # patch_yaml_file(file_path, [locale, *key_path], existing_value, value, **options) end - def patch_units_file(file_path, paths_to_keep) + def patch_units_file(file_path, paths_to_keep) # rubocop:disable Naming/PredicateMethod return false unless File.exist?(file_path) source_content = File.read(file_path) diff --git a/rake/cldr/puller.rb b/rake/cldr/puller.rb index 1653f4cb2..8ac1bf281 100644 --- a/rake/cldr/puller.rb +++ b/rake/cldr/puller.rb @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require "cldr/download" require "cldr/draft_status" diff --git a/rake/cldr/sort_yaml.rb b/rake/cldr/sort_yaml.rb index f72b791c6..834b0705c 100644 --- a/rake/cldr/sort_yaml.rb +++ b/rake/cldr/sort_yaml.rb @@ -13,7 +13,7 @@ def sort(data) UnflattenHash.run(sorted) end - def sort_file(filename, output_filename: nil) + def sort_file(filename, output_filename: nil) # rubocop:disable Naming/PredicateMethod output_filename ||= begin extension = File.extname(filename) File.join(File.dirname(filename), "#{File.basename(filename, extension)}_sorted#{extension}") diff --git a/rake/cldr/unflatten_hash.rb b/rake/cldr/unflatten_hash.rb index 98944f591..17330e9bb 100644 --- a/rake/cldr/unflatten_hash.rb +++ b/rake/cldr/unflatten_hash.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true module UnflattenHash - NotHashError = Class.new(StandardError) + class NotHashError < StandardError + end class << self def run(hash) diff --git a/rake/tasks/cldr.rake b/rake/tasks/cldr.rake index f1b7f0c94..c98df5e55 100644 --- a/rake/tasks/cldr.rake +++ b/rake/tasks/cldr.rake @@ -1,4 +1,4 @@ -# frozen_string_literal: false +# frozen_string_literal: true require "worldwide/util" diff --git a/test/worldwide/currencies_test.rb b/test/worldwide/currencies_test.rb index 47a41fc67..e35c369ee 100644 --- a/test/worldwide/currencies_test.rb +++ b/test/worldwide/currencies_test.rb @@ -10,13 +10,13 @@ class CurrenciesTest < ActiveSupport::TestCase refute_empty currencies currencies.each do |currency| - assert currency.is_a?(Worldwide::Currency) + assert_kind_of Worldwide::Currency, currency end end test ".each should allow currencies to be enumerable" do Worldwide::Currencies.each do |currency| - assert currency.is_a?(Worldwide::Currency) + assert_kind_of Worldwide::Currency, currency end end diff --git a/test/worldwide/field_data_consistency_test.rb b/test/worldwide/field_data_consistency_test.rb index cf06041ec..4d7242f31 100644 --- a/test/worldwide/field_data_consistency_test.rb +++ b/test/worldwide/field_data_consistency_test.rb @@ -43,7 +43,7 @@ class FieldDataConsistencyTest < ActiveSupport::TestCase assert( differ_only_in_contents_of_parens(value, optional_labels[optional_key]) || - differ_only_in_optionality(value, optional_labels[optional_key]), + differ_only_in_optionality?(value, optional_labels[optional_key]), "Expected that the label for `#{key[-3]}` and its optional version in `#{file_path}` would only differ by the contents of the parentheses. Instead found:\n\t default: #{value}\n\toptional: #{optional_labels[optional_key]}", ) end @@ -77,7 +77,7 @@ def differ_only_in_contents_of_parens(default, optional) # For one label, our Korean translator has opted for a phrasing that already has paretheses in the core text. # This means that the (optional) phrasing shares the same parentheses, after a comma. # In order to avoid failing the test on that label, we need to explicitly search for ", optional" in Korean. - def differ_only_in_optionality(default, optional) + def differ_only_in_optionality?(default, optional) default == optional.gsub(/, 선택 사항/, "") end diff --git a/test/worldwide/region_data_consistency_test.rb b/test/worldwide/region_data_consistency_test.rb index 2422543c9..30e6453df 100644 --- a/test/worldwide/region_data_consistency_test.rb +++ b/test/worldwide/region_data_consistency_test.rb @@ -173,7 +173,7 @@ class RegionDataConsistencyTest < ActiveSupport::TestCase Regions.all.select(&:country?).each do |country| country_tags = country.tags&.to_set next if country_tags.nil? - next if eu_tags.intersection(country_tags).empty? + next unless eu_tags.intersect?(country_tags) assert_includes eu.zones.map(&:iso_code), country.iso_code end