rubocop-sketchup 1.2.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +20 -19
  3. data/assets/output.html.erb +301 -301
  4. data/config/default.yml +379 -379
  5. data/lib/rubocop/sketchup/config.rb +63 -63
  6. data/lib/rubocop/sketchup/cop/bugs/material_name.rb +108 -108
  7. data/lib/rubocop/sketchup/cop/bugs/render_mode.rb +72 -72
  8. data/lib/rubocop/sketchup/cop/bugs/uniform_scaling.rb +36 -36
  9. data/lib/rubocop/sketchup/cop/deprecations/add_separator_to_menu.rb +25 -25
  10. data/lib/rubocop/sketchup/cop/deprecations/operation_next_transparent.rb +30 -30
  11. data/lib/rubocop/sketchup/cop/deprecations/require_all.rb +27 -27
  12. data/lib/rubocop/sketchup/cop/deprecations/set_texture_projection.rb +26 -26
  13. data/lib/rubocop/sketchup/cop/deprecations/show_ruby_panel.rb +25 -25
  14. data/lib/rubocop/sketchup/cop/deprecations/sketchup_set.rb +30 -30
  15. data/lib/rubocop/sketchup/cop/performance/openssl.rb +41 -41
  16. data/lib/rubocop/sketchup/cop/performance/operation_disable_ui.rb +33 -33
  17. data/lib/rubocop/sketchup/cop/performance/selection_bulk.rb +79 -79
  18. data/lib/rubocop/sketchup/cop/performance/type_check.rb +63 -63
  19. data/lib/rubocop/sketchup/cop/performance/typename.rb +24 -24
  20. data/lib/rubocop/sketchup/cop/requirements/api_namespace.rb +30 -30
  21. data/lib/rubocop/sketchup/cop/requirements/exit.rb +33 -33
  22. data/lib/rubocop/sketchup/cop/requirements/extension_namespace.rb +125 -125
  23. data/lib/rubocop/sketchup/cop/requirements/file_structure.rb +97 -97
  24. data/lib/rubocop/sketchup/cop/requirements/gem_install.rb +45 -45
  25. data/lib/rubocop/sketchup/cop/requirements/get_extension_license.rb +95 -95
  26. data/lib/rubocop/sketchup/cop/requirements/global_constants.rb +38 -38
  27. data/lib/rubocop/sketchup/cop/requirements/global_include.rb +42 -42
  28. data/lib/rubocop/sketchup/cop/requirements/global_methods.rb +65 -65
  29. data/lib/rubocop/sketchup/cop/requirements/global_variables.rb +95 -95
  30. data/lib/rubocop/sketchup/cop/requirements/language_handler_globals.rb +46 -46
  31. data/lib/rubocop/sketchup/cop/requirements/load_path.rb +83 -83
  32. data/lib/rubocop/sketchup/cop/requirements/minimal_registration.rb +73 -73
  33. data/lib/rubocop/sketchup/cop/requirements/observers_start_operation.rb +161 -161
  34. data/lib/rubocop/sketchup/cop/requirements/register_extension.rb +45 -45
  35. data/lib/rubocop/sketchup/cop/requirements/ruby_core_namespace.rb +291 -291
  36. data/lib/rubocop/sketchup/cop/requirements/ruby_stdlib_namespace.rb +634 -634
  37. data/lib/rubocop/sketchup/cop/requirements/shipped_extensions_namespace.rb +61 -61
  38. data/lib/rubocop/sketchup/cop/requirements/sketchup_extension.rb +119 -119
  39. data/lib/rubocop/sketchup/cop/requirements/sketchup_require.rb +150 -149
  40. data/lib/rubocop/sketchup/cop/suggestions/add_group.rb +49 -49
  41. data/lib/rubocop/sketchup/cop/suggestions/compatibility.rb +128 -128
  42. data/lib/rubocop/sketchup/cop/suggestions/dc_internals.rb +34 -34
  43. data/lib/rubocop/sketchup/cop/suggestions/file_encoding.rb +78 -78
  44. data/lib/rubocop/sketchup/cop/suggestions/model_entities.rb +58 -58
  45. data/lib/rubocop/sketchup/cop/suggestions/monkey_patched_api.rb +45 -45
  46. data/lib/rubocop/sketchup/cop/suggestions/operation_name.rb +137 -137
  47. data/lib/rubocop/sketchup/cop/suggestions/sketchup_find_support_file.rb +39 -39
  48. data/lib/rubocop/sketchup/cop/suggestions/tool_drawing_bounds.rb +45 -45
  49. data/lib/rubocop/sketchup/cop/suggestions/tool_invalidate.rb +68 -68
  50. data/lib/rubocop/sketchup/cop/suggestions/tool_user_input.rb +41 -41
  51. data/lib/rubocop/sketchup/cop/suggestions/toolbar_timer.rb +65 -65
  52. data/lib/rubocop/sketchup/cop.rb +110 -110
  53. data/lib/rubocop/sketchup/dc_globals.rb +24 -24
  54. data/lib/rubocop/sketchup/dc_methods.rb +130 -130
  55. data/lib/rubocop/sketchup/extension_project.rb +65 -65
  56. data/lib/rubocop/sketchup/features.rb +1477 -1420
  57. data/lib/rubocop/sketchup/formatter/extension_review.rb +269 -269
  58. data/lib/rubocop/sketchup/inject.rb +19 -19
  59. data/lib/rubocop/sketchup/namespace.rb +49 -49
  60. data/lib/rubocop/sketchup/namespace_checker.rb +103 -46
  61. data/lib/rubocop/sketchup/no_comment_disable.rb +17 -17
  62. data/lib/rubocop/sketchup/range_help.rb +52 -52
  63. data/lib/rubocop/sketchup/sketchup_target_range.rb +75 -75
  64. data/lib/rubocop/sketchup/sketchup_version.rb +129 -128
  65. data/lib/rubocop/sketchup/tool_checker.rb +41 -43
  66. data/lib/rubocop/sketchup/version.rb +7 -7
  67. data/lib/rubocop/sketchup.rb +14 -14
  68. data/lib/rubocop-sketchup.rb +53 -53
  69. data/rubocop-sketchup.gemspec +29 -29
  70. metadata +8 -8
@@ -1,27 +1,27 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module SketchupDeprecations
6
- # Method is deprecated because it adds the given path to `$LOAD_PATH`.
7
- # Modifying `$LOAD_PATH` is bad practice because it can cause extensions
8
- # to inadvertently load the wrong file.
9
- class RequireAll < SketchUp::Cop
10
-
11
- MSG = 'Method is deprecated because it adds the given path '\
12
- 'to $LOAD_PATH.'
13
-
14
- def_node_matcher :require_all?, <<-PATTERN
15
- (send nil? :require_all _)
16
- PATTERN
17
-
18
- def on_send(node)
19
- return unless require_all?(node)
20
-
21
- add_offense(node, location: :selector)
22
- end
23
-
24
- end
25
- end
26
- end
27
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupDeprecations
6
+ # Method is deprecated because it adds the given path to `$LOAD_PATH`.
7
+ # Modifying `$LOAD_PATH` is bad practice because it can cause extensions
8
+ # to inadvertently load the wrong file.
9
+ class RequireAll < SketchUp::Cop
10
+
11
+ MSG = 'Method is deprecated because it adds the given path ' \
12
+ 'to $LOAD_PATH.'
13
+
14
+ def_node_matcher :require_all?, <<-PATTERN
15
+ (send nil? :require_all _)
16
+ PATTERN
17
+
18
+ def on_send(node)
19
+ return unless require_all?(node)
20
+
21
+ add_offense(node, location: :selector)
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,26 +1,26 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module SketchupDeprecations
6
- # Method is deprecated because it creates invalid UV mapping. Saving the
7
- # model will display a dialog indicating that the model needs to be
8
- # repaired. Once repaired the UV mapping will visually change.
9
- class SetTextureProjection < SketchUp::Cop
10
-
11
- MSG = 'Method is deprecated. It can create invalid UV mapping.'
12
-
13
- def_node_matcher :set_texture_projection?, <<-PATTERN
14
- (send _ :set_texture_projection ...)
15
- PATTERN
16
-
17
- def on_send(node)
18
- return unless set_texture_projection?(node)
19
-
20
- add_offense(node, location: :selector)
21
- end
22
-
23
- end
24
- end
25
- end
26
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupDeprecations
6
+ # Method is deprecated because it creates invalid UV mapping. Saving the
7
+ # model will display a dialog indicating that the model needs to be
8
+ # repaired. Once repaired the UV mapping will visually change.
9
+ class SetTextureProjection < SketchUp::Cop
10
+
11
+ MSG = 'Method is deprecated. It can create invalid UV mapping.'
12
+
13
+ def_node_matcher :set_texture_projection?, <<-PATTERN
14
+ (send _ :set_texture_projection ...)
15
+ PATTERN
16
+
17
+ def on_send(node)
18
+ return unless set_texture_projection?(node)
19
+
20
+ add_offense(node, location: :selector)
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,25 +1,25 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module SketchupDeprecations
6
- # Method is deprecated. Use `SKETCHUP_CONSOLE.show` instead.
7
- class ShowRubyPanel < SketchUp::Cop
8
-
9
- MSG = 'Method is deprecated. Use `SKETCHUP_CONSOLE.show` '\
10
- 'instead.'
11
-
12
- def_node_matcher :show_ruby_panel?, <<-PATTERN
13
- (send nil? :show_ruby_panel)
14
- PATTERN
15
-
16
- def on_send(node)
17
- return unless show_ruby_panel?(node)
18
-
19
- add_offense(node, location: :expression)
20
- end
21
-
22
- end
23
- end
24
- end
25
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupDeprecations
6
+ # Method is deprecated. Use `SKETCHUP_CONSOLE.show` instead.
7
+ class ShowRubyPanel < SketchUp::Cop
8
+
9
+ MSG = 'Method is deprecated. Use `SKETCHUP_CONSOLE.show` ' \
10
+ 'instead.'
11
+
12
+ def_node_matcher :show_ruby_panel?, <<-PATTERN
13
+ (send nil? :show_ruby_panel)
14
+ PATTERN
15
+
16
+ def on_send(node)
17
+ return unless show_ruby_panel?(node)
18
+
19
+ add_offense(node, location: :expression)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,30 +1,30 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module SketchupDeprecations
6
- # From SketchUp 6 until SketchUp 2013 the SketchUp API shipped with a
7
- # `Set` class. When SketchUp started shipping with the Ruby StdLib in
8
- # SketchUp 2014 the class was changed from `Set` to `Sketchup::Set` in
9
- # order to avoid conflict with the Ruby Standard Library.
10
- #
11
- # The `Sketchup::Set` class is much slower than Ruby's own `Set` class
12
- # and less versatile.
13
- class SketchupSet < SketchUp::Cop
14
-
15
- MSG = 'Class is deprecated.'
16
-
17
- def_node_matcher :sketchup_set?, <<-PATTERN
18
- (const (const nil? :Sketchup) :Set)
19
- PATTERN
20
-
21
- def on_const(node)
22
- return unless sketchup_set?(node)
23
-
24
- add_offense(node, location: :expression)
25
- end
26
-
27
- end
28
- end
29
- end
30
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupDeprecations
6
+ # From SketchUp 6 until SketchUp 2013 the SketchUp API shipped with a
7
+ # `Set` class. When SketchUp started shipping with the Ruby StdLib in
8
+ # SketchUp 2014 the class was changed from `Set` to `Sketchup::Set` in
9
+ # order to avoid conflict with the Ruby Standard Library.
10
+ #
11
+ # The `Sketchup::Set` class is much slower than Ruby's own `Set` class
12
+ # and less versatile.
13
+ class SketchupSet < SketchUp::Cop
14
+
15
+ MSG = 'Class is deprecated.'
16
+
17
+ def_node_matcher :sketchup_set?, <<-PATTERN
18
+ (const (const nil? :Sketchup) :Set)
19
+ PATTERN
20
+
21
+ def on_const(node)
22
+ return unless sketchup_set?(node)
23
+
24
+ add_offense(node, location: :expression)
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,41 +1,41 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module SketchupPerformance
6
- # There are performance issue with the OpenSSL library that Ruby ship. In
7
- # a clean SU session, default model there is a small delay observed in the
8
- # Windows version of SU.
9
- #
10
- # But with a larger model loaded, or session that have had larger files
11
- # loaded the lag will be minutes.
12
- #
13
- # `SecureRandom` is also affected by this, as it uses OpenSSL to seed.
14
- #
15
- # It also affects `Net::HTTP` if making HTTPS connections.
16
- class OpenSSL < SketchUp::Cop
17
-
18
- MSG = 'Avoid use of OpenSSL within SketchUp due to severe performance '\
19
- 'issues.'
20
-
21
- # http://www.rubydoc.info/gems/rubocop/RuboCop/NodePattern
22
- # https://rubocop.readthedocs.io/en/latest/node_pattern/
23
- def_node_matcher :require, <<-PATTERN
24
- (send nil? :require
25
- (str $_)
26
- )
27
- PATTERN
28
-
29
- OPEN_SSL_USAGE = %w[openssl securerandom net/https net/http].freeze
30
-
31
- def on_send(node)
32
- filename = require(node)
33
- return if filename.nil?
34
- return unless OPEN_SSL_USAGE.include?(filename.downcase)
35
-
36
- add_offense(node, location: :expression)
37
- end
38
- end
39
- end
40
- end
41
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupPerformance
6
+ # There are performance issue with the OpenSSL library that Ruby ship. In
7
+ # a clean SU session, default model there is a small delay observed in the
8
+ # Windows version of SU.
9
+ #
10
+ # But with a larger model loaded, or session that have had larger files
11
+ # loaded the lag will be minutes.
12
+ #
13
+ # `SecureRandom` is also affected by this, as it uses OpenSSL to seed.
14
+ #
15
+ # It also affects `Net::HTTP` if making HTTPS connections.
16
+ class OpenSSL < SketchUp::Cop
17
+
18
+ MSG = 'Avoid use of OpenSSL within SketchUp due to severe ' \
19
+ 'performance issues.'
20
+
21
+ # http://www.rubydoc.info/gems/rubocop/RuboCop/NodePattern
22
+ # https://rubocop.readthedocs.io/en/latest/node_pattern/
23
+ def_node_matcher :require, <<-PATTERN
24
+ (send nil? :require
25
+ (str $_)
26
+ )
27
+ PATTERN
28
+
29
+ OPEN_SSL_USAGE = %w[openssl securerandom net/https net/http].freeze
30
+
31
+ def on_send(node)
32
+ filename = require(node)
33
+ return if filename.nil?
34
+ return unless OPEN_SSL_USAGE.include?(filename.downcase)
35
+
36
+ add_offense(node, location: :expression)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,33 +1,33 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module SketchupPerformance
6
- # Operations should disable the UI for performance gain.
7
- #
8
- # @example
9
- # model = Sketchup.active_model
10
- # model.start_operation('Operation Name', true)
11
- # # <model changes>
12
- # model.commit_operation
13
- class OperationDisableUI < SketchUp::Cop
14
- MSG = 'Operations should disable the UI for performance gain.'
15
-
16
- def on_send(node)
17
- _, method_name, *args = *node
18
- return unless method_name == :start_operation
19
-
20
- if args.size < 2
21
- add_offense(node, location: :selector)
22
- return
23
- end
24
- argument = args[1]
25
- disable_ui = argument.truthy_literal?
26
- return if disable_ui
27
-
28
- add_offense(argument, location: :expression)
29
- end
30
- end
31
- end
32
- end
33
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupPerformance
6
+ # Operations should disable the UI for performance gain.
7
+ #
8
+ # @example
9
+ # model = Sketchup.active_model
10
+ # model.start_operation('Operation Name', true)
11
+ # # <model changes>
12
+ # model.commit_operation
13
+ class OperationDisableUI < SketchUp::Cop
14
+ MSG = 'Operations should disable the UI for performance gain.'
15
+
16
+ def on_send(node)
17
+ _, method_name, *args = *node
18
+ return unless method_name == :start_operation
19
+
20
+ if args.size < 2
21
+ add_offense(node, location: :selector)
22
+ return
23
+ end
24
+ argument = args[1]
25
+ disable_ui = argument.truthy_literal?
26
+ return if disable_ui
27
+
28
+ add_offense(argument, location: :expression)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,79 +1,79 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module SketchupPerformance
6
- # Prefer changing selection in bulk instead of modifying selection within
7
- # loops. It's much faster to change the selection in bulk. UI updates are
8
- # triggered when you update the selection, so reduce the amount of calls.
9
- #
10
- # @example Poor performance
11
- # model = Sketchup.active_model
12
- # model.active_entities.each { |entity|
13
- # model.selection.add(entity) if entity.is_a?(Sketchup::Face)
14
- # }
15
- #
16
- # @example Better performance
17
- # model = Sketchup.active_model
18
- # faces = model.active_entities.map { |entity|
19
- # entity.is_a?(Sketchup::Face)
20
- # }
21
- # model.selection.add(faces)
22
- #
23
- # @example Better performance and simpler
24
- # model = Sketchup.active_model
25
- # faces = model.active_entities.grep(Sketchup::Face)
26
- # model.selection.add(faces)
27
- class SelectionBulkChanges < SketchUp::Cop
28
-
29
- include RangeHelp
30
-
31
- MSG = 'Prefer changing selection in bulk instead of modifying '\
32
- 'selection within loops.'
33
-
34
- # http://www.rubydoc.info/gems/rubocop/RuboCop/NodePattern
35
- # https://rubocop.readthedocs.io/en/latest/node_pattern/
36
- def_node_matcher :selection?, <<-PATTERN
37
- (send
38
- (send _ {:selection :sel}) {:add :remove :toggle}
39
- ...)
40
- PATTERN
41
-
42
- def_node_matcher :block_loop?, <<-PATTERN
43
- (block
44
- (send
45
- (send _ _) {
46
- :each :each_with_index :each_with_object
47
- :each_entry :each_index :each_slice
48
- :each_key :each_pair :each_value
49
- :grep
50
- } ...)
51
- ...)
52
- PATTERN
53
-
54
- def_node_matcher :numeric_loop?, <<-PATTERN
55
- (block
56
- (send
57
- ({int float} _) {:times :upto :downto} ...)
58
- ...)
59
- PATTERN
60
-
61
- def iterator?(node)
62
- node.is_a?(RuboCop::AST::ForNode) ||
63
- node.is_a?(RuboCop::AST::UntilNode) ||
64
- node.is_a?(RuboCop::AST::WhileNode) ||
65
- block_loop?(node) ||
66
- numeric_loop?(node)
67
- end
68
-
69
- def on_send(node)
70
- return unless selection?(node)
71
- return unless node.ancestors.any?(&method(:iterator?))
72
-
73
- add_offense(node, location: range_with_receiver(node))
74
- end
75
-
76
- end
77
- end
78
- end
79
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupPerformance
6
+ # Prefer changing selection in bulk instead of modifying selection within
7
+ # loops. It's much faster to change the selection in bulk. UI updates are
8
+ # triggered when you update the selection, so reduce the amount of calls.
9
+ #
10
+ # @example Poor performance
11
+ # model = Sketchup.active_model
12
+ # model.active_entities.each { |entity|
13
+ # model.selection.add(entity) if entity.is_a?(Sketchup::Face)
14
+ # }
15
+ #
16
+ # @example Better performance
17
+ # model = Sketchup.active_model
18
+ # faces = model.active_entities.map { |entity|
19
+ # entity.is_a?(Sketchup::Face)
20
+ # }
21
+ # model.selection.add(faces)
22
+ #
23
+ # @example Better performance and simpler
24
+ # model = Sketchup.active_model
25
+ # faces = model.active_entities.grep(Sketchup::Face)
26
+ # model.selection.add(faces)
27
+ class SelectionBulkChanges < SketchUp::Cop
28
+
29
+ include RangeHelp
30
+
31
+ MSG = 'Prefer changing selection in bulk instead of modifying ' \
32
+ 'selection within loops.'
33
+
34
+ # http://www.rubydoc.info/gems/rubocop/RuboCop/NodePattern
35
+ # https://rubocop.readthedocs.io/en/latest/node_pattern/
36
+ def_node_matcher :selection?, <<-PATTERN
37
+ (send
38
+ (send _ {:selection :sel}) {:add :remove :toggle}
39
+ ...)
40
+ PATTERN
41
+
42
+ def_node_matcher :block_loop?, <<-PATTERN
43
+ (block
44
+ (send
45
+ (send _ _) {
46
+ :each :each_with_index :each_with_object
47
+ :each_entry :each_index :each_slice
48
+ :each_key :each_pair :each_value
49
+ :grep
50
+ } ...)
51
+ ...)
52
+ PATTERN
53
+
54
+ def_node_matcher :numeric_loop?, <<-PATTERN
55
+ (block
56
+ (send
57
+ ({int float} _) {:times :upto :downto} ...)
58
+ ...)
59
+ PATTERN
60
+
61
+ def iterator?(node)
62
+ node.is_a?(RuboCop::AST::ForNode) ||
63
+ node.is_a?(RuboCop::AST::UntilNode) ||
64
+ node.is_a?(RuboCop::AST::WhileNode) ||
65
+ block_loop?(node) ||
66
+ numeric_loop?(node)
67
+ end
68
+
69
+ def on_send(node)
70
+ return unless selection?(node)
71
+ return unless node.ancestors.any?(&method(:iterator?))
72
+
73
+ add_offense(node, location: range_with_receiver(node))
74
+ end
75
+
76
+ end
77
+ end
78
+ end
79
+ end
@@ -1,63 +1,63 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module SketchupPerformance
6
- # String comparisons for type checks are very slow.
7
- #
8
- # `entity.class.name == 'Sketchup::Face'` is slow because it performs a
9
- # string comparison. `is_a?` is much faster because it's a simple type
10
- # check.
11
- #
12
- # If you know you need a strict type check, compare the classes directly:
13
- # `entity.class == Sketchup::Face`.
14
- #
15
- # @example Poor performance
16
- # entity.class.name == 'Sketchup::Face'
17
- #
18
- # @example Good performance
19
- # entity.class == Sketchup::Face
20
- #
21
- # @example Good performance and idiomatic Ruby convention
22
- # entity.is_a?(Sketchup::Face)
23
- class TypeCheck < SketchUp::Cop
24
-
25
- # TODO(thomthom): It probably makes sense to eventually merge the
26
- # Typename cop into this cop. But until this cop have been
27
- # battle tested they remain separate. .typename is no prevalent in
28
- # use (wrongly) that it's better to err in the name of caution, making
29
- # sure we don't miss any scenarios.
30
-
31
- include RangeHelp
32
-
33
- MSG = 'String comparisons are very slow, prefer `.is_a?` '\
34
- 'instead.'
35
-
36
- def_node_matcher :string_class_compare?, <<-PATTERN
37
- (send
38
- (send
39
- (send
40
- _ :class) :name) {:== :=== :!=}
41
- (str _))
42
- PATTERN
43
-
44
- def on_send(node)
45
- return unless string_class_compare?(node)
46
-
47
- add_offense(node, location: comparison_range(node))
48
- end
49
-
50
- private
51
-
52
- def comparison_range(node)
53
- lhs = node.receiver
54
- rhs = node.arguments.first
55
-
56
- loc_begin = lhs.receiver.loc.selector.begin_pos
57
- loc_end = rhs.loc.expression.end_pos
58
- range_between(loc_begin, loc_end)
59
- end
60
- end
61
- end
62
- end
63
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupPerformance
6
+ # String comparisons for type checks are very slow.
7
+ #
8
+ # `entity.class.name == 'Sketchup::Face'` is slow because it performs a
9
+ # string comparison. `is_a?` is much faster because it's a simple type
10
+ # check.
11
+ #
12
+ # If you know you need a strict type check, compare the classes directly:
13
+ # `entity.class == Sketchup::Face`.
14
+ #
15
+ # @example Poor performance
16
+ # entity.class.name == 'Sketchup::Face'
17
+ #
18
+ # @example Good performance
19
+ # entity.class == Sketchup::Face
20
+ #
21
+ # @example Good performance and idiomatic Ruby convention
22
+ # entity.is_a?(Sketchup::Face)
23
+ class TypeCheck < SketchUp::Cop
24
+
25
+ # TODO(thomthom): It probably makes sense to eventually merge the
26
+ # Typename cop into this cop. But until this cop have been
27
+ # battle tested they remain separate. .typename is no prevalent in
28
+ # use (wrongly) that it's better to err in the name of caution, making
29
+ # sure we don't miss any scenarios.
30
+
31
+ include RangeHelp
32
+
33
+ MSG = 'String comparisons are very slow, prefer `.is_a?` ' \
34
+ 'instead.'
35
+
36
+ def_node_matcher :string_class_compare?, <<-PATTERN
37
+ (send
38
+ (send
39
+ (send
40
+ _ :class) :name) {:== :=== :!=}
41
+ (str _))
42
+ PATTERN
43
+
44
+ def on_send(node)
45
+ return unless string_class_compare?(node)
46
+
47
+ add_offense(node, location: comparison_range(node))
48
+ end
49
+
50
+ private
51
+
52
+ def comparison_range(node)
53
+ lhs = node.receiver
54
+ rhs = node.arguments.first
55
+
56
+ loc_begin = lhs.receiver.loc.selector.begin_pos
57
+ loc_end = rhs.loc.expression.end_pos
58
+ range_between(loc_begin, loc_end)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end