Merge pull request #5240 from MikeMcQuaid/rubocop-bump

RuboCop 0.60.0
This commit is contained in:
Mike McQuaid 2018-11-04 11:48:51 +00:00 committed by GitHub
commit bada451a81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
328 changed files with 11438 additions and 604 deletions

4
.gitignore vendored
View File

@ -36,10 +36,8 @@
**/vendor/bundle-standalone/ruby/*/gems/activesupport-*/lib
**/vendor/bundle-standalone/ruby/*/gems/concurrent-ruby-*/lib
**/vendor/bundle-standalone/ruby/*/gems/backports-*/lib
**/vendor/bundle-standalone/ruby/*/gems/i18n-*/lib
**/vendor/bundle-standalone/ruby/*/gems/minitest-*/lib
**/vendor/bundle-standalone/ruby/*/gems/thread_safe-*/lib
**/vendor/bundle-standalone/ruby/*/gems/tzinfo-*/lib
# Ignore rubocop dependencies we don't wish to vendor
**/vendor/bundle-standalone/ruby/*/gems/ast-*/
@ -48,7 +46,7 @@
**/vendor/bundle-standalone/ruby/*/gems/parser-*/
**/vendor/bundle-standalone/ruby/*/gems/powerpack-*/
**/vendor/bundle-standalone/ruby/*/gems/rainbow-*/
**/vendor/bundle-standalone/ruby/*/gems/rubocop-*/
**/vendor/bundle-standalone/ruby/*/gems/rubocop-0*/
**/vendor/bundle-standalone/ruby/*/gems/ruby-progressbar-*/
**/vendor/bundle-standalone/ruby/*/gems/unicode-display_width-*/

View File

@ -19,6 +19,11 @@ FormulaAuditStrict:
NewFormulaAudit:
Enabled: false
# make our hashes consistent
Layout/AlignHash:
EnforcedHashRocketStyle: table
EnforcedColonStyle: table
# `system` is a special case and aligns on second argument
Layout/AlignParameters:
Enabled: false

View File

@ -8,9 +8,9 @@ module Cask
"/" => :slashes,
}.freeze
DIVIDER_REGEX = /(#{DIVIDERS.keys.map { |v| Regexp.quote(v) }.join('|')})/
DIVIDER_REGEX = /(#{DIVIDERS.keys.map { |v| Regexp.quote(v) }.join('|')})/.freeze
MAJOR_MINOR_PATCH_REGEX = /^(\d+)(?:\.(\d+)(?:\.(\d+))?)?/
MAJOR_MINOR_PATCH_REGEX = /^(\d+)(?:\.(\d+)(?:\.(\d+))?)?/.freeze
class << self
private

View File

@ -1,7 +1,7 @@
# @private
module CompilerConstants
GNU_GCC_VERSIONS = %w[4.4 4.5 4.6 4.7 4.8 4.9 5 6 7 8].freeze
GNU_GCC_REGEXP = /^gcc-(4\.[4-9]|[5-8])$/
GNU_GCC_REGEXP = /^gcc-(4\.[4-9]|[5-8])$/.freeze
COMPILER_SYMBOL_MAP = {
"gcc" => :gcc,
"gcc-4.0" => :gcc_4_0,

View File

@ -1,5 +1,5 @@
# frozen_string_literal: true
# RuboCop version used for `brew style` and `brew cask style`
HOMEBREW_RUBOCOP_VERSION = "0.59.1"
HOMEBREW_RUBOCOP_CASK_VERSION = "~> 0.22.0" # has to be updated when RuboCop version changes
HOMEBREW_RUBOCOP_VERSION = "0.60.0"
HOMEBREW_RUBOCOP_CASK_VERSION = "~> 0.23.0" # has to be updated when RuboCop version changes

View File

@ -111,7 +111,7 @@ class Keg
# Matches framework references like `XXX.framework/Versions/YYY/XXX` and
# `XXX.framework/XXX`, both with or without a slash-delimited prefix.
FRAMEWORK_RX = %r{(?:^|/)(([^/]+)\.framework/(?:Versions/[^/]+/)?\2)$}
FRAMEWORK_RX = %r{(?:^|/)(([^/]+)\.framework/(?:Versions/[^/]+/)?\2)$}.freeze
def find_dylib_suffix_from(bad_name)
if (framework = bad_name.match(FRAMEWORK_RX))

View File

@ -70,7 +70,7 @@ class Pathname
include DiskUsageExtension
# @private
BOTTLE_EXTNAME_RX = /(\.[a-z0-9_]+\.bottle\.(\d+\.)?tar\.gz)$/
BOTTLE_EXTNAME_RX = /(\.[a-z0-9_]+\.bottle\.(\d+\.)?tar\.gz)$/.freeze
# Moves a file from the original location to the {Pathname}'s.
def install(*sources)

View File

@ -327,7 +327,7 @@ class Formula
active_spec == head
end
delegate [
delegate [ # rubocop:disable Layout/AlignHash
:bottle_unneeded?,
:bottle_disabled?,
:bottle_disable_reason,
@ -1615,10 +1615,20 @@ class Formula
"bottle" => {},
"keg_only" => keg_only?,
"options" => [],
"build_dependencies" => dependencies.select(&:build?).map(&:name).uniq,
"dependencies" => dependencies.reject(&:optional?).reject(&:recommended?).reject(&:build?).map(&:name).uniq,
"recommended_dependencies" => dependencies.select(&:recommended?).map(&:name).uniq,
"optional_dependencies" => dependencies.select(&:optional?).map(&:name).uniq,
"build_dependencies" => dependencies.select(&:build?)
.map(&:name)
.uniq,
"dependencies" => dependencies.reject(&:optional?)
.reject(&:recommended?)
.reject(&:build?)
.map(&:name)
.uniq,
"recommended_dependencies" => dependencies.select(&:recommended?)
.map(&:name)
.uniq,
"optional_dependencies" => dependencies.select(&:optional?)
.map(&:name)
.uniq,
"requirements" => [],
"conflicts_with" => conflicts.map(&:name),
"caveats" => caveats,
@ -1641,9 +1651,10 @@ class Formula
}
bottle_info["files"] = {}
bottle_spec.collector.keys.each do |os|
bottle_url = "#{bottle_spec.root_url}/#{Bottle::Filename.create(self, os, bottle_spec.rebuild).bintray}"
checksum = bottle_spec.collector[os]
bottle_info["files"][os] = {
"url" => "#{bottle_spec.root_url}/#{Bottle::Filename.create(self, os, bottle_spec.rebuild).bintray}",
"url" => bottle_url,
checksum.hash_type.to_s => checksum.hexdigest,
}
end

View File

@ -104,8 +104,10 @@ module Homebrew
end
end
HOMEBREW_PULL_API_REGEX = %r{https://api\.github\.com/repos/([\w-]+)/([\w-]+)?/pulls/(\d+)}
HOMEBREW_PULL_OR_COMMIT_URL_REGEX = %r[https://github\.com/([\w-]+)/([\w-]+)?/(?:pull/(\d+)|commit/[0-9a-fA-F]{4,40})]
HOMEBREW_PULL_API_REGEX =
%r{https://api\.github\.com/repos/([\w-]+)/([\w-]+)?/pulls/(\d+)}.freeze
HOMEBREW_PULL_OR_COMMIT_URL_REGEX =
%r[https://github\.com/([\w-]+)/([\w-]+)?/(?:pull/(\d+)|commit/[0-9a-fA-F]{4,40})].freeze
require "forwardable"
require "PATH"

View File

@ -63,8 +63,8 @@ class Keg
end
# locale-specific directories have the form language[_territory][.codeset][@modifier]
LOCALEDIR_RX = %r{(locale|man)/([a-z]{2}|C|POSIX)(_[A-Z]{2})?(\.[a-zA-Z\-0-9]+(@.+)?)?}
INFOFILE_RX = %r{info/([^.].*?\.info|dir)$}
LOCALEDIR_RX = %r{(locale|man)/([a-z]{2}|C|POSIX)(_[A-Z]{2})?(\.[a-zA-Z\-0-9]+(@.+)?)?}.freeze
INFOFILE_RX = %r{info/([^.].*?\.info|dir)$}.freeze
KEG_LINK_DIRECTORIES = %w[
bin etc include lib sbin share var
].freeze

View File

@ -2,11 +2,11 @@ class Locale
class ParserError < StandardError
end
LANGUAGE_REGEX = /(?:[a-z]{2,3})/ # ISO 639-1 or ISO 639-2
REGION_REGEX = /(?:[A-Z]{2}|\d{3})/ # ISO 3166-1 or UN M.49
SCRIPT_REGEX = /(?:[A-Z][a-z]{3})/ # ISO 15924
LANGUAGE_REGEX = /(?:[a-z]{2,3})/.freeze # ISO 639-1 or ISO 639-2
REGION_REGEX = /(?:[A-Z]{2}|\d{3})/.freeze # ISO 3166-1 or UN M.49
SCRIPT_REGEX = /(?:[A-Z][a-z]{3})/.freeze # ISO 15924
LOCALE_REGEX = /\A((?:#{LANGUAGE_REGEX}|#{REGION_REGEX}|#{SCRIPT_REGEX})(?:\-|$)){1,3}\Z/
LOCALE_REGEX = /\A((?:#{LANGUAGE_REGEX}|#{REGION_REGEX}|#{SCRIPT_REGEX})(?:\-|$)){1,3}\Z/.freeze
def self.parse(string)
string = string.to_s

View File

@ -3,7 +3,7 @@ require "version"
class PkgVersion
include Comparable
RX = /\A(.+?)(?:_(\d+))?\z/
RX = /\A(.+?)(?:_(\d+))?\z/.freeze
attr_reader :version, :revision

View File

@ -1,10 +1,10 @@
# match taps' formulae, e.g. someuser/sometap/someformula
HOMEBREW_TAP_FORMULA_REGEX = %r{^([\w-]+)/([\w-]+)/([\w+-.@]+)$}
HOMEBREW_TAP_FORMULA_REGEX = %r{^([\w-]+)/([\w-]+)/([\w+-.@]+)$}.freeze
# match taps' casks, e.g. someuser/sometap/somecask
HOMEBREW_TAP_CASK_REGEX = %r{^([\w-]+)/([\w-]+)/([a-z0-9\-]+)$}
HOMEBREW_TAP_CASK_REGEX = %r{^([\w-]+)/([\w-]+)/([a-z0-9\-]+)$}.freeze
# match taps' directory paths, e.g. HOMEBREW_LIBRARY/Taps/someuser/sometap
HOMEBREW_TAP_DIR_REGEX = %r{#{Regexp.escape(HOMEBREW_LIBRARY)}/Taps/(?<user>[\w-]+)/(?<repo>[\w-]+)}
HOMEBREW_TAP_DIR_REGEX = %r{#{Regexp.escape(HOMEBREW_LIBRARY)}/Taps/(?<user>[\w-]+)/(?<repo>[\w-]+)}.freeze
# match taps' formula paths, e.g. HOMEBREW_LIBRARY/Taps/someuser/sometap/someformula
HOMEBREW_TAP_PATH_REGEX = Regexp.new(HOMEBREW_TAP_DIR_REGEX.source + %r{(?:/.*)?$}.source)
# match official taps' casks, e.g. homebrew/cask/somecask or homebrew/cask-versions/somecask
HOMEBREW_CASK_TAP_CASK_REGEX = %r{^(?:([Cc]askroom)/(cask|versions)|(homebrew)/(cask|cask-[\w-]+))/([\w+-.]+)$}
HOMEBREW_CASK_TAP_CASK_REGEX = %r{^(?:([Cc]askroom)/(cask|versions)|(homebrew)/(cask|cask-[\w-]+))/([\w+-.]+)$}.freeze

View File

@ -32,7 +32,8 @@ describe RuboCop::Cop::FormulaAudit::Homepage do
end
RUBY
expected_offenses = [{ message: "The homepage should start with http or https (URL is ftp://example.com/foo).",
expected_offenses = [{ message: "The homepage should start with http or " \
"https (URL is ftp://example.com/foo).",
severity: :convention,
line: 2,
column: 2,

View File

@ -72,7 +72,7 @@ module Utils
zsh: "~/.zshrc",
}.freeze
UNSAFE_SHELL_CHAR = %r{([^A-Za-z0-9_\-.,:/@~\n])}
UNSAFE_SHELL_CHAR = %r{([^A-Za-z0-9_\-.,:/@~\n])}.freeze
def csh_quote(str)
# ruby's implementation of shell_escape

View File

@ -9,7 +9,7 @@ GEM
ast (2.4.0)
backports (3.11.4)
concurrent-ruby (1.0.5)
i18n (1.1.0)
i18n (1.1.1)
concurrent-ruby (~> 1.0)
jaro_winkler (1.5.1)
minitest (5.11.3)
@ -44,7 +44,7 @@ DEPENDENCIES
backports
concurrent-ruby
plist
rubocop (= 0.59.1)
rubocop (= 0.60.0)
rubocop-rspec
ruby-macho

View File

@ -4,7 +4,7 @@ ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
ruby_version = RbConfig::CONFIG["ruby_version"]
path = File.expand_path('..', __FILE__)
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/concurrent-ruby-1.0.5/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.1.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/i18n-1.1.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/minitest-5.11.3/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/thread_safe-0.3.6/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/tzinfo-1.2.5/lib"
@ -15,12 +15,12 @@ $:.unshift "#{path}/"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/universal-darwin-18/2.3.0/jaro_winkler-1.5.1"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/jaro_winkler-1.5.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parallel-1.12.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.5.1.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/parser-2.5.3.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/plist-3.4.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/powerpack-0.1.2/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rainbow-3.0.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.10.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-1.4.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.59.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.30.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-0.60.0/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-1.30.1/lib"
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.1.0/lib"

View File

@ -1,8 +0,0 @@
module Kernel
def suppress_warnings
original_verbosity, $VERBOSE = $VERBOSE, nil
yield
ensure
$VERBOSE = original_verbosity
end
end

View File

@ -2,7 +2,6 @@
require 'yaml'
require 'i18n/core_ext/hash'
require 'i18n/core_ext/kernel/suppress_warnings'
module I18n
module Backend

View File

@ -59,6 +59,14 @@ module I18n
super
end
def translations(do_init: false)
# To avoid returning empty translations,
# call `init_translations`
init_translations if do_init && !initialized?
@translations ||= {}
end
protected
def init_translations
@ -66,10 +74,6 @@ module I18n
@initialized = true
end
def translations
@translations ||= {}
end
# Looks up a translation from the translations hash. Returns nil if
# either key is nil, or locale, scope or key do not exist as a key in the
# nested translations hash. Splits keys or scopes containing dots

View File

@ -0,0 +1,9 @@
# This file used to backport the Ruby 1.9 String interpolation syntax to Ruby 1.8.
#
# Since I18n has dropped support to Ruby 1.8, this file is not required anymore,
# however, Rails 3.2 still requires it directly:
#
# https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/core_ext/string/interpolation.rb#L2
#
# So we can't just drop the file entirely, which would then break Rails users
# under Ruby 1.9. This file can be removed once Rails 3.2 support is dropped.

View File

@ -0,0 +1,28 @@
# frozen_string_literal: true
module I18n
module Gettext
PLURAL_SEPARATOR = "\001"
CONTEXT_SEPARATOR = "\004"
autoload :Helpers, 'i18n/gettext/helpers'
@@plural_keys = { :en => [:one, :other] }
class << self
# returns an array of plural keys for the given locale or the whole hash
# of locale mappings to plural keys so that we can convert from gettext's
# integer-index based style
# TODO move this information to the pluralization module
def plural_keys(*args)
args.empty? ? @@plural_keys : @@plural_keys[args.first] || @@plural_keys[:en]
end
def extract_scope(msgid, separator)
scope = msgid.to_s.split(separator)
msgid = scope.pop
[scope, msgid]
end
end
end
end

View File

@ -0,0 +1,75 @@
# frozen_string_literal: true
require 'i18n/gettext'
module I18n
module Gettext
# Implements classical Gettext style accessors. To use this include the
# module to the global namespace or wherever you want to use it.
#
# include I18n::Gettext::Helpers
module Helpers
# Makes dynamic translation messages readable for the gettext parser.
# <tt>_(fruit)</tt> cannot be understood by the gettext parser. To help the parser find all your translations,
# you can add <tt>fruit = N_("Apple")</tt> which does not translate, but tells the parser: "Apple" needs translation.
# * msgid: the message id.
# * Returns: msgid.
def N_(msgsid)
msgsid
end
def gettext(msgid, options = EMPTY_HASH)
I18n.t(msgid, { :default => msgid, :separator => '|' }.merge(options))
end
alias _ gettext
def sgettext(msgid, separator = '|')
scope, msgid = I18n::Gettext.extract_scope(msgid, separator)
I18n.t(msgid, :scope => scope, :default => msgid, :separator => separator)
end
alias s_ sgettext
def pgettext(msgctxt, msgid)
separator = I18n::Gettext::CONTEXT_SEPARATOR
sgettext([msgctxt, msgid].join(separator), separator)
end
alias p_ pgettext
def ngettext(msgid, msgid_plural, n = 1)
nsgettext(msgid, msgid_plural, n)
end
alias n_ ngettext
# Method signatures:
# nsgettext('Fruits|apple', 'apples', 2)
# nsgettext(['Fruits|apple', 'apples'], 2)
def nsgettext(msgid, msgid_plural, n = 1, separator = '|')
if msgid.is_a?(Array)
msgid, msgid_plural, n, separator = msgid[0], msgid[1], msgid_plural, n
separator = '|' unless separator.is_a?(::String)
end
scope, msgid = I18n::Gettext.extract_scope(msgid, separator)
default = { :one => msgid, :other => msgid_plural }
I18n.t(msgid, :default => default, :count => n, :scope => scope, :separator => separator)
end
alias ns_ nsgettext
# Method signatures:
# npgettext('Fruits', 'apple', 'apples', 2)
# npgettext('Fruits', ['apple', 'apples'], 2)
def npgettext(msgctxt, msgid, msgid_plural, n = 1)
separator = I18n::Gettext::CONTEXT_SEPARATOR
if msgid.is_a?(Array)
msgid_plural, msgid, n = msgid[1], [msgctxt, msgid[0]].join(separator), msgid_plural
else
msgid = [msgctxt, msgid].join(separator)
end
nsgettext(msgid, msgid_plural, n, separator)
end
alias np_ npgettext
end
end
end

View File

@ -0,0 +1,329 @@
=begin
poparser.rb - Generate a .mo
Copyright (C) 2003-2009 Masao Mutoh <mutoh at highway.ne.jp>
You may redistribute it and/or modify it under the same
license terms as Ruby.
=end
#MODIFIED
# removed include GetText etc
# added stub translation method _(x)
require 'racc/parser'
module GetText
class PoParser < Racc::Parser
def _(x)
x
end
module_eval <<'..end src/poparser.ry modeval..id7a99570e05', 'src/poparser.ry', 108
def unescape(orig)
ret = orig.gsub(/\\n/, "\n")
ret.gsub!(/\\t/, "\t")
ret.gsub!(/\\r/, "\r")
ret.gsub!(/\\"/, "\"")
ret
end
def parse(str, data, ignore_fuzzy = true)
@comments = []
@data = data
@fuzzy = false
@msgctxt = ""
$ignore_fuzzy = ignore_fuzzy
str.strip!
@q = []
until str.empty? do
case str
when /\A\s+/
str = $'
when /\Amsgctxt/
@q.push [:MSGCTXT, $&]
str = $'
when /\Amsgid_plural/
@q.push [:MSGID_PLURAL, $&]
str = $'
when /\Amsgid/
@q.push [:MSGID, $&]
str = $'
when /\Amsgstr/
@q.push [:MSGSTR, $&]
str = $'
when /\A\[(\d+)\]/
@q.push [:PLURAL_NUM, $1]
str = $'
when /\A\#~(.*)/
$stderr.print _("Warning: obsolete msgid exists.\n")
$stderr.print " #{$&}\n"
@q.push [:COMMENT, $&]
str = $'
when /\A\#(.*)/
@q.push [:COMMENT, $&]
str = $'
when /\A\"(.*)\"/
@q.push [:STRING, $1]
str = $'
else
#c = str[0,1]
#@q.push [:STRING, c]
str = str[1..-1]
end
end
@q.push [false, '$end']
if $DEBUG
@q.each do |a,b|
puts "[#{a}, #{b}]"
end
end
@yydebug = true if $DEBUG
do_parse
if @comments.size > 0
@data.set_comment(:last, @comments.join("\n"))
end
@data
end
def next_token
@q.shift
end
def on_message(msgid, msgstr)
if msgstr.size > 0
@data[msgid] = msgstr
@data.set_comment(msgid, @comments.join("\n"))
end
@comments.clear
@msgctxt = ""
end
def on_comment(comment)
@fuzzy = true if (/fuzzy/ =~ comment)
@comments << comment
end
..end src/poparser.ry modeval..id7a99570e05
##### racc 1.4.5 generates ###
racc_reduce_table = [
0, 0, :racc_error,
0, 10, :_reduce_none,
2, 10, :_reduce_none,
2, 10, :_reduce_none,
2, 10, :_reduce_none,
2, 12, :_reduce_5,
1, 13, :_reduce_none,
1, 13, :_reduce_none,
4, 15, :_reduce_8,
5, 16, :_reduce_9,
2, 17, :_reduce_10,
1, 17, :_reduce_none,
3, 18, :_reduce_12,
1, 11, :_reduce_13,
2, 14, :_reduce_14,
1, 14, :_reduce_15 ]
racc_reduce_n = 16
racc_shift_n = 26
racc_action_table = [
3, 13, 5, 7, 9, 15, 16, 17, 20, 17,
13, 17, 13, 13, 11, 17, 23, 20, 13, 17 ]
racc_action_check = [
1, 16, 1, 1, 1, 12, 12, 12, 18, 18,
7, 14, 15, 9, 3, 19, 20, 21, 23, 25 ]
racc_action_pointer = [
nil, 0, nil, 14, nil, nil, nil, 3, nil, 6,
nil, nil, 0, nil, 4, 5, -6, nil, 2, 8,
8, 11, nil, 11, nil, 12 ]
racc_action_default = [
-1, -16, -2, -16, -3, -13, -4, -16, -6, -16,
-7, 26, -16, -15, -5, -16, -16, -14, -16, -8,
-16, -9, -11, -16, -10, -12 ]
racc_goto_table = [
12, 22, 14, 4, 24, 6, 2, 8, 18, 19,
10, 21, 1, nil, nil, nil, 25 ]
racc_goto_check = [
5, 9, 5, 3, 9, 4, 2, 6, 5, 5,
7, 8, 1, nil, nil, nil, 5 ]
racc_goto_pointer = [
nil, 12, 5, 2, 4, -7, 6, 9, -7, -17 ]
racc_goto_default = [
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ]
racc_token_table = {
false => 0,
Object.new => 1,
:COMMENT => 2,
:MSGID => 3,
:MSGCTXT => 4,
:MSGID_PLURAL => 5,
:MSGSTR => 6,
:STRING => 7,
:PLURAL_NUM => 8 }
racc_use_result_var = true
racc_nt_base = 9
Racc_arg = [
racc_action_table,
racc_action_check,
racc_action_default,
racc_action_pointer,
racc_goto_table,
racc_goto_check,
racc_goto_default,
racc_goto_pointer,
racc_nt_base,
racc_reduce_table,
racc_token_table,
racc_shift_n,
racc_reduce_n,
racc_use_result_var ]
Racc_token_to_s_table = [
'$end',
'error',
'COMMENT',
'MSGID',
'MSGCTXT',
'MSGID_PLURAL',
'MSGSTR',
'STRING',
'PLURAL_NUM',
'$start',
'msgfmt',
'comment',
'msgctxt',
'message',
'string_list',
'single_message',
'plural_message',
'msgstr_plural',
'msgstr_plural_line']
Racc_debug_parser = true
##### racc system variables end #####
# reduce 0 omitted
# reduce 1 omitted
# reduce 2 omitted
# reduce 3 omitted
# reduce 4 omitted
module_eval <<'.,.,', 'src/poparser.ry', 25
def _reduce_5( val, _values, result )
@msgctxt = unescape(val[1]) + "\004"
result
end
.,.,
# reduce 6 omitted
# reduce 7 omitted
module_eval <<'.,.,', 'src/poparser.ry', 48
def _reduce_8( val, _values, result )
if @fuzzy and $ignore_fuzzy
if val[1] != ""
$stderr.print _("Warning: fuzzy message was ignored.\n")
$stderr.print " msgid '#{val[1]}'\n"
else
on_message('', unescape(val[3]))
end
@fuzzy = false
else
on_message(@msgctxt + unescape(val[1]), unescape(val[3]))
end
result = ""
result
end
.,.,
module_eval <<'.,.,', 'src/poparser.ry', 65
def _reduce_9( val, _values, result )
if @fuzzy and $ignore_fuzzy
if val[1] != ""
$stderr.print _("Warning: fuzzy message was ignored.\n")
$stderr.print "msgid = '#{val[1]}\n"
else
on_message('', unescape(val[3]))
end
@fuzzy = false
else
on_message(@msgctxt + unescape(val[1]) + "\000" + unescape(val[3]), unescape(val[4]))
end
result = ""
result
end
.,.,
module_eval <<'.,.,', 'src/poparser.ry', 76
def _reduce_10( val, _values, result )
if val[0].size > 0
result = val[0] + "\000" + val[1]
else
result = ""
end
result
end
.,.,
# reduce 11 omitted
module_eval <<'.,.,', 'src/poparser.ry', 84
def _reduce_12( val, _values, result )
result = val[2]
result
end
.,.,
module_eval <<'.,.,', 'src/poparser.ry', 91
def _reduce_13( val, _values, result )
on_comment(val[0])
result
end
.,.,
module_eval <<'.,.,', 'src/poparser.ry', 99
def _reduce_14( val, _values, result )
result = val.delete_if{|item| item == ""}.join
result
end
.,.,
module_eval <<'.,.,', 'src/poparser.ry', 103
def _reduce_15( val, _values, result )
result = val[0]
result
end
.,.,
def _reduce_none( val, _values, result )
result
end
end # class PoParser
end # module GetText

View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
module I18n
module Locale
autoload :Fallbacks, 'i18n/locale/fallbacks'
autoload :Tag, 'i18n/locale/tag'
end
end

View File

@ -0,0 +1,96 @@
# Locale Fallbacks
#
# Extends the I18n module to hold a fallbacks instance which is set to an
# instance of I18n::Locale::Fallbacks by default but can be swapped with a
# different implementation.
#
# Locale fallbacks will compute a number of fallback locales for a given locale.
# For example:
#
# <pre><code>
# I18n.fallbacks[:"es-MX"] # => [:"es-MX", :es, :en] </code></pre>
#
# Locale fallbacks always fall back to
#
# * all parent locales of a given locale (e.g. :es for :"es-MX") first,
# * the current default locales and all of their parents second
#
# The default locales are set to [I18n.default_locale] by default but can be
# set to something else.
#
# One can additionally add any number of additional fallback locales manually.
# These will be added before the default locales to the fallback chain. For
# example:
#
# # using the default locale as default fallback locale
#
# I18n.default_locale = :"en-US"
# I18n.fallbacks = I18n::Locale::Fallbacks.new(:"de-AT" => :"de-DE")
# I18n.fallbacks[:"de-AT"] # => [:"de-AT", :"de-DE", :de, :"en-US", :en]
#
# # using a custom locale as default fallback locale
#
# I18n.fallbacks = I18n::Locale::Fallbacks.new(:"en-GB", :"de-AT" => :de, :"de-CH" => :de)
# I18n.fallbacks[:"de-AT"] # => [:"de-AT", :de, :"en-GB", :en]
# I18n.fallbacks[:"de-CH"] # => [:"de-CH", :de, :"en-GB", :en]
#
# # mapping fallbacks to an existing instance
#
# # people speaking Catalan also speak Spanish as spoken in Spain
# fallbacks = I18n.fallbacks
# fallbacks.map(:ca => :"es-ES")
# fallbacks[:ca] # => [:ca, :"es-ES", :es, :"en-US", :en]
#
# # people speaking Arabian as spoken in Palestine also speak Hebrew as spoken in Israel
# fallbacks.map(:"ar-PS" => :"he-IL")
# fallbacks[:"ar-PS"] # => [:"ar-PS", :ar, :"he-IL", :he, :"en-US", :en]
# fallbacks[:"ar-EG"] # => [:"ar-EG", :ar, :"en-US", :en]
#
# # people speaking Sami as spoken in Finnland also speak Swedish and Finnish as spoken in Finnland
# fallbacks.map(:sms => [:"se-FI", :"fi-FI"])
# fallbacks[:sms] # => [:sms, :"se-FI", :se, :"fi-FI", :fi, :"en-US", :en]
module I18n
module Locale
class Fallbacks < Hash
def initialize(*mappings)
@map = {}
map(mappings.pop) if mappings.last.is_a?(Hash)
self.defaults = mappings.empty? ? [] : mappings
end
def defaults=(defaults)
@defaults = defaults.map { |default| compute(default, false) }.flatten
end
attr_reader :defaults
def [](locale)
raise InvalidLocale.new(locale) if locale.nil?
locale = locale.to_sym
super || store(locale, compute(locale))
end
def map(mappings)
mappings.each do |from, to|
from, to = from.to_sym, Array(to)
to.each do |_to|
@map[from] ||= []
@map[from] << _to.to_sym
end
end
end
protected
def compute(tags, include_defaults = true, exclude = [])
result = Array(tags).collect do |tag|
tags = I18n::Locale::Tag.tag(tag).self_and_parents.map! { |t| t.to_sym } - exclude
tags.each { |_tag| tags += compute(@map[_tag], false, exclude + tags) if @map[_tag] }
tags
end.flatten
result.push(*defaults) if include_defaults
result.uniq.compact
end
end
end
end

View File

@ -0,0 +1,28 @@
# encoding: utf-8
module I18n
module Locale
module Tag
autoload :Parents, 'i18n/locale/tag/parents'
autoload :Rfc4646, 'i18n/locale/tag/rfc4646'
autoload :Simple, 'i18n/locale/tag/simple'
class << self
# Returns the current locale tag implementation. Defaults to +I18n::Locale::Tag::Simple+.
def implementation
@@implementation ||= Simple
end
# Sets the current locale tag implementation. Use this to set a different locale tag implementation.
def implementation=(implementation)
@@implementation = implementation
end
# Factory method for locale tags. Delegates to the current locale tag implementation.
def tag(tag)
implementation.tag(tag)
end
end
end
end
end

View File

@ -0,0 +1,22 @@
module I18n
module Locale
module Tag
module Parents
def parent
@parent ||= begin
segs = to_a.compact
segs.length > 1 ? self.class.tag(*segs[0..(segs.length-2)].join('-')) : nil
end
end
def self_and_parents
@self_and_parents ||= [self] + parents
end
def parents
@parents ||= ([parent] + (parent ? parent.parents : [])).compact
end
end
end
end
end

View File

@ -0,0 +1,74 @@
# RFC 4646/47 compliant Locale tag implementation that parses locale tags to
# subtags such as language, script, region, variant etc.
#
# For more information see by http://en.wikipedia.org/wiki/IETF_language_tag
#
# Rfc4646::Parser does not implement grandfathered tags.
module I18n
module Locale
module Tag
RFC4646_SUBTAGS = [ :language, :script, :region, :variant, :extension, :privateuse, :grandfathered ]
RFC4646_FORMATS = { :language => :downcase, :script => :capitalize, :region => :upcase, :variant => :downcase }
class Rfc4646 < Struct.new(*RFC4646_SUBTAGS)
class << self
# Parses the given tag and returns a Tag instance if it is valid.
# Returns false if the given tag is not valid according to RFC 4646.
def tag(tag)
matches = parser.match(tag)
new(*matches) if matches
end
def parser
@@parser ||= Rfc4646::Parser
end
def parser=(parser)
@@parser = parser
end
end
include Parents
RFC4646_FORMATS.each do |name, format|
define_method(name) { self[name].send(format) unless self[name].nil? }
end
def to_sym
to_s.to_sym
end
def to_s
@tag ||= to_a.compact.join("-")
end
def to_a
members.collect { |attr| self.send(attr) }
end
module Parser
PATTERN = %r{\A(?:
([a-z]{2,3}(?:(?:-[a-z]{3}){0,3})?|[a-z]{4}|[a-z]{5,8}) # language
(?:-([a-z]{4}))? # script
(?:-([a-z]{2}|\d{3}))? # region
(?:-([0-9a-z]{5,8}|\d[0-9a-z]{3}))* # variant
(?:-([0-9a-wyz](?:-[0-9a-z]{2,8})+))* # extension
(?:-(x(?:-[0-9a-z]{1,8})+))?| # privateuse subtag
(x(?:-[0-9a-z]{1,8})+)| # privateuse tag
/* ([a-z]{1,3}(?:-[0-9a-z]{2,8}){1,2}) */ # grandfathered
)\z}xi
class << self
def match(tag)
c = PATTERN.match(tag.to_s).captures
c[0..4] << (c[5].nil? ? c[6] : c[5]) << c[7] # TODO c[7] is grandfathered, throw a NotImplemented exception here?
rescue
false
end
end
end
end
end
end
end

View File

@ -0,0 +1,39 @@
# Simple Locale tag implementation that computes subtags by simply splitting
# the locale tag at '-' occurences.
module I18n
module Locale
module Tag
class Simple
class << self
def tag(tag)
new(tag)
end
end
include Parents
attr_reader :tag
def initialize(*tag)
@tag = tag.join('-').to_sym
end
def subtags
@subtags = tag.to_s.split('-').map { |subtag| subtag.to_s }
end
def to_sym
tag
end
def to_s
tag.to_s
end
def to_a
subtags
end
end
end
end
end

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
module I18n
class Middleware
def initialize(app)
@app = app
end
def call(env)
@app.call(env)
ensure
Thread.current[:i18n_config] = I18n::Config.new
end
end
end

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
module I18n
module Tests
autoload :Basics, 'i18n/tests/basics'
autoload :Defaults, 'i18n/tests/defaults'
autoload :Interpolation, 'i18n/tests/interpolation'
autoload :Link, 'i18n/tests/link'
autoload :Localization, 'i18n/tests/localization'
autoload :Lookup, 'i18n/tests/lookup'
autoload :Pluralization, 'i18n/tests/pluralization'
autoload :Procs, 'i18n/tests/procs'
end
end

View File

@ -0,0 +1,60 @@
module I18n
module Tests
module Basics
def teardown
I18n.available_locales = nil
end
test "available_locales returns the locales stored to the backend by default" do
I18n.backend.store_translations('de', :foo => 'bar')
I18n.backend.store_translations('en', :foo => 'foo')
assert I18n.available_locales.include?(:de)
assert I18n.available_locales.include?(:en)
end
test "available_locales can be set to something else independently from the actual locale data" do
I18n.backend.store_translations('de', :foo => 'bar')
I18n.backend.store_translations('en', :foo => 'foo')
I18n.available_locales = :foo
assert_equal [:foo], I18n.available_locales
I18n.available_locales = [:foo, 'bar']
assert_equal [:foo, :bar], I18n.available_locales
I18n.available_locales = nil
assert I18n.available_locales.include?(:de)
assert I18n.available_locales.include?(:en)
end
test "available_locales memoizes when set explicitely" do
I18n.backend.expects(:available_locales).never
I18n.available_locales = [:foo]
I18n.backend.store_translations('de', :bar => 'baz')
I18n.reload!
assert_equal [:foo], I18n.available_locales
end
test "available_locales delegates to the backend when not set explicitely" do
original_available_locales_value = I18n.backend.available_locales
I18n.backend.expects(:available_locales).returns(original_available_locales_value).twice
assert_equal I18n.backend.available_locales, I18n.available_locales
end
test "exists? is implemented by the backend" do
I18n.backend.store_translations(:foo, :bar => 'baz')
assert I18n.exists?(:bar, :foo)
end
test "storing a nil value as a translation removes it from the available locale data" do
I18n.backend.store_translations(:en, :to_be_deleted => 'bar')
assert_equal 'bar', I18n.t(:to_be_deleted, :default => 'baz')
I18n.cache_store.clear if I18n.respond_to?(:cache_store) && I18n.cache_store
I18n.backend.store_translations(:en, :to_be_deleted => nil)
assert_equal 'baz', I18n.t(:to_be_deleted, :default => 'baz')
end
end
end
end

View File

@ -0,0 +1,52 @@
# encoding: utf-8
module I18n
module Tests
module Defaults
def setup
super
I18n.backend.store_translations(:en, :foo => { :bar => 'bar', :baz => 'baz' })
end
test "defaults: given nil as a key it returns the given default" do
assert_equal 'default', I18n.t(nil, :default => 'default')
end
test "defaults: given a symbol as a default it translates the symbol" do
assert_equal 'bar', I18n.t(nil, :default => :'foo.bar')
end
test "defaults: given a symbol as a default and a scope it stays inside the scope when looking up the symbol" do
assert_equal 'bar', I18n.t(:missing, :default => :bar, :scope => :foo)
end
test "defaults: given an array as a default it returns the first match" do
assert_equal 'bar', I18n.t(:does_not_exist, :default => [:does_not_exist_2, :'foo.bar'])
end
test "defaults: given an array as a default with false it returns false" do
assert_equal false, I18n.t(:does_not_exist, :default => [false])
end
test "defaults: given false it returns false" do
assert_equal false, I18n.t(:does_not_exist, :default => false)
end
test "defaults: given nil it returns nil" do
assert_nil I18n.t(:does_not_exist, :default => nil)
end
test "defaults: given an array of missing keys it raises a MissingTranslationData exception" do
assert_raise I18n::MissingTranslationData do
I18n.t(:does_not_exist, :default => [:does_not_exist_2, :does_not_exist_3], :raise => true)
end
end
test "defaults: using a custom scope separator" do
# data must have been stored using the custom separator when using the ActiveRecord backend
I18n.backend.store_translations(:en, { :foo => { :bar => 'bar' } }, { :separator => '|' })
assert_equal 'bar', I18n.t(nil, :default => :'foo|bar', :separator => '|')
end
end
end
end

View File

@ -0,0 +1,159 @@
# encoding: utf-8
module I18n
module Tests
module Interpolation
# If no interpolation parameter is not given, I18n should not alter the string.
# This behavior is due to three reasons:
#
# * Checking interpolation keys in all strings hits performance, badly;
#
# * This allows us to retrieve untouched values through I18n. For example
# I could have a middleware that returns I18n lookup results in JSON
# to be processed through Javascript. Leaving the keys untouched allows
# the interpolation to happen at the javascript level;
#
# * Security concerns: if I allow users to translate a web site, they can
# insert %{} in messages causing the I18n lookup to fail in every request.
#
test "interpolation: given no values it does not alter the string" do
assert_equal 'Hi %{name}!', interpolate(:default => 'Hi %{name}!')
end
test "interpolation: given values it interpolates them into the string" do
assert_equal 'Hi David!', interpolate(:default => 'Hi %{name}!', :name => 'David')
end
test "interpolation: given a nil value it still interpolates it into the string" do
assert_equal 'Hi !', interpolate(:default => 'Hi %{name}!', :name => nil)
end
test "interpolation: given a lambda as a value it calls it if the string contains the key" do
assert_equal 'Hi David!', interpolate(:default => 'Hi %{name}!', :name => lambda { |*args| 'David' })
end
test "interpolation: given a lambda as a value it does not call it if the string does not contain the key" do
assert_nothing_raised { interpolate(:default => 'Hi!', :name => lambda { |*args| raise 'fail' }) }
end
test "interpolation: given values but missing a key it raises I18n::MissingInterpolationArgument" do
assert_raise(I18n::MissingInterpolationArgument) do
interpolate(:default => '%{foo}', :bar => 'bar')
end
end
test "interpolation: it does not raise I18n::MissingInterpolationArgument for escaped variables" do
assert_nothing_raised do
assert_equal 'Barr %{foo}', interpolate(:default => '%{bar} %%{foo}', :bar => 'Barr')
end
end
test "interpolation: it does not change the original, stored translation string" do
I18n.backend.store_translations(:en, :interpolate => 'Hi %{name}!')
assert_equal 'Hi David!', interpolate(:interpolate, :name => 'David')
assert_equal 'Hi Yehuda!', interpolate(:interpolate, :name => 'Yehuda')
end
test "interpolation: given an array interpolates each element" do
I18n.backend.store_translations(:en, :array_interpolate => ['Hi', 'Mr. %{name}', 'or sir %{name}'])
assert_equal ['Hi', 'Mr. Bartuz', 'or sir Bartuz'], interpolate(:array_interpolate, :name => 'Bartuz')
end
test "interpolation: given the translation is in utf-8 it still works" do
assert_equal 'Häi David!', interpolate(:default => 'Häi %{name}!', :name => 'David')
end
test "interpolation: given the value is in utf-8 it still works" do
assert_equal 'Hi ゆきひろ!', interpolate(:default => 'Hi %{name}!', :name => 'ゆきひろ')
end
test "interpolation: given the translation and the value are in utf-8 it still works" do
assert_equal 'こんにちは、ゆきひろさん!', interpolate(:default => 'こんにちは、%{name}さん!', :name => 'ゆきひろ')
end
if Object.const_defined?(:Encoding)
test "interpolation: given a euc-jp translation and a utf-8 value it raises Encoding::CompatibilityError" do
assert_raise(Encoding::CompatibilityError) do
interpolate(:default => euc_jp('こんにちは、%{name}さん!'), :name => 'ゆきひろ')
end
end
test "interpolation: given a utf-8 translation and a euc-jp value it raises Encoding::CompatibilityError" do
assert_raise(Encoding::CompatibilityError) do
interpolate(:default => 'こんにちは、%{name}さん!', :name => euc_jp('ゆきひろ'))
end
end
test "interpolation: ASCII strings in the backend should be encoded to UTF8 if interpolation options are in UTF8" do
I18n.backend.store_translations 'en', 'encoding' => ('%{who} let me go'.force_encoding("ASCII"))
result = I18n.t 'encoding', :who => "måmmå miå"
assert_equal Encoding::UTF_8, result.encoding
end
test "interpolation: UTF8 strings in the backend are still returned as UTF8 with ASCII interpolation" do
I18n.backend.store_translations 'en', 'encoding' => 'måmmå miå %{what}'
result = I18n.t 'encoding', :what => 'let me go'.force_encoding("ASCII")
assert_equal Encoding::UTF_8, result.encoding
end
test "interpolation: UTF8 strings in the backend are still returned as UTF8 even with numbers interpolation" do
I18n.backend.store_translations 'en', 'encoding' => '%{count} times: måmmå miå'
result = I18n.t 'encoding', :count => 3
assert_equal Encoding::UTF_8, result.encoding
end
end
test "interpolation: given a translations containing a reserved key it raises I18n::ReservedInterpolationKey" do
assert_raise(I18n::ReservedInterpolationKey) { interpolate(:foo => :bar, :default => '%{exception_handler}') }
assert_raise(I18n::ReservedInterpolationKey) { interpolate(:foo => :bar, :default => '%{default}') }
assert_raise(I18n::ReservedInterpolationKey) { interpolate(:foo => :bar, :default => '%{separator}') }
assert_raise(I18n::ReservedInterpolationKey) { interpolate(:foo => :bar, :default => '%{scope}') }
end
test "interpolation: deep interpolation for default string" do
assert_equal 'Hi %{name}!', interpolate(:default => 'Hi %{name}!', :deep_interpolation => true)
end
test "interpolation: deep interpolation for interpolated string" do
assert_equal 'Hi Ann!', interpolate(:default => 'Hi %{name}!', :name => 'Ann', :deep_interpolation => true)
end
test "interpolation: deep interpolation for Hash" do
people = { :people => { :ann => 'Ann is %{ann}', :john => 'John is %{john}' } }
interpolated_people = { :people => { :ann => 'Ann is good', :john => 'John is big' } }
assert_equal interpolated_people, interpolate(:default => people, :ann => 'good', :john => 'big', :deep_interpolation => true)
end
test "interpolation: deep interpolation for Array" do
people = { :people => ['Ann is %{ann}', 'John is %{john}'] }
interpolated_people = { :people => ['Ann is good', 'John is big'] }
assert_equal interpolated_people, interpolate(:default => people, :ann => 'good', :john => 'big', :deep_interpolation => true)
end
protected
def capture(stream)
begin
stream = stream.to_s
eval "$#{stream} = StringIO.new"
yield
result = eval("$#{stream}").string
ensure
eval("$#{stream} = #{stream.upcase}")
end
result
end
def euc_jp(string)
string.encode!(Encoding::EUC_JP)
end
def interpolate(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
key = args.pop
I18n.backend.translate('en', key, options)
end
end
end
end

View File

@ -0,0 +1,56 @@
# encoding: utf-8
module I18n
module Tests
module Link
test "linked lookup: if a key resolves to a symbol it looks up the symbol" do
I18n.backend.store_translations 'en', {
:link => :linked,
:linked => 'linked'
}
assert_equal 'linked', I18n.backend.translate('en', :link)
end
test "linked lookup: if a key resolves to a dot-separated symbol it looks up the symbol" do
I18n.backend.store_translations 'en', {
:link => :"foo.linked",
:foo => { :linked => 'linked' }
}
assert_equal('linked', I18n.backend.translate('en', :link))
end
test "linked lookup: if a dot-separated key resolves to a symbol it looks up the symbol" do
I18n.backend.store_translations 'en', {
:foo => { :link => :linked },
:linked => 'linked'
}
assert_equal('linked', I18n.backend.translate('en', :'foo.link'))
end
test "linked lookup: if a dot-separated key resolves to a dot-separated symbol it looks up the symbol" do
I18n.backend.store_translations 'en', {
:foo => { :link => :"bar.linked" },
:bar => { :linked => 'linked' }
}
assert_equal('linked', I18n.backend.translate('en', :'foo.link'))
end
test "linked lookup: links always refer to the absolute key" do
I18n.backend.store_translations 'en', {
:foo => { :link => :linked, :linked => 'linked in foo' },
:linked => 'linked absolutely'
}
assert_equal 'linked absolutely', I18n.backend.translate('en', :link, :scope => :foo)
end
test "linked lookup: a link can resolve to a namespace in the middle of a dot-separated key" do
I18n.backend.store_translations 'en', {
:activemodel => { :errors => { :messages => { :blank => "can't be blank" } } },
:activerecord => { :errors => { :messages => :"activemodel.errors.messages" } }
}
assert_equal "can't be blank", I18n.t(:"activerecord.errors.messages.blank")
assert_equal "can't be blank", I18n.t(:"activerecord.errors.messages.blank")
end
end
end
end

View File

@ -0,0 +1,19 @@
module I18n
module Tests
module Localization
autoload :Date, 'i18n/tests/localization/date'
autoload :DateTime, 'i18n/tests/localization/date_time'
autoload :Time, 'i18n/tests/localization/time'
autoload :Procs, 'i18n/tests/localization/procs'
def self.included(base)
base.class_eval do
include I18n::Tests::Localization::Date
include I18n::Tests::Localization::DateTime
include I18n::Tests::Localization::Procs
include I18n::Tests::Localization::Time
end
end
end
end
end

View File

@ -0,0 +1,95 @@
# encoding: utf-8
module I18n
module Tests
module Localization
module Date
def setup
super
setup_date_translations
@date = ::Date.new(2008, 3, 1)
end
test "localize Date: given the short format it uses it" do
# TODO should be Mrz, shouldn't it?
assert_equal '01. Mar', I18n.l(@date, :format => :short, :locale => :de)
end
test "localize Date: given the long format it uses it" do
assert_equal '01. März 2008', I18n.l(@date, :format => :long, :locale => :de)
end
test "localize Date: given the default format it uses it" do
assert_equal '01.03.2008', I18n.l(@date, :format => :default, :locale => :de)
end
test "localize Date: given a day name format it returns the correct day name" do
assert_equal 'Samstag', I18n.l(@date, :format => '%A', :locale => :de)
end
test "localize Date: given an abbreviated day name format it returns the correct abbreviated day name" do
assert_equal 'Sa', I18n.l(@date, :format => '%a', :locale => :de)
end
test "localize Date: given a month name format it returns the correct month name" do
assert_equal 'März', I18n.l(@date, :format => '%B', :locale => :de)
end
test "localize Date: given an abbreviated month name format it returns the correct abbreviated month name" do
# TODO should be Mrz, shouldn't it?
assert_equal 'Mar', I18n.l(@date, :format => '%b', :locale => :de)
end
test "localize Date: given an unknown format it does not fail" do
assert_nothing_raised { I18n.l(@date, :format => '%x') }
end
test "localize Date: does not modify the options hash" do
options = { :format => '%b', :locale => :de }
assert_equal 'Mar', I18n.l(@date, options)
assert_equal({ :format => '%b', :locale => :de }, options)
assert_nothing_raised { I18n.l(@date, options.freeze) }
end
test "localize Date: given nil with default value it returns default" do
assert_equal 'default', I18n.l(nil, :default => 'default')
end
test "localize Date: given nil it raises I18n::ArgumentError" do
assert_raise(I18n::ArgumentError) { I18n.l(nil) }
end
test "localize Date: given a plain Object it raises I18n::ArgumentError" do
assert_raise(I18n::ArgumentError) { I18n.l(Object.new) }
end
test "localize Date: given a format is missing it raises I18n::MissingTranslationData" do
assert_raise(I18n::MissingTranslationData) { I18n.l(@date, :format => :missing) }
end
test "localize Date: it does not alter the format string" do
assert_equal '01. Februar 2009', I18n.l(::Date.parse('2009-02-01'), :format => :long, :locale => :de)
assert_equal '01. Oktober 2009', I18n.l(::Date.parse('2009-10-01'), :format => :long, :locale => :de)
end
protected
def setup_date_translations
I18n.backend.store_translations :de, {
:date => {
:formats => {
:default => "%d.%m.%Y",
:short => "%d. %b",
:long => "%d. %B %Y",
},
:day_names => %w(Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag),
:abbr_day_names => %w(So Mo Di Mi Do Fr Sa),
:month_names => %w(Januar Februar März April Mai Juni Juli August September Oktober November Dezember).unshift(nil),
:abbr_month_names => %w(Jan Feb Mar Apr Mai Jun Jul Aug Sep Okt Nov Dez).unshift(nil)
}
}
end
end
end
end
end

View File

@ -0,0 +1,82 @@
# encoding: utf-8
module I18n
module Tests
module Localization
module DateTime
def setup
super
setup_datetime_translations
@datetime = ::DateTime.new(2008, 3, 1, 6)
@other_datetime = ::DateTime.new(2008, 3, 1, 18)
end
test "localize DateTime: given the short format it uses it" do
# TODO should be Mrz, shouldn't it?
assert_equal '01. Mar 06:00', I18n.l(@datetime, :format => :short, :locale => :de)
end
test "localize DateTime: given the long format it uses it" do
assert_equal '01. März 2008 06:00', I18n.l(@datetime, :format => :long, :locale => :de)
end
test "localize DateTime: given the default format it uses it" do
# TODO should be Mrz, shouldn't it?
assert_equal 'Sa, 01. Mar 2008 06:00:00 +0000', I18n.l(@datetime, :format => :default, :locale => :de)
end
test "localize DateTime: given a day name format it returns the correct day name" do
assert_equal 'Samstag', I18n.l(@datetime, :format => '%A', :locale => :de)
end
test "localize DateTime: given an abbreviated day name format it returns the correct abbreviated day name" do
assert_equal 'Sa', I18n.l(@datetime, :format => '%a', :locale => :de)
end
test "localize DateTime: given a month name format it returns the correct month name" do
assert_equal 'März', I18n.l(@datetime, :format => '%B', :locale => :de)
end
test "localize DateTime: given an abbreviated month name format it returns the correct abbreviated month name" do
# TODO should be Mrz, shouldn't it?
assert_equal 'Mar', I18n.l(@datetime, :format => '%b', :locale => :de)
end
test "localize DateTime: given a meridian indicator format it returns the correct meridian indicator" do
assert_equal 'AM', I18n.l(@datetime, :format => '%p', :locale => :de)
assert_equal 'PM', I18n.l(@other_datetime, :format => '%p', :locale => :de)
end
test "localize DateTime: given a meridian indicator format it returns the correct meridian indicator in downcase" do
assert_equal 'am', I18n.l(@datetime, :format => '%P', :locale => :de)
assert_equal 'pm', I18n.l(@other_datetime, :format => '%P', :locale => :de)
end
test "localize DateTime: given an unknown format it does not fail" do
assert_nothing_raised { I18n.l(@datetime, :format => '%x') }
end
test "localize DateTime: given a format is missing it raises I18n::MissingTranslationData" do
assert_raise(I18n::MissingTranslationData) { I18n.l(@datetime, :format => :missing) }
end
protected
def setup_datetime_translations
# time translations might have been set up in Tests::Api::Localization::Time
I18n.backend.store_translations :de, {
:time => {
:formats => {
:default => "%a, %d. %b %Y %H:%M:%S %z",
:short => "%d. %b %H:%M",
:long => "%d. %B %Y %H:%M"
},
:am => 'am',
:pm => 'pm'
}
}
end
end
end
end
end

View File

@ -0,0 +1,116 @@
# encoding: utf-8
module I18n
module Tests
module Localization
module Procs
test "localize: using day names from lambdas" do
setup_time_proc_translations
time = ::Time.utc(2008, 3, 1, 6, 0)
assert_match(/Суббота/, I18n.l(time, :format => "%A, %d %B", :locale => :ru))
assert_match(/суббота/, I18n.l(time, :format => "%d %B (%A)", :locale => :ru))
end
test "localize: using month names from lambdas" do
setup_time_proc_translations
time = ::Time.utc(2008, 3, 1, 6, 0)
assert_match(/марта/, I18n.l(time, :format => "%d %B %Y", :locale => :ru))
assert_match(/Март /, I18n.l(time, :format => "%B %Y", :locale => :ru))
end
test "localize: using abbreviated day names from lambdas" do
setup_time_proc_translations
time = ::Time.utc(2008, 3, 1, 6, 0)
assert_match(/марта/, I18n.l(time, :format => "%d %b %Y", :locale => :ru))
assert_match(/март /, I18n.l(time, :format => "%b %Y", :locale => :ru))
end
test "localize Date: given a format that resolves to a Proc it calls the Proc with the object" do
setup_time_proc_translations
date = ::Date.new(2008, 3, 1)
assert_equal '[Sat, 01 Mar 2008, {}]', I18n.l(date, :format => :proc, :locale => :ru)
end
test "localize Date: given a format that resolves to a Proc it calls the Proc with the object and extra options" do
setup_time_proc_translations
date = ::Date.new(2008, 3, 1)
assert_equal '[Sat, 01 Mar 2008, {:foo=>"foo"}]', I18n.l(date, :format => :proc, :foo => 'foo', :locale => :ru)
end
test "localize DateTime: given a format that resolves to a Proc it calls the Proc with the object" do
setup_time_proc_translations
datetime = ::DateTime.new(2008, 3, 1, 6)
assert_equal '[Sat, 01 Mar 2008 06:00:00 +00:00, {}]', I18n.l(datetime, :format => :proc, :locale => :ru)
end
test "localize DateTime: given a format that resolves to a Proc it calls the Proc with the object and extra options" do
setup_time_proc_translations
datetime = ::DateTime.new(2008, 3, 1, 6)
assert_equal '[Sat, 01 Mar 2008 06:00:00 +00:00, {:foo=>"foo"}]', I18n.l(datetime, :format => :proc, :foo => 'foo', :locale => :ru)
end
test "localize Time: given a format that resolves to a Proc it calls the Proc with the object" do
setup_time_proc_translations
time = ::Time.utc(2008, 3, 1, 6, 0)
assert_equal I18n::Tests::Localization::Procs.inspect_args([time, {}]), I18n.l(time, :format => :proc, :locale => :ru)
end
test "localize Time: given a format that resolves to a Proc it calls the Proc with the object and extra options" do
setup_time_proc_translations
time = ::Time.utc(2008, 3, 1, 6, 0)
options = { :foo => 'foo' }
assert_equal I18n::Tests::Localization::Procs.inspect_args([time, options]), I18n.l(time, options.merge(:format => :proc, :locale => :ru))
end
protected
def self.inspect_args(args)
args = args.map do |arg|
case arg
when ::Time, ::DateTime
arg.strftime('%a, %d %b %Y %H:%M:%S %Z').sub('+0000', '+00:00')
when ::Date
arg.strftime('%a, %d %b %Y')
when Hash
arg.delete(:fallback_in_progress)
arg.inspect
else
arg.inspect
end
end
"[#{args.join(', ')}]"
end
def setup_time_proc_translations
I18n.backend.store_translations :ru, {
:time => {
:formats => {
:proc => lambda { |*args| I18n::Tests::Localization::Procs.inspect_args(args) }
}
},
:date => {
:formats => {
:proc => lambda { |*args| I18n::Tests::Localization::Procs.inspect_args(args) }
},
:'day_names' => lambda { |key, options|
(options[:format] =~ /^%A/) ?
%w(Воскресенье Понедельник Вторник Среда Четверг Пятница Суббота) :
%w(воскресенье понедельник вторник среда четверг пятница суббота)
},
:'month_names' => lambda { |key, options|
(options[:format] =~ /(%d|%e)(\s*)?(%B)/) ?
%w(января февраля марта апреля мая июня июля августа сентября октября ноября декабря).unshift(nil) :
%w(Январь Февраль Март Апрель Май Июнь Июль Август Сентябрь Октябрь Ноябрь Декабрь).unshift(nil)
},
:'abbr_month_names' => lambda { |key, options|
(options[:format] =~ /(%d|%e)(\s*)(%b)/) ?
%w(янв. февр. марта апр. мая июня июля авг. сент. окт. нояб. дек.).unshift(nil) :
%w(янв. февр. март апр. май июнь июль авг. сент. окт. нояб. дек.).unshift(nil)
},
}
}
end
end
end
end
end

View File

@ -0,0 +1,81 @@
# encoding: utf-8
module I18n
module Tests
module Localization
module Time
def setup
super
setup_time_translations
@time = ::Time.utc(2008, 3, 1, 6, 0)
@other_time = ::Time.utc(2008, 3, 1, 18, 0)
end
test "localize Time: given the short format it uses it" do
# TODO should be Mrz, shouldn't it?
assert_equal '01. Mar 06:00', I18n.l(@time, :format => :short, :locale => :de)
end
test "localize Time: given the long format it uses it" do
assert_equal '01. März 2008 06:00', I18n.l(@time, :format => :long, :locale => :de)
end
# TODO Seems to break on Windows because ENV['TZ'] is ignored. What's a better way to do this?
# def test_localize_given_the_default_format_it_uses_it
# assert_equal 'Sa, 01. Mar 2008 06:00:00 +0000', I18n.l(@time, :format => :default, :locale => :de)
# end
test "localize Time: given a day name format it returns the correct day name" do
assert_equal 'Samstag', I18n.l(@time, :format => '%A', :locale => :de)
end
test "localize Time: given an abbreviated day name format it returns the correct abbreviated day name" do
assert_equal 'Sa', I18n.l(@time, :format => '%a', :locale => :de)
end
test "localize Time: given a month name format it returns the correct month name" do
assert_equal 'März', I18n.l(@time, :format => '%B', :locale => :de)
end
test "localize Time: given an abbreviated month name format it returns the correct abbreviated month name" do
# TODO should be Mrz, shouldn't it?
assert_equal 'Mar', I18n.l(@time, :format => '%b', :locale => :de)
end
test "localize Time: given a meridian indicator format it returns the correct meridian indicator" do
assert_equal 'AM', I18n.l(@time, :format => '%p', :locale => :de)
assert_equal 'PM', I18n.l(@other_time, :format => '%p', :locale => :de)
end
test "localize Time: given a meridian indicator format it returns the correct meridian indicator in upcase" do
assert_equal 'am', I18n.l(@time, :format => '%P', :locale => :de)
assert_equal 'pm', I18n.l(@other_time, :format => '%P', :locale => :de)
end
test "localize Time: given an unknown format it does not fail" do
assert_nothing_raised { I18n.l(@time, :format => '%x') }
end
test "localize Time: given a format is missing it raises I18n::MissingTranslationData" do
assert_raise(I18n::MissingTranslationData) { I18n.l(@time, :format => :missing) }
end
protected
def setup_time_translations
I18n.backend.store_translations :de, {
:time => {
:formats => {
:default => "%a, %d. %b %Y %H:%M:%S %z",
:short => "%d. %b %H:%M",
:long => "%d. %B %Y %H:%M",
},
:am => 'am',
:pm => 'pm'
}
}
end
end
end
end
end

View File

@ -0,0 +1,81 @@
# encoding: utf-8
module I18n
module Tests
module Lookup
def setup
super
I18n.backend.store_translations(:en, :foo => { :bar => 'bar', :baz => 'baz' }, :falsy => false, :truthy => true,
:string => "a", :array => %w(a b c), :hash => { "a" => "b" })
end
test "lookup: it returns a string" do
assert_equal("a", I18n.t(:string))
end
test "lookup: it returns hash" do
assert_equal({ :a => "b" }, I18n.t(:hash))
end
test "lookup: it returns an array" do
assert_equal(%w(a b c), I18n.t(:array))
end
test "lookup: it returns a native true" do
assert I18n.t(:truthy) === true
end
test "lookup: it returns a native false" do
assert I18n.t(:falsy) === false
end
test "lookup: given a missing key, no default and no raise option it returns an error message" do
assert_equal "translation missing: en.missing", I18n.t(:missing)
end
test "lookup: given a missing key, no default and the raise option it raises MissingTranslationData" do
assert_raise(I18n::MissingTranslationData) { I18n.t(:missing, :raise => true) }
end
test "lookup: does not raise an exception if no translation data is present for the given locale" do
assert_nothing_raised { I18n.t(:foo, :locale => :xx) }
end
test "lookup: does not modify the options hash" do
options = {}
assert_equal "a", I18n.t(:string, options)
assert_equal({}, options)
assert_nothing_raised { I18n.t(:string, options.freeze) }
end
test "lookup: given an array of keys it translates all of them" do
assert_equal %w(bar baz), I18n.t([:bar, :baz], :scope => [:foo])
end
test "lookup: using a custom scope separator" do
# data must have been stored using the custom separator when using the ActiveRecord backend
I18n.backend.store_translations(:en, { :foo => { :bar => 'bar' } }, { :separator => '|' })
assert_equal 'bar', I18n.t('foo|bar', :separator => '|')
end
# In fact it probably *should* fail but Rails currently relies on using the default locale instead.
# So we'll stick to this for now until we get it fixed in Rails.
test "lookup: given nil as a locale it does not raise but use the default locale" do
# assert_raise(I18n::InvalidLocale) { I18n.t(:bar, :locale => nil) }
assert_nothing_raised { I18n.t(:bar, :locale => nil) }
end
test "lookup: a resulting String is not frozen" do
assert !I18n.t(:string).frozen?
end
test "lookup: a resulting Array is not frozen" do
assert !I18n.t(:array).frozen?
end
test "lookup: a resulting Hash is not frozen" do
assert !I18n.t(:hash).frozen?
end
end
end
end

View File

@ -0,0 +1,35 @@
# encoding: utf-8
module I18n
module Tests
module Pluralization
test "pluralization: given 0 it returns the :zero translation if it is defined" do
assert_equal 'zero', I18n.t(:default => { :zero => 'zero' }, :count => 0)
end
test "pluralization: given 0 it returns the :other translation if :zero is not defined" do
assert_equal 'bars', I18n.t(:default => { :other => 'bars' }, :count => 0)
end
test "pluralization: given 1 it returns the singular translation" do
assert_equal 'bar', I18n.t(:default => { :one => 'bar' }, :count => 1)
end
test "pluralization: given 2 it returns the :other translation" do
assert_equal 'bars', I18n.t(:default => { :other => 'bars' }, :count => 2)
end
test "pluralization: given 3 it returns the :other translation" do
assert_equal 'bars', I18n.t(:default => { :other => 'bars' }, :count => 3)
end
test "pluralization: given nil it returns the whole entry" do
assert_equal({ :one => 'bar' }, I18n.t(:default => { :one => 'bar' }, :count => nil))
end
test "pluralization: given incomplete pluralization data it raises I18n::InvalidPluralizationData" do
assert_raise(I18n::InvalidPluralizationData) { I18n.t(:default => { :one => 'bar' }, :count => 2) }
end
end
end
end

View File

@ -0,0 +1,55 @@
# encoding: utf-8
module I18n
module Tests
module Procs
test "lookup: given a translation is a proc it calls the proc with the key and interpolation values" do
I18n.backend.store_translations(:en, :a_lambda => lambda { |*args| I18n::Tests::Procs.filter_args(*args) })
assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(:a_lambda, :foo => 'foo')
end
test "defaults: given a default is a Proc it calls it with the key and interpolation values" do
proc = lambda { |*args| I18n::Tests::Procs.filter_args(*args) }
assert_equal '[nil, {:foo=>"foo"}]', I18n.t(nil, :default => proc, :foo => 'foo')
end
test "defaults: given a default is a key that resolves to a Proc it calls it with the key and interpolation values" do
the_lambda = lambda { |*args| I18n::Tests::Procs.filter_args(*args) }
I18n.backend.store_translations(:en, :a_lambda => the_lambda)
assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(nil, :default => :a_lambda, :foo => 'foo')
assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(nil, :default => [nil, :a_lambda], :foo => 'foo')
end
test "interpolation: given an interpolation value is a lambda it calls it with key and values before interpolating it" do
proc = lambda { |*args| I18n::Tests::Procs.filter_args(*args) }
assert_match %r(\[\{:foo=>#<Proc.*>\}\]), I18n.t(nil, :default => '%{foo}', :foo => proc)
end
test "interpolation: given a key resolves to a Proc that returns a string then interpolation still works" do
proc = lambda { |*args| "%{foo}: " + I18n::Tests::Procs.filter_args(*args) }
assert_equal 'foo: [nil, {:foo=>"foo"}]', I18n.t(nil, :default => proc, :foo => 'foo')
end
test "pluralization: given a key resolves to a Proc that returns valid data then pluralization still works" do
proc = lambda { |*args| { :zero => 'zero', :one => 'one', :other => 'other' } }
assert_equal 'zero', I18n.t(:default => proc, :count => 0)
assert_equal 'one', I18n.t(:default => proc, :count => 1)
assert_equal 'other', I18n.t(:default => proc, :count => 2)
end
test "lookup: given the option :resolve => false was passed it does not resolve proc translations" do
I18n.backend.store_translations(:en, :a_lambda => lambda { |*args| I18n::Tests::Procs.filter_args(*args) })
assert_equal Proc, I18n.t(:a_lambda, :resolve => false).class
end
test "lookup: given the option :resolve => false was passed it does not resolve proc default" do
assert_equal Proc, I18n.t(nil, :default => lambda { |*args| I18n::Tests::Procs.filter_args(*args) }, :resolve => false).class
end
def self.filter_args(*args)
args.map {|arg| arg.delete(:fallback_in_progress) if arg.is_a?(Hash) ; arg }.inspect
end
end
end
end

View File

@ -1,5 +1,5 @@
# frozen_string_literal: true
module I18n
VERSION = "1.1.0"
VERSION = "1.1.1"
end

View File

@ -0,0 +1,391 @@
# Change log
## Master (Unreleased)
## 1.30.1 (2018-11-01)
* `FactoryBot/CreateList` now ignores `times` blocks with an argument. ([@Darhazer][])
## 1.30.0 (2018-10-08)
* Add config to `RSpec/VerifiedDoubles` to enforcement of verification on unnamed doubles. ([@BrentWheeldon][])
* Fix `FactoryBot/AttributeDefinedStatically` not working when there is a non-symbol key. ([@vzvu3k6k][])
* Fix false positive in `RSpec/ImplicitSubject` when `is_expected` is used inside `its()` block. ([@Darhazer][])
* Add `single_statement_only` style to `RSpec/ImplicitSubject` as a more relaxed alternative to `single_line_only`. ([@Darhazer][])
* Add `RSpec/UnspecifiedException` as a default cop to encourage more-specific `expect{}.to raise_error(ExceptionType)`, or `raise_exception` style handling of exceptions. ([@daveworth][])
## 1.29.1 (2018-09-01)
* Fix false negative in `FactoryBot/AttributeDefinedStatically` when attribute is defined on `self`. ([@Darhazer][])
* `RSpec/FactoryBot` cops will now also inspect the `spec/factories.rb` path by default. ([@bquorning][])
## 1.29.0 (2018-08-25)
* `RSpec/InstanceVariable` - Recommend local variables in addition to `let`. ([@jaredbeck][])
* Add `RSpec/ImplicitSubject` cop. ([@Darhazer][])
* Add `RSpec/HooksBeforeExamples` cop. ([@Darhazer][])
## 1.28.0 (2018-08-14)
* Add `RSpec/ReceiveNever` cop enforcing usage of `not_to receive` instead of `never` matcher. ([@Darhazer][])
* Fix false positive in `RSpec/EmptyLineAfterExampleGroup` cop when example is inside `if`. ([@Darhazer][])
* Add `RSpec/MissingExampleGroupArgument` to enforce first argument for an example group. ([@geniou][])
* Drop support for ruby `2.1`. ([@bquorning][])
* Add `FactoryBot/AttributeDefinedStatically` cop to help FactoryBot users with the deprecation of static attributes. ([@composerinteralia][], [@seanpdoyle][])
* Remove `FactoryBot/DynamicAttributeDefinedStatically` and `FactoryBot/StaticAttributeDefinedDynamically` cops. ([@composerinteralia][])
## 1.27.0 (2018-06-14)
* `RSpec/LeadingSubject` now enforces subject to be before any examples, hooks or let declarations. ([@Darhazer][])
* Fix `RSpec/NotToNot` to highlight only the selector (`not_to` or `to_not`), so it works also on `expect { ... }` blocks. ([@bquorning][])
* Add `RSpec/EmptyLineAfterHook` cop. ([@bquorning][])
* Add `RSpec/EmptyLineAfterExampleGroup` cop to check that there is an empty line after example group blocks. ([@bquorning][])
* Fix `RSpec/DescribeClass` crashing on `RSpec.describe` without arguments. ([@Darhazer][])
* Bump RuboCop requirement to v0.56.0. ([@bquorning][])
* Fix `RSpec/OverwritingSetup` crashing if a variable is used as an argument for `let`. ([@Darhazer][])
## 1.26.0 (2018-06-06)
* Fix false positive in `RSpec/EmptyExampleGroup` cop when methods named like a RSpec method are used. ([@Darhazer][])
* Fix `Capybara/FeatureMethods` not working when there is require before the spec. ([@Darhazer][])
* Fix `RSpec/EmptyLineAfterFinalLet`: allow a comment to be placed after latest let, requiring empty line after the comment. ([@Darhazer][])
* Add `RSpec/ReceiveCounts` cop to enforce usage of :once and :twice matchers. ([@Darhazer][])
## 1.25.1 (2018-04-10)
* Fix false positive in `RSpec/Pending` cop when pending is used as a method name. ([@Darhazer][])
* Fix `FactoryBot/DynamicAttributeDefinedStatically` false positive when using symbol proc argument for a sequence. ([@tdeo][])
## 1.25.0 (2018-04-07)
* Add `RSpec/SharedExamples` cop to enforce consistent usage of string to titleize shared examples. ([@anthony-robin][])
* Add `RSpec/Be` cop to enforce passing argument to the generic `be` matcher. ([@Darhazer][])
* Fix false positives in `StaticAttributeDefinedDynamically` and `ReturnFromStub` when a const is used in an array or hash. ([@Darhazer][])
* Add `RSpec/Pending` cop to enforce no existing pending or skipped examples. This is disabled by default. ([@patrickomatic][])
* Fix `RSpec/NestedGroups` cop support --auto-gen-config. ([@walf443][])
* Fix false positives in `Capybara/FeatureMethods` when feature methods are used as property names in a factory. ([@Darhazer][])
* Allow configuring enabled methods in `Capybara/FeatureMethods`. ([@Darhazer][])
* Add `FactoryBot/CreateList` cop. ([@Darhazer][])
## 1.24.0 (2018-03-06)
* Compatibility with RuboCop v0.53.0. ([@bquorning][])
* The `Rails/HttpStatus` cop is unavailable if the `rack` gem cannot be loaded. ([@bquorning][])
* Fix `Rails/HttpStatus` not working with custom HTTP status codes. ([@bquorning][])
* Fix `FactoryBot/StaticAttributeDefinedDynamically` to handle empty block. ([@abrom][])
* Fix false positive in `FactoryBot/DynamicAttributeDefinedStatically` when a before/after callback has a symbol proc argument. ([@abrom][])
## 1.23.0 (2018-02-23)
* Add `RSpec/Rails/HttpStatus` cop to enforce consistent usage of the status format (numeric or symbolic). ([@anthony-robin][], [@jojos003][])
* Fix false negative in `RSpec/ReturnFromStub` when a constant is being returned by the stub. ([@Darhazer][])
* Fix `FactoryBot/DynamicAttributeDefinedStatically` to handle dynamic attributes inside arrays/hashes. ([@abrom][])
* Add `FactoryBot/StaticAttributeDefinedDynamically` (based on dynamic attribute cop). ([@abrom][])
## 1.22.2 (2018-02-01)
* Fix error in `RSpec/DescribedClass` when working on an empty `describe` block. ([@bquorning][])
## 1.22.1 (2018-01-17)
* Fix false positives in `RSpec/ReturnFromStub`. ([@Darhazer][])
## 1.22.0 (2018-01-10)
* Updates `describe_class` to account for RSpecs `:system` wrapper of rails system tests. ([@EliseFitz15][])
* Add `RSpec/ExpectChange` cop to enforce consistent usage of the change matcher. ([@Darhazer][])
* Add autocorrect support to `RSpec/LetBeforeExamples`. ([@Darhazer][])
* Fix `RSpec/InstanceVariable` flagging instance variables inside dynamically defined class. ([@Darhazer][])
* Add autocorrect support for `RSpec/ReturnFromStub` cop. ([@bquorning][])
* Add `RSpec/ExampleWithoutDescription` cop. ([@Darhazer][])
## 1.21.0 (2017-12-13)
* Compatibility with RuboCop v0.52.0. ([@bquorning][])
* Improve performance when user does not override default RSpec Pattern config. ([@walf443][])
* Add `AggregateFailuresByDefault` configuration for `RSpec/MultipleExpectations` cop. ([@onk][])
## 1.20.1 (2017-11-15)
* Add "without" to list of default allowed prefixes for `RSpec/ContextWording`. ([@bquorning][])
## 1.20.0 (2017-11-09)
* Rename namespace `FactoryGirl` to `FactoryBot` following original library update. ([@walf443][])
* Fix exception in `RSpec/ReturnFromStub` on empty block. ([@yevhene][])
* Add `RSpec/ContextWording` cop. ([@pirj][], [@telmofcosta][])
* Fix `RSpec/SubjectStub` cop matches receive message inside all matcher. ([@walf443][])
## 1.19.0 (2017-10-18)
Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
## 1.18.0 (2017-09-29)
* Fix false positive in `Capybara/FeatureMethods`. ([@Darhazer][])
* Add `RSpec/Capybara/CurrentPathExpectation` cop for feature specs, disallowing setting expectations on `current_path`. ([@timrogers][])
* Fix false positive in `RSpec/LetBeforeExamples` cop when example group contains single let. ([@Darhazer][])
## 1.17.1 (2017-09-20)
* Improved `RSpec/ReturnFromStub` to handle string interpolation, hashes and do..end blocks. ([@Darhazer][])
* Fixed compatibility with JRuby. ([@zverok][])
## 1.17.0 (2017-09-14)
* Add `RSpec/Capybara` namespace including the first cop for feature specs: `Capybara/FeatureMethods`. ([@rspeicher][])
* Update to RuboCop 0.50.0. ([@bquorning][])
## 1.16.0 (2017-09-06)
* Add `RSpec/FactoryGirl` namespace including the first cop for factories: `FactoryGirl/DynamicAttributeDefinedStatically`. ([@jonatas][])
* Add disabled by default `RSpec/AlignLeftLetBrace`. ([@backus][])
* Add disabled by default `RSpec/AlignRightLetBrace`. ([@backus][])
* Add `RSpec/LetBeforeExamples` cop. ([@Darhazer][])
* Add `RSpec/MultipleSubjects` cop. ([@backus][])
* Add `RSpec/ReturnFromStub` cop. ([@Darhazer][])
* Add `RSpec/VoidExpect` cop. ([@pocke][])
* Add `RSpec/InvalidPredicateMatcher` cop. ([@pocke][])
* Change HookArgument cop to detect when hook has a receiver. ([@pocke][])
* Add `RSpec/PredicateMatcher` cop. ([@pocke][])
* Add `RSpec/ExpectInHook` cop. ([@pocke][])
* `RSpec/MultipleExpectations` now detects usage of expect_any_instance_of. ([@Darhazer][])
* `RSpec/MultipleExpectations` now detects usage of is_expected. ([@bmorrall][])
## 1.15.1 (2017-04-30)
* Fix the handling of various edge cases in the `RSpec/ExampleWording` cop, including one that would cause autocorrect to crash. ([@dgollahon][])
* Fix `RSpec/IteratedExpectation` crashing when there is an assignment in the iteration. ([@Darhazer][])
* Fix false positive in `RSpec/SingleArgumentMessageChain` cop when the single argument is a hash. ([@Darhazer][])
## 1.15.0 (2017-03-24)
* Add `RSpec/DescribeSymbol` cop. ([@rspeicher][])
* Fix error when `RSpec/OverwritingSetup` and `RSpec/ScatteredLet` analyzed empty example groups. ([@backus][])
## 1.14.0 (2017-03-24)
* Add `RSpec/OverwritingSetup` cop. ([@Darhazer][])
* Add autocorrect support for `RSpec/LeadingSubject` cop. ([@Darhazer][])
* Add `RSpec/ScatteredLet` cop. ([@Darhazer][])
* Add `RSpec/IteratedExpectation` cop. ([@Darhazer][])
* Add `RSpec/EmptyLineAfterSubject` cop. ([@Darhazer][])
* Add `RSpec/EmptyLineAfterFinalLet` cop. ([@Darhazer][])
## 1.13.0 (2017-03-07)
* Add repeated 'it' detection to `RSpec/ExampleWording` cop. ([@dgollahon][])
* Add [observed_nesting/max_nesting] info to `RSpec/NestedGroups` messages. ([@dgollahon][])
* Add `RSpec/ItBehavesLike` cop. ([@dgollahon][])
* Add `RSpec/SharedContext` cop. ([@Darhazer][])
* `Rspec/MultipleExpectations`: Count aggregate_failures block as single expectation. ([@Darhazer][])
* Fix `ExpectActual` cop flagging `rspec-rails` routing specs. ([@backus][])
* Fix `FilePath` cop not registering offenses for files like `spec/blog/user.rb` when it should be `spec/blog/user_spec.rb`. ([@backus][])
## 1.12.0 (2017-02-21)
* Add `RSpec/InstanceSpy` cop. ([@Darhazer][])
* Add `RSpec/BeforeAfterAll` for avoiding leaky global test setup. ([@cfabianski][])
## 1.11.0 (2017-02-16)
* Add `AroundBlock` cop. ([@Darhazer][])
* Add `EnforcedStyle` configuration for `RSpec/DescribedClass` cop. ([@Darhazer][])
* Fix false positive for `RSpec/RepeatedExample` cop. ([@redross][])
## 1.10.0 (2017-01-15)
* Fix false negative for `RSpec/MessageSpies` cop. ([@onk][])
* Fix internal dependencies on RuboCop to be compatible with 0.47 release. ([@backus][])
* Add autocorrect support for `SingleArgumentMessageChain` cop. ([@bquorning][])
* Rename `NestedGroups`' configuration key from `MaxNesting` to `Max` in order to be consistent with other cop configuration. ([@backus][])
* Add `RepeatedExample` cop for detecting repeated examples within example groups. ([@backus][])
* Add `ScatteredSetup` cop for enforcing that only one `before`, `around`, and `after` hook are used per example group scope. ([@backus][])
* Add `ExpectOutput` cop for recommending `expect { ... }.to output(...).to_stdout`. ([@backus][])
## 1.9.1 (2017-01-02)
* Fix unintentional regression change in `NestedGroups` reported in #270. ([@backus][])
* Change `MaxNesting` for `NestedGroups` from 2 to 3. ([@backus][])
## 1.9.0 (2016-12-29)
* Add `MessageSpies` cop for enforcing consistent style of either `expect(...).to have_received` or `expect(...).to receive`, intended as a replacement for the `MessageExpectation` cop. ([@bquorning][])
* Fix `DescribeClass` to not flag `describe` at the top of a block of shared examples. ([@clupprich][])
* Add `SingleArgumentMessageChain` cop for recommending use of `receive` instead of `receive_message_chain` where possible. ([@bquorning][])
* Add `RepeatedDescription` cop for detecting repeated example descriptions within example groups. ([@backus][])
## 1.8.0 (2016-10-27)
* Optionally ignore method names in the `describe` argument when running the `FilePath` cop. ([@bquorning][])
* Fix regression in how `FilePath` converts alphanumeric class names into paths. ([@bquorning][])
* Add `ImplicitExpect` cop for enforcing `should` vs. `is_expected.to`. ([@backus][])
* Disable `MessageExpectation` cop in the default configuration. ([@bquorning][])
## 1.7.0 (2016-08-24)
* Add support for checking all example groups with `ExampleLength`. ([@backus][])
* Add support for checking shared example groups for `DescribedClass`. ([@backus][])
* Add support for checking `its` from [rspec-its](https://github.com/rspec/rspec-its). ([@backus][])
* Add `EmptyExampleGroup` cop for detecting `describe`s and `context`s without any tests inside. ([@backus][])
* Add `CustomIncludeMethods` configuration option for `EmptyExampleGroup`. ([@backus][])
* Add `NestedGroups` cop for detecting excessive example group nesting. ([@backus][])
* Add `MaxNesting` configuration option for `NestedGroups` cop. ([@backus][])
* Add `ExpectActual` cop for detecting literal values within `expect(...)`. ([@backus][])
* Add `MultipleExpectations` cop for detecting multiple `expect(...)` calls within one example. ([@backus][])
* Add `Max` configuration option for `MultipleExpectations`. ([@backus][])
* Add `SubjectStub` cop for testing stubbed test subjects. ([@backus][])
* Add `LetSetup` cop for detecting cases where `let!` is used for test setup. ([@backus][])
* Change all cops to only inspect files with names following rspec convention (`*/spec/*` and/or `_spec.rb`). ([@backus][])
* Add `AllCops/RSpec` configuration option for specifying custom spec file patterns. ([@backus][])
* Add `AssignmentOnly` configuration option for `RSpec/InstanceVariable` cop. ([@backus][])
* Add `BeEql` cop which looks for expectations that can use `be(...)` instead of `eql(...)`. ([@backus][])
* Add autocorrect support for `BeEql` cop. ([@backus][])
* Add `MessageExpectation` cop for enforcing consistent style of either `expect(...).to receive` or `allow(...).to receive`. ([@backus][])
* Add `MessageChain` cop. ([@bquorning][])
## 1.6.0 (2016-08-03)
* Add `SkipBlocks` option for `DescribedClass` cop. ([@backus][])
## 1.5.3 (2016-08-02)
* Add `RSpec/NamedSubject` cop. ([@backus][])
## 1.5.2 (2016-08-01)
* Drop support for ruby `2.0.0` and `2.1.0`. ([@backus][])
* Internal refactorings and improved test coverage. ([@backus][])
## 1.5.1 (2016-07-20)
* Fix `unrecognized parameter RSpec/VerifiedDoubles:IgnoreSymbolicNames` warning. ([@jeffreyc][])
* Update to rubocop 0.41.2. ([@backus][])
## 1.5.0 (2016-05-17)
* Expand `VerifiedDoubles` cop to check for `spy` as well as `double`. ([@andyw8][])
* Enable `VerifiedDoubles` cop by default. ([@andyw8][])
* Add `IgnoreSymbolicNames` option for `VerifiedDoubles` cop. ([@andyw8][])
* Add `RSpec::ExampleLength` cop. ([@andyw8][])
* Handle alphanumeric class names in `FilePath` cop. ([@andyw8][])
* Skip `DescribeClass` cop for view specs. ([@andyw8][])
* Skip `FilePath` cop for Rails routing specs. ([@andyw8][])
* Add cop to check for focused specs. ([@renanborgescampos][], [@jaredmoody][])
* Clean-up `RSpec::NotToNot` to use same configuration semantics as other Rubocop cops, add autocorrect support for `RSpec::NotToNot`. ([@baberthal][])
* Update to rubocop 0.40.0. ([@nijikon][])
## 1.4.1 (2016-04-03)
* Ignore routing specs for DescribeClass cop. ([@nijikon][])
* Move rubocop dependency to runtime. ([@nijikon][])
* Update to rubocop 0.39.0. ([@nijikon][])
## 1.4.0 (2016-02-15)
* Update to rubocop 0.37.2. ([@nijikon][])
* Update ruby versions we test against. ([@nijikon][])
* Add `RSpec::NotToNot` cop. ([@miguelfteixeira][])
* Add `Rspec/AnyInstance` cop. ([@mlarraz][])
## 1.3.1
* Fix auto correction issue - syntax had changed in RuboCop v0.31. ([@bquorning][])
* Add RuboCop clone to vendor folder - see #39 for details. ([@bquorning][])
## 1.3.0
* Ignore non string arguments for FilePathCop - thanks to @deivid-rodriguez. ([@geniou][])
* Skip DescribeMethod cop for tagged specs. ([@deivid-rodriguez][])
* Skip DescribeClass cop for feature/request specs. ([@deivid-rodriguez][])
## 1.2.2
* Make `RSpec::ExampleWording` case insensitive. ([@geniou][])
## 1.2.1
* Add `RSpec::VerifiedDoubles` cop. ([@andyw8][])
## 1.2.0
* Drop support of ruby `1.9.2`. ([@geniou][])
* Update to RuboCop `~> 0.24`. ([@geniou][])
* Add `autocorrect` to `RSpec::ExampleWording`. This experimental - use with care and check the changes. ([@geniou][])
* Fix config loader debug output. ([@geniou][])
* Rename `FileName` cop to `FilePath` as a workaround - see [#19](https://github.com/nevir/rubocop-rspec/issues/19). ([@geniou][])
## 1.1.0
* Add `autocorrect` to `RSpec::DescribedClass` cop. ([@geniou][])
## 1.0.1
* Add `config` folder to gemspec. ([@pstengel][])
## 1.0.rc3
* Update to RuboCop `>= 0.23`. ([@geniou][])
* Add configuration option for `CustomTransformation` to `FileName` cop. ([@geniou][])
## 1.0.rc2
* Gem is no longer 20MB (sorry!). ([@nevir][])
* `RspecFileName` cop allows for method specs to organized into directories by class and type. ([@nevir][])
## 1.0.rc1
* Update code to work with rubocop `>= 0.19`. ([@geniou][])
* Split `UnitSpecNaming` cop into `RSpecDescribeClass`, `RSpecDescribeMethod` and `RSpecFileName` and enabled them all by default. ([@geniou][])
* Add `RSpecExampleWording` cop to prevent to use of should at the beginning of the spec description. ([@geniou][])
* Fix `RSpecFileName` cop for non-class specs. ([@geniou][])
* Adapt `RSpecFileName` cop to commen naming convention and skip spec with multiple top level describes. ([@geniou][])
* Add `RSpecMultipleDescribes` cop to check for multiple top level describes. ([@geniou][])
* Add `RSpecDescribedClass` to promote the use of `described_class`. ([@geniou][])
* Add `RSpecInstanceVariable` cop to check for the usage of instance variables. ([@geniou][])
<!-- Contributors -->
[@andyw8]: https://github.com/andyw8
[@backus]: https://github.com/backus
[@bquorning]: https://github.com/bquorning
[@deivid-rodriguez]: https://github.com/deivid-rodriguez
[@geniou]: https://github.com/geniou
[@jaredbeck]: https://github.com/jaredbeck
[@jawshooah]: https://github.com/jawshooah
[@nevir]: https://github.com/nevir
[@nijikon]: https://github.com/nijikon
[@pstengel]: https://github.com/pstengel
[@miguelfteixeira]: https://github.com/miguelfteixeira
[@mlarraz]: https://github.com/mlarraz
[@renanborgescampos]: https://github.com/renanborgescampos
[@jaredmoody]: https://github.com/jaredmoody
[@baberthal]: https://github.com/baberthal
[@jeffreyc]: https://github.com/jeffreyc
[@clupprich]: https://github.com/clupprich
[@onk]: https://github.com/onk
[@Darhazer]: https://github.com/Darhazer
[@redross]: https://github.com/redross
[@cfabianski]: https://github.com/cfabianski
[@dgollahon]: https://github.com/dgollahon
[@rspeicher]: https://github.com/rspeicher
[@jonatas]: https://github.com/jonatas
[@pocke]: https://github.com/pocke
[@bmorrall]: https:/github.com/bmorrall
[@zverok]: https:/github.com/zverok
[@timrogers]: https://github.com/timrogers
[@yevhene]: https://github.com/yevhene
[@walf443]: https://github.com/walf443
[@pirj]: https://github.com/pirj
[@telmofcosta]: https://github.com/telmofcosta
[@EliseFitz15]: https://github.com/EliseFitz15
[@anthony-robin]: https://github.com/anthony-robin
[@jojos003]: https://github.com/jojos003
[@abrom]: https://github.com/abrom
[@patrickomatic]: https://github.com/patrickomatic
[@tdeo]: https://github.com/tdeo
[@composerinteralia]: https://github.com/composerinteralia
[@seanpdoyle]: https://github.com/seanpdoyle
[@vzvu3k6k]: https://github.com/vzvu3k6k
[@BrentWheeldon]: https://github.com/BrentWheeldon
[@daveworth]: https://github.com/daveworth

View File

@ -0,0 +1,9 @@
source 'https://rubygems.org'
gemspec
local_gemfile = 'Gemfile.local'
if File.exist?(local_gemfile)
eval(File.read(local_gemfile)) # rubocop:disable Security/Eval
end

View File

@ -0,0 +1,22 @@
The MIT License (MIT)
=====================
Copyright (c) 2014 Ian MacLeod <ian@nevir.net>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,146 @@
# RuboCop RSpec
[![Join the chat at https://gitter.im/rubocop-rspec/Lobby](https://badges.gitter.im/rubocop-rspec/Lobby.svg)](https://gitter.im/rubocop-rspec/Lobby)
[![Gem Version](https://badge.fury.io/rb/rubocop-rspec.svg)](https://rubygems.org/gems/rubocop-rspec)
[![CircleCI](https://circleci.com/gh/rubocop-hq/rubocop-rspec.svg?style=svg)](https://circleci.com/gh/rubocop-hq/rubocop-rspec)
[![Test Coverage](https://api.codeclimate.com/v1/badges/8ffaabf633c968c22bdd/test_coverage)](https://codeclimate.com/github/rubocop-hq/rubocop-rspec/test_coverage)
[![Maintainability](https://api.codeclimate.com/v1/badges/8ffaabf633c968c22bdd/maintainability)](https://codeclimate.com/github/rubocop-hq/rubocop-rspec/maintainability)
RSpec-specific analysis for your projects, as an extension to
[RuboCop](https://github.com/rubocop-hq/rubocop).
## Installation
Just install the `rubocop-rspec` gem
```bash
gem install rubocop-rspec
```
or if you use bundler put this in your `Gemfile`
```
gem 'rubocop-rspec'
```
## Usage
You need to tell RuboCop to load the RSpec extension. There are three
ways to do this:
### RuboCop configuration file
Put this into your `.rubocop.yml`.
```
require: rubocop-rspec
```
Now you can run `rubocop` and it will automatically load the RuboCop RSpec
cops together with the standard cops.
### Command line
```bash
rubocop --require rubocop-rspec
```
### Rake task
```ruby
RuboCop::RakeTask.new do |task|
task.requires << 'rubocop-rspec'
end
```
### Code Climate
rubocop-rspec is available on Code Climate as part of the rubocop engine. [Learn More](https://codeclimate.com/changelog/55a433bbe30ba00852000fac).
## Documentation
You can read more about RuboCop-RSpec in its [official manual](http://rubocop-rspec.readthedocs.io).
## Inspecting files that don't end with `_spec.rb`
By default, `rubocop-rspec` only inspects code within paths ending in `_spec.rb` or including `spec/`. You can override this setting in your config file by specifying one or more patterns:
```yaml
# Inspect all files
AllCops:
RSpec:
Patterns:
- '.+'
```
```yaml
# Inspect only files ending with `_test.rb`
AllCops:
RSpec:
Patterns:
- '_test.rb$'
```
## The Cops
All cops are located under
[`lib/rubocop/cop/rspec`](lib/rubocop/cop/rspec), and contain
examples/documentation.
In your `.rubocop.yml`, you may treat the RSpec cops just like any other
cop. For example:
```yaml
RSpec/FilePath:
Exclude:
- spec/my_poorly_named_spec_file.rb
```
## Non-goals of RuboCop RSpec
### Enforcing `should` vs. `expect` syntax
Enforcing
```ruby
expect(calculator.compute(line_item)).to eq(5)
```
over
```ruby
calculator.compute(line_item).should == 5
```
is a feature of RSpec itself you can read about it in the [RSpec Documentation](https://relishapp.com/rspec/rspec-expectations/docs/syntax-configuration#disable-should-syntax)
### Enforcing an explicit RSpec receiver for top-level methods (disabling monkey patching)
Enforcing
```ruby
Rspec.describe MyClass do
...
end
```
over
```ruby
describe MyClass do
...
end
```
can be achieved using RSpec's `disable_monkey_patching!` method, which you can read more about in the [RSpec Documentation](https://relishapp.com/rspec/rspec-core/v/3-7/docs/configuration/zero-monkey-patching-mode#monkey-patched-methods-are-undefined-with-%60disable-monkey-patching!%60). This will also prevent `should` from being defined on every object in your system.
Before disabling `should` you will need all your specs to use the `expect` syntax. You can use [Transpec](http://yujinakayama.me/transpec/), which will do the conversion for you.
## Contributing
Checkout the [contribution guidelines](.github/CONTRIBUTING.md).
## License
`rubocop-rspec` is MIT licensed. [See the accompanying file](MIT-LICENSE.md) for
the full text.

View File

@ -0,0 +1,85 @@
require 'open3'
require 'bundler'
require 'bundler/gem_tasks'
begin
Bundler.setup(:default, :development)
rescue Bundler::BundlerError => e
warn e.message
warn 'Run `bundle install` to install missing gems'
exit e.status_code
end
require 'rspec/core/rake_task'
Dir['tasks/**/*.rake'].each { |t| load t }
RSpec::Core::RakeTask.new(:spec) do |spec|
spec.pattern = FileList['spec/**/*_spec.rb']
end
desc 'Run RSpec with code coverage'
task :coverage do
ENV['COVERAGE'] = 'true'
Rake::Task['spec'].execute
end
desc 'Run RuboCop over this gem'
task :internal_investigation do
sh('bundle exec rubocop --require rubocop-rspec')
end
desc 'Build config/default.yml'
task :build_config do
sh('bin/build_config')
end
desc 'Confirm config/default.yml is up to date'
task confirm_config: :build_config do
_, stdout, _, process =
Open3.popen3('git diff --exit-code config/default.yml')
unless process.value.success?
raise "default.yml is out of sync:\n\n#{stdout.read}\nRun bin/build_config"
end
end
desc 'Confirm documentation is up to date'
task confirm_documentation: :generate_cops_documentation do
_, _, _, process =
Open3.popen3('git diff --exit-code manual/')
unless process.value.success?
raise 'Please run `rake generate_cops_documentation` ' \
'and add manual/ to the commit.'
end
end
task default: %i[build_config coverage
internal_investigation
confirm_config
documentation_syntax_check
confirm_documentation]
desc 'Generate a new cop template'
task :new_cop, [:cop] do |_task, args|
require 'rubocop'
cop_name = args.fetch(:cop) do
warn 'usage: bundle exec rake new_cop[Department/Name]'
exit!
end
github_user = `git config github.user`.chop
github_user = 'your_id' if github_user.empty?
generator = RuboCop::Cop::Generator.new(cop_name, github_user)
generator.write_source
generator.write_spec
generator.inject_require(root_file_path: 'lib/rubocop/cop/rspec_cops.rb')
generator.inject_config(config_file_path: 'config/default.yml')
puts generator.todo
end

View File

@ -33,8 +33,8 @@ module RuboCop
MSG_SHOULD = 'Do not use should when describing your tests.'.freeze
MSG_IT = "Do not repeat 'it' when describing your tests.".freeze
SHOULD_PREFIX = /\Ashould(?:n't)?\b/i
IT_PREFIX = /\Ait /i
SHOULD_PREFIX = /\Ashould(?:n't)?\b/i.freeze
IT_PREFIX = /\Ait /i.freeze
def_node_matcher(
:it_description,

View File

@ -30,9 +30,10 @@ module RuboCop
MSG_CREATE_LIST = 'Prefer create_list.'.freeze
MSG_N_TIMES = 'Prefer %<number>s.times.'.freeze
def_node_matcher :n_times_block?, <<-PATTERN
def_node_matcher :n_times_block_without_arg?, <<-PATTERN
(block
(send (int _) :times)
(args)
...
)
PATTERN
@ -47,7 +48,7 @@ module RuboCop
def on_block(node)
return unless style == :create_list
return unless n_times_block?(node)
return unless n_times_block_without_arg?(node)
return unless contains_only_factory?(node.body)
add_offense(node.send_node,

Some files were not shown because too many files have changed in this diff Show More