relnotes/v1.88.0.md
Recursive option to Style/MutableConstant. When enabled, the cop checks and freezes mutable literals nested inside arrays and hashes. The option is disabled by default to preserve existing behavior. (@paracycle)Lint/RedundantSplatExpansion when splatting an empty literal (e.g. when *[] or rescue *[]), which expanded to invalid or semantically different code. (@bbatsov)Lint/RegexpAsCondition when the regexp literal is negated (e.g. if !/foo/), which inverted the condition. (@bbatsov)Lint/SymbolConversion when the receiver is an interpolated string containing an embedded double quote (e.g. "foo#{bar}\"qux".to_sym), which produced a syntax error. (@bbatsov)Style/CombinableLoops when a for loop has an empty body, and stop autocorrecting consecutive for loops whose iteration variables differ (which produced code referencing an undefined variable). (@bbatsov)Style/ConstantVisibility when a visibility declaration has a numeric literal argument (e.g. private_constant 42). (@bbatsov)Lint/OrderedMagicComments when an encoding magic comment is preceded by a magic comment other than frozen_string_literal (e.g. shareable_constant_value). (@bbatsov)Lint/RedundantWithIndex when the block takes no arguments (e.g. ary.each_with_index { do_something }). (@bbatsov)Lint/RequireRelativeSelfPath when requiring the current file by name with its extension (e.g. require_relative 'foo.rb') and the file path is absolute. (@bbatsov)Lint/SafeNavigationChain when an ordinary method is chained after a parenthesized safe navigation call (e.g. (x&.foo).bar). (@bbatsov)Lint/SafeNavigationWithEmpty when the receiver of &.empty? is a local variable, instance variable, constant, or other non-method-call expression. (@bbatsov)Lint/SendWithMixinArgument when send/public_send/__send__ is called with no explicit receiver or with a self receiver (e.g. send(:include, Bar)). (@bbatsov)Lint/ToEnumArguments when more positional arguments are passed than the method accepts (e.g. def m(x); to_enum(:m, x, extra); end), which raises ArgumentError when the enumerator is used. (@bbatsov)Lint/UnescapedBracketInRegexp when an unescaped ] is preceded by an escaped backslash (e.g. /abc\\]123/). (@bbatsov)Style/ArrayIntersectWithSingleElement with a splat argument (e.g. array.intersect?([*foo])), which is not a single element and was incorrectly rewritten to array.include?(*foo). (@bbatsov)Style/ColonMethodCall with chained JRuby interop calls (e.g. Java::com::something_method). (@bbatsov)Style/ConditionalAssignment with EnforcedStyle: assign_inside_condition when assigning an unless without an else branch (e.g. x = unless cond; 1; end), which was rewritten to move the assignment inside the unless and changed behavior when the condition was true. (@bbatsov)Layout/BlockAlignment with EnforcedStyleAlignWith: start_of_line when a block is passed as a method argument. (@augustocbx)Lint/RaiseException when raise Exception is used inside a module nested within an allowed implicit namespace (e.g. Gem). (@bbatsov)Lint/RedundantDirGlobSort when sort is given a comparator block or a block-pass argument, which is not redundant with the default sorting. (@bbatsov)Lint/ShadowingOuterLocalVariable when a block argument has the same name as a pattern variable from a different in branch of the same case. (@bbatsov)Lint/SuppressedExceptionInNumberConversion when the numeric constructor already passes exception: false (e.g. Integer(arg, exception: false) rescue nil), which also produced an autocorrect with a duplicate exception: false keyword. (@bbatsov)Lint/TopLevelReturnWithArgument when a return with an argument is inside a numbered-parameter block or an it block. (@bbatsov)Lint/UselessRuby2Keywords when ruby2_keywords in a nested class or module refers to a method of the same name defined in an outer scope. (@bbatsov)Lint/UselessSetterCall when a multiple assignment uses nested destructuring (e.g. (a, b), c = arg, other_arg), which misaligned variables with the right-hand side values. (@bbatsov)Style/ZeroLengthPredicate when File::Stat.new(...).size.zero? is used. (@augustocbx)--start-server to wait until the server is running before returning, which fixes a flaky --restart-server spec and a race for commands run right after starting the server. (@koic)Style/Alias not detecting block scope for numbered-parameter and it blocks, which caused a false positive for alias_method and a false negative for alias inside such blocks. (@bbatsov)Style/IfUnlessModifier and Style/Next correct the same conditional. (@fynsta)Style/FileWrite when a literal or variable is passed to write in the block form. (@koic)Style/RedundantFormat when the format string is a heredoc with format arguments. (@fynsta)Style/AndOr when an operand is next, break, or yield with an argument (e.g. foo and next 1), which produced invalid Ruby like foo && next 1. (@bbatsov)Style/ArrayFirstLast when arr[0]/arr[-1] is the target of a compound assignment (e.g. arr[0] += 1), which produced arr.first += 1 and raised NoMethodError. (@bbatsov)Style/ArrayIntersect where a negated predicate on a safe-navigation chain (e.g. a&.intersection(b)&.none?) was rewritten to !a&.intersect?(b), flipping the result when the receiver is nil. (@bbatsov)Style/BlockDelimiters that converted a single-line do...end block containing a block-level rescue or ensure to {...}, producing invalid Ruby. (@bbatsov)Style/CaseEquality when the argument is an operator or unary expression (e.g. Array === a + b), which produced mis-parsed code like a + b.is_a?(Array). (@bbatsov)Style/ClassEqualityComparison inside a namespace when the class name string is already fully qualified (e.g. bar.class.name == '::Bar'), which produced instance_of?(::::Bar) and was a syntax error. (@bbatsov)Style/ClassEqualityComparison when comparing Class itself to a string literal (e.g. var.class == 'Date'), which produced var.instance_of?('Date') and raised TypeError; such comparisons are no longer autocorrected. (@bbatsov)Style/ClassMethodsDefinitions that corrupted a preceding comment containing def <name> and left the method undefined as a class method. (@bbatsov)Style/ComparableClamp when the clamped value is an operator expression (e.g. a + b), which produced mis-parsed code like a + b.clamp(low, high). (@bbatsov)Style/ConcatArrayLiterals with an empty array literal argument (e.g. arr.concat([], [b])), which produced invalid Ruby like arr.push(, b). (@bbatsov)Style/DigChain that duplicated a trailing comment and dropped indentation when the chain was inside a method or block. (@bbatsov)Lint/UselessTimes when a 1.times block takes a single destructured (|(a, b)|) or splat (|*a|) argument, which produced a body referencing an undefined variable. (@bbatsov)Style/ConditionalAssignment with EnforcedStyle: assign_inside_condition and a single-line case. (@fynsta)Style/ParallelAssignment when the right-hand side contains a heredoc. (@fynsta)Style/Semicolon when a heredoc is opened before the semicolon. (@fynsta)Style/WordArray when the array contains heredocs. (@fynsta)Lint/UselessAssignment that rewrote a first-seen foo &&= 1 to foo && 1, raising NameError at runtime. (@bbatsov)Include pattern could match directories above the project root. (@augustocbx)Lint/InterpolationCheck when interpolation appears in a multiline single-quoted string. (@bbatsov)Lint/NonLocalExitFromIterator when the iterator receiver uses safe navigation. (@bbatsov)Lint/RedundantSafeNavigation with &.respond_to? on a guaranteed-instance receiver (e.g. foo.to_s&.respond_to?(:class)) and with &.to_h using a numbered-parameter or it block (e.g. foo&.to_h { _1 } || {}). (@bbatsov)Lint/RescueType when rescuing from true, false, a rational literal (1r), or a complex literal (1i), all of which raise a TypeError at runtime. (@bbatsov)Lint/SelfAssignment with ||= and &&= on constants, attributes, and hash keys (e.g. Foo ||= Foo, foo.bar ||= foo.bar, hash['foo'] ||= hash['foo']). (@bbatsov)Lint/SharedMutableDefault when a mutable default is combined with a capacity: keyword argument and given as an array or Array.new/Hash.new (e.g. Hash.new([], capacity: 42)). (@bbatsov)Lint/FloatComparison when comparing against a parenthesized zero or nil. (@bbatsov)Lint/IncompatibleIoSelectWithFiberScheduler when the single array argument element is a splat. (@bbatsov)Lint/LiteralAssignmentInCondition when a literal is assigned inside a block in the condition. (@bbatsov)Style/DateTime: a bare to_datetime call on implicit self is no longer flagged, and historic-date calls using safe navigation (e.g. DateTime&.iso8601(str, Date::ENGLAND)) are now exempted. (@bbatsov)Layout/BlockAlignment when there is a line break between method arguments before the block. (@koic)Lint/EnsureReturn and Lint/NoReturnInBeginEndBlocks for return inside a nested method definition or lambda. (@bbatsov)Style/WhileUntilDo when the loop body is on the same line as the do keyword. (@koic)Lint/ErbNewArguments when a keyword argument follows the safe_level argument. (@bbatsov)Lint/LambdaWithoutLiteralBlock that dropped safe navigation from the block argument. (@bbatsov)Lint/NumericOperationWithConstantResult when using safe navigation, as the result is nil when the receiver is nil. (@bbatsov)Lint/RedundantCopDisableDirective and Lint/RedundantCopEnableDirective when a cop name in the directive is a prefix of another cop name in the same directive (e.g. Lint/AmbiguousOperator and Lint/AmbiguousOperatorPrecedence). (@bbatsov)Style/FileWrite that deleted or duplicated heredoc bodies when a heredoc was used as the filename, in an argument expression, or in an inline block. (@fynsta)Lint/UselessTimes when the times block uses next/break (which became a syntax error) or takes multiple block arguments (which became undefined references). (@bbatsov)Lint/ScriptPermission to honor a cop-level AutoCorrect: false setting and to not crash on sources without a file on disk (e.g. unsaved editor buffers). (@bbatsov)Lint/TrailingCommaInAttributeDeclaration to detect a trailing comma before a singleton method definition (e.g. def self.bar) and to not crash when a def is the sole argument (e.g. attr_reader def bar; end). (@bbatsov)Lint/LiteralInInterpolation with embedded quotes and escaped interpolation text. (@RedZapdos123)Lint/LiteralInInterpolation when interpolated hashes contain symbols that require quoted syntax, such as :'foo-bar'. (@RedZapdos123).rubocop_todo.yml autocorrect safety comments for local custom cops configured in the project config. (@RedZapdos123)Lint/NumberConversion offenses on safe navigation calls. (@RedZapdos123)--auto-gen-config to record --disable-pending-cops and --enable-pending-cops in the generated .rubocop_todo.yml command so that --regenerate-todo preserves them. (@augustocbx)InternalAffairs/RedundantLetRuboCopConfigNew crash when let(:config) has no enclosing describe. (@bbatsov)Lint/RequireRangeParentheses offense message, which incorrectly called the flagged (finite) range "endless". (@bbatsov)Lint/RefinementImportMethods (replacing include/prepend with import_methods) and report that the functionality was removed (not just deprecated) on Ruby 3.2+. (@bbatsov)Lint/UnreachableCode, Metrics/AbcSize, Security/Eval) for consistency. (@bbatsov)Lint/RedundantWithObject autocorrect unsafe, since each_with_object returns the memo object while the corrected each returns the receiver. (@bbatsov)Bundler/GemComment's IgnoredGems to AllowedGems, Lint/NumberConversion's IgnoredClasses to AllowedClasses, Lint/MissingCopEnableDirective's MaximumRangeSize to MaxRangeSize, Metrics/CollectionLiteralLength's LengthThreshold to Max, and Style/FetchEnvVar's AllowedVars to AllowedVariables. (@bbatsov)