Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new
Performance/OpenStruct
cop (#6486)
Add new `Performance/OpenStruct` cop which checks for `OpenStruct.new` calls. The suggested way to fix this issue is to replace `OpenStruct`s with static `Struct`s. The cop is disabled by default.
- Loading branch information
Showing
7 changed files
with
111 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Performance | ||
# This cop checks for `OpenStruct.new` calls. | ||
# Instantiation of an `OpenStruct` invalidates | ||
# Ruby global method cache as it causes dynamic method | ||
# definition during program runtime. | ||
# This could have an effect on performance, | ||
# especially in case of single-threaded | ||
# applications with multiple `OpenStruct` instantiations. | ||
|
||
# @example | ||
# # bad | ||
# class MyClass | ||
# def my_method | ||
# OpenStruct.new(my_key1: 'my_value1', my_key2: 'my_value2') | ||
# end | ||
# end | ||
# | ||
# # good | ||
# class MyClass | ||
# MyStruct = Struct.new(:my_key1, :my_key2) | ||
# def my_method | ||
# MyStruct.new('my_value1', 'my_value2') | ||
# end | ||
# end | ||
# | ||
class OpenStruct < Cop | ||
MSG = 'Consider using `Struct` over `OpenStruct` ' \ | ||
'to optimize the performance.'.freeze | ||
|
||
def_node_matcher :open_struct, <<-PATTERN | ||
(send (const {nil? cbase} :OpenStruct) :new ...) | ||
PATTERN | ||
|
||
def on_send(node) | ||
open_struct(node) do |method| | ||
add_offense(node, location: :selector, message: format(MSG, method)) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Performance::OpenStruct do | ||
subject(:cop) { described_class.new(config) } | ||
|
||
let(:config) { RuboCop::Config.new } | ||
|
||
it 'registers an offense for OpenStruct.new' do | ||
expect_offense(<<-RUBY.strip_indent) | ||
OpenStruct.new(key: "value") | ||
^^^ Consider using `Struct` over `OpenStruct` to optimize the performance. | ||
RUBY | ||
end | ||
|
||
it 'registers an offense for a fully qualified ::OpenStruct.new' do | ||
expect_offense(<<-RUBY.strip_indent) | ||
::OpenStruct.new(key: "value") | ||
^^^ Consider using `Struct` over `OpenStruct` to optimize the performance. | ||
RUBY | ||
end | ||
|
||
it 'does not register offense for Struct' do | ||
expect_no_offenses(<<-RUBY.strip_indent) | ||
MyStruct = Struct.new(:key) | ||
MyStruct.new('value') | ||
RUBY | ||
end | ||
end |
c74c199
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why it is disabled by default? https://github.com/rubocop-hq/rubocop/blob/master/config/default.yml typically lists what is problematic with cops (even one enabled by default).
I considered enabling this one, but as I don't understand potential danger I kept it disabled.