rubocop-sketchup 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +7 -1
  3. data/assets/logo.png +0 -0
  4. data/assets/output.html.erb +301 -0
  5. data/config/default.yml +141 -36
  6. data/lib/rubocop/sketchup/config.rb +28 -8
  7. data/lib/rubocop/sketchup/cop/deprecations/add_separator_to_menu.rb +4 -1
  8. data/lib/rubocop/sketchup/cop/deprecations/operation_next_transparent.rb +11 -2
  9. data/lib/rubocop/sketchup/cop/deprecations/require_all.rb +7 -2
  10. data/lib/rubocop/sketchup/cop/deprecations/set_texture_projection.rb +6 -2
  11. data/lib/rubocop/sketchup/cop/deprecations/show_ruby_panel.rb +4 -1
  12. data/lib/rubocop/sketchup/cop/deprecations/sketchup_set.rb +8 -0
  13. data/lib/rubocop/sketchup/cop/performance/openssl.rb +5 -3
  14. data/lib/rubocop/sketchup/cop/performance/operation_disable_ui.rb +10 -2
  15. data/lib/rubocop/sketchup/cop/performance/selection_bulk.rb +11 -4
  16. data/lib/rubocop/sketchup/cop/performance/type_check.rb +63 -0
  17. data/lib/rubocop/sketchup/cop/performance/typename.rb +6 -1
  18. data/lib/rubocop/sketchup/cop/requirements/api_namespace.rb +8 -2
  19. data/lib/rubocop/sketchup/cop/requirements/exit.rb +7 -3
  20. data/lib/rubocop/sketchup/cop/requirements/extension_namespace.rb +32 -2
  21. data/lib/rubocop/sketchup/cop/requirements/file_structure.rb +22 -10
  22. data/lib/rubocop/sketchup/cop/requirements/gem_install.rb +45 -0
  23. data/lib/rubocop/sketchup/cop/requirements/get_extension_license.rb +95 -0
  24. data/lib/rubocop/sketchup/cop/requirements/global_constants.rb +10 -1
  25. data/lib/rubocop/sketchup/cop/requirements/global_include.rb +9 -2
  26. data/lib/rubocop/sketchup/cop/requirements/global_methods.rb +10 -1
  27. data/lib/rubocop/sketchup/cop/requirements/global_variables.rb +13 -4
  28. data/lib/rubocop/sketchup/cop/requirements/language_handler_globals.rb +6 -4
  29. data/lib/rubocop/sketchup/cop/requirements/load_path.rb +9 -6
  30. data/lib/rubocop/sketchup/cop/requirements/minimal_registration.rb +26 -2
  31. data/lib/rubocop/sketchup/cop/requirements/observers_start_operation.rb +28 -2
  32. data/lib/rubocop/sketchup/cop/requirements/register_extension.rb +12 -2
  33. data/lib/rubocop/sketchup/cop/requirements/ruby_core_namespace.rb +14 -8
  34. data/lib/rubocop/sketchup/cop/requirements/ruby_stdlib_namespace.rb +594 -588
  35. data/lib/rubocop/sketchup/cop/requirements/shipped_extensions_namespace.rb +6 -6
  36. data/lib/rubocop/sketchup/cop/requirements/sketchup_extension.rb +28 -9
  37. data/lib/rubocop/sketchup/cop/requirements/sketchup_require.rb +163 -0
  38. data/lib/rubocop/sketchup/cop/suggestions/add_group.rb +49 -0
  39. data/lib/rubocop/sketchup/cop/suggestions/compatibility.rb +35 -6
  40. data/lib/rubocop/sketchup/cop/suggestions/dc_internals.rb +6 -3
  41. data/lib/rubocop/sketchup/cop/suggestions/file_encoding.rb +3 -0
  42. data/lib/rubocop/sketchup/cop/suggestions/model_entities.rb +9 -2
  43. data/lib/rubocop/sketchup/cop/suggestions/monkey_patched_api.rb +5 -1
  44. data/lib/rubocop/sketchup/cop/suggestions/operation_name.rb +20 -9
  45. data/lib/rubocop/sketchup/cop/suggestions/sketchup_find_support_file.rb +13 -2
  46. data/lib/rubocop/sketchup/cop/suggestions/tool_drawing_bounds.rb +44 -0
  47. data/lib/rubocop/sketchup/cop/suggestions/tool_invalidate.rb +66 -0
  48. data/lib/rubocop/sketchup/cop/suggestions/tool_user_input.rb +41 -0
  49. data/lib/rubocop/sketchup/cop/suggestions/toolbar_timer.rb +65 -0
  50. data/lib/rubocop/sketchup/cop.rb +38 -18
  51. data/lib/rubocop/sketchup/dc_globals.rb +1 -1
  52. data/lib/rubocop/sketchup/dc_methods.rb +27 -27
  53. data/lib/rubocop/sketchup/extension_project.rb +19 -2
  54. data/lib/rubocop/sketchup/formatter/extension_review.rb +35 -15
  55. data/lib/rubocop/sketchup/inject.rb +1 -1
  56. data/lib/rubocop/sketchup/namespace.rb +1 -0
  57. data/lib/rubocop/sketchup/namespace_checker.rb +4 -1
  58. data/lib/rubocop/sketchup/no_comment_disable.rb +1 -1
  59. data/lib/rubocop/sketchup/range_help.rb +52 -0
  60. data/lib/rubocop/sketchup/sketchup_version.rb +4 -2
  61. data/lib/rubocop/sketchup/tool_checker.rb +43 -0
  62. data/lib/rubocop/sketchup/version.rb +1 -1
  63. data/lib/rubocop/sketchup.rb +1 -1
  64. data/lib/rubocop-sketchup.rb +9 -0
  65. data/rubocop-sketchup.gemspec +8 -11
  66. metadata +18 -6
  67. data/lib/rubocop/sketchup/cop/suggestions/sketchup_require.rb +0 -67
@@ -3,8 +3,9 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module SketchupPerformance
6
- # Avoid modifying the selection set within loops. It's much faster to
7
- # change the selection in bulk.
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.
8
9
  #
9
10
  # @example Poor performance
10
11
  # model = Sketchup.active_model
@@ -24,7 +25,11 @@ module RuboCop
24
25
  # faces = model.active_entities.grep(Sketchup::Face)
25
26
  # model.selection.add(faces)
26
27
  class SelectionBulkChanges < SketchUp::Cop
27
- MSG = 'Avoid modifying selecting within loops.'.freeze
28
+
29
+ include RangeHelp
30
+
31
+ MSG = 'Prefer changing selection in bulk instead of modifying '\
32
+ 'selection within loops.'.freeze
28
33
 
29
34
  # http://www.rubydoc.info/gems/rubocop/RuboCop/NodePattern
30
35
  # https://rubocop.readthedocs.io/en/latest/node_pattern/
@@ -64,8 +69,10 @@ module RuboCop
64
69
  def on_send(node)
65
70
  return unless selection?(node)
66
71
  return unless node.ancestors.any?(&method(:iterator?))
67
- add_offense(node, location: :expression)
72
+
73
+ add_offense(node, location: range_with_receiver(node))
68
74
  end
75
+
69
76
  end
70
77
  end
71
78
  end
@@ -0,0 +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.'.freeze
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
@@ -3,15 +3,20 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module SketchupPerformance
6
+ # `.typename` is very slow, prefer `.is_a?` instead.
7
+ #
8
+ # `entity.typename == 'Face'` is slow because it performs a string
9
+ # comparison. `is_a?` is much faster because it's a simple type check.
6
10
  class Typename < SketchUp::Cop
7
11
  MSG = '`.typename` is very slow, prefer `.is_a?` instead.'.freeze
8
12
 
9
13
  def on_send(node)
10
14
  _, method_name = *node
11
15
  return unless method_name == :typename
16
+
12
17
  # TODO(thomthom): Should we try to detect use of #typename
13
18
  # in context of comparing against a string?
14
- add_offense(node, location: :expression)
19
+ add_offense(node, location: :selector)
15
20
  end
16
21
  end
17
22
  end
@@ -3,6 +3,12 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module SketchupRequirements
6
+ # Do not modify the Sketch API. This will affect other extensions and
7
+ # very likely cause them to fail.
8
+ #
9
+ # This requirement also include adding things into the SketchUp API
10
+ # namespace. The API namespace is reserved for future additions to the
11
+ # API.
6
12
  class ApiNamespace < SketchUp::Cop
7
13
 
8
14
  include SketchUp::NoCommentDisable
@@ -10,9 +16,9 @@ module RuboCop
10
16
 
11
17
  MSG = 'Do not modify the SketchUp API.'.freeze
12
18
 
13
- NAMESPACES = %w(
19
+ NAMESPACES = %w[
14
20
  Geom Layout Sketchup SketchupExtension UI
15
- ).freeze
21
+ ].freeze
16
22
 
17
23
  def namespaces
18
24
  NAMESPACES
@@ -7,12 +7,14 @@ module RuboCop
7
7
  # SketchUp will trap `exit` and prevent that, with a message in the
8
8
  # console. But `exit!` is not trapped and with terminate SketchUp without
9
9
  # shutting down cleanly.
10
- # Use `return`, `next` or `break` instead.
10
+ #
11
+ # Use `return`, `next`, `break` or `raise` instead.
11
12
  class Exit < SketchUp::Cop
12
13
 
13
14
  include SketchUp::NoCommentDisable
14
15
 
15
- MSG = 'Exit attempts to kill the Ruby interpreter. Use return, next or break instead.'.freeze
16
+ MSG = '`exit` attempts to kill the Ruby interpreter. Use `return`, '\
17
+ '`next`, `break` or `raise` instead.'.freeze
16
18
 
17
19
  # Reference: http://rubocop.readthedocs.io/en/latest/development/
18
20
  def_node_matcher :exit?, <<-PATTERN
@@ -20,7 +22,9 @@ module RuboCop
20
22
  PATTERN
21
23
 
22
24
  def on_send(node)
23
- add_offense(node, location: :expression, severity: :error) if exit?(node)
25
+ return unless exit?(node)
26
+
27
+ add_offense(node, location: :selector)
24
28
  end
25
29
  end
26
30
  end
@@ -7,6 +7,30 @@ require 'rubocop/sketchup/cop/requirements/ruby_stdlib_namespace'
7
7
  module RuboCop
8
8
  module Cop
9
9
  module SketchupRequirements
10
+ # Extensions in SketchUp all share the same Ruby environment on the user's
11
+ # machine. Because of this it's important that each extension isolate
12
+ # itself to avoid clashing with other extensions.
13
+ #
14
+ # Extensions submitted to Extension Warehouse is expected to use only one
15
+ # root module.
16
+ #
17
+ # @example Good - this contains everything in the extension.
18
+ # module MyExtension
19
+ # class Foo
20
+ # end
21
+ # class Bar
22
+ # end
23
+ # end
24
+ #
25
+ # @example Better - this further reduce chance of clashing.
26
+ # module MyCompany
27
+ # module MyExtension
28
+ # class Foo
29
+ # end
30
+ # class Bar
31
+ # end
32
+ # end
33
+ # end
10
34
  class ExtensionNamespace < SketchUp::Cop
11
35
 
12
36
  include SketchUp::NoCommentDisable
@@ -28,6 +52,7 @@ module RuboCop
28
52
  return unless parent.top_level?
29
53
  # Don't check excluded namespaces.
30
54
  return if exempted?(namespace)
55
+
31
56
  check_namespace(node, namespace)
32
57
  end
33
58
 
@@ -40,12 +65,14 @@ module RuboCop
40
65
  # Make sure the namespace isn't part of reserved namespaces that other
41
66
  # cops are checking.
42
67
  return if reserved?(namespace)
68
+
43
69
  # Remember the first namespace encountered and log an offence if
44
70
  # more top level namespaces are registered.
45
71
  top = namespace.first
46
72
  @@namespace ||= top
47
73
  return if @@namespace == top
48
- add_offense(node, location: :name, severity: :error)
74
+
75
+ add_offense(node, location: :name)
49
76
  end
50
77
 
51
78
  def reserved?(namespace)
@@ -53,12 +80,15 @@ module RuboCop
53
80
  return true if RubyCoreNamespace::NAMESPACES.include?(top)
54
81
  return true if RubyStdLibNamespace::NAMESPACES.include?(top)
55
82
  return true if ApiNamespace::NAMESPACES.include?(top)
83
+
56
84
  false
57
85
  end
58
86
 
59
87
  def message(node)
60
88
  namespace = Namespace.new(node.defined_module_name).from_root
61
- format('Use a single root namespace. (Found `%s`; Previously found `%s`)', namespace, @@namespace)
89
+ format('Use a single root namespace. '\
90
+ '(Found `%<found>s`; Previously found `%<expected>s`)',
91
+ found: namespace, expected: @@namespace)
62
92
  end
63
93
 
64
94
  def exempted?(namespace)
@@ -5,6 +5,16 @@ module RuboCop
5
5
  module SketchupRequirements
6
6
  # Check that the extension conform to expected file structure with a
7
7
  # single root .rb file and a support folder with matching name.
8
+ #
9
+ # Make sure to match upper and lower case characters between the root .rb
10
+ # file and the support folder.
11
+ #
12
+ # @example
13
+ # SketchUp/Plugins
14
+ # + ex_hello_world.rb
15
+ # + ex_hello_world
16
+ # + main.rb
17
+ # + ...
8
18
  class FileStructure < SketchUp::Cop
9
19
 
10
20
  include SketchUp::NoCommentDisable
@@ -27,41 +37,40 @@ module RuboCop
27
37
 
28
38
  # Ensure there is only one root Ruby file.
29
39
  if root_ruby_files.size != 1
30
- msg = "Extensions must have exactly one root Ruby (.rb) file. Found: %d"
40
+ msg = 'Extensions must have exactly one root Ruby (.rb) file. '\
41
+ 'Found: %d'
31
42
  add_offense(nil,
32
43
  location: range,
33
- message: format(msg, root_ruby_files.size),
34
- severity: :error)
44
+ message: format(msg, root_ruby_files.size))
35
45
  return
36
46
  end
37
47
 
38
48
  # Find the root file and collect the sub-directories.
39
49
  root_file = root_ruby_files.first
40
50
  extension_basename = File.basename(root_file, '.*')
41
- sub_folders = source_path.children.select { |c| c.directory? }
51
+ sub_folders = source_path.children.select(&:directory?)
42
52
  sub_folders.reject! { |folder|
43
53
  IGNORED_DIRECTORIES.include?(folder.basename.to_s)
44
54
  }
45
55
 
46
56
  # Ensure there is only one sub-directory.
47
57
  if sub_folders.size != 1
48
- msg = "Extensions must have exactly one support directory. Found %d"
58
+ msg = 'Extensions must have exactly one support directory. Found %d'
49
59
  add_offense(nil,
50
60
  location: range,
51
- message: format(msg, sub_folders.size),
52
- severity: :error)
61
+ message: format(msg, sub_folders.size))
53
62
  return
54
63
  end
55
64
 
56
65
  # Ensure support directory's name match the root Ruby file.
57
66
  support_directory = sub_folders.first
58
67
  unless support_directory.basename.to_s == extension_basename
59
- msg = 'Extensions must have a support directory matching the name of the root Ruby file. Expected %s, found %s'
68
+ msg = 'Extensions must have a support directory matching the name '\
69
+ 'of the root Ruby file. Expected %s, found %s'
60
70
  msg = format(msg, extension_basename, support_directory.basename)
61
71
  add_offense(nil,
62
72
  location: range,
63
- message: msg,
64
- severity: :error)
73
+ message: msg)
65
74
  end
66
75
  end
67
76
 
@@ -71,13 +80,16 @@ module RuboCop
71
80
 
72
81
  def already_run?
73
82
  return true if @@already_run
83
+
74
84
  @@already_run = true
75
85
  false
76
86
  end
77
87
 
88
+ # rubocop:disable Lint/IneffectiveAccessModifier
78
89
  def self.reset
79
90
  @@already_run = false
80
91
  end
92
+ # rubocop:enable Lint/IneffectiveAccessModifier
81
93
 
82
94
  end
83
95
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupRequirements
6
+ # It's tempting to use gems in an extension. However, there are issues if
7
+ # consuming them via Gem.install;
8
+ #
9
+ # * Net::HTTP is unreliable. (SSL certificate issues, OpenSSL performance
10
+ # freeze under Windows)
11
+ # * Compiled extensions cannot be installed like this as they require
12
+ # DevKit.
13
+ # * While downloading and installing SketchUp freezes. (Bad thing if done
14
+ # automatically upon loading the extensions - especially without user
15
+ # notice. It's easy to think SU have stopped working)
16
+ # * Version collisions. If multiple extensions want to use different
17
+ # versions of a gem they will clash if the versions aren't compatible
18
+ # with the features they use.
19
+ #
20
+ # They only way to ensure extensions doesn't clash is to namespace
21
+ # everything into extension namespace. This means making a copy of the
22
+ # gem you want to use and wrap it in your own namespace.
23
+ class GemInstall < SketchUp::Cop
24
+
25
+ include RangeHelp
26
+ include SketchUp::NoCommentDisable
27
+
28
+ MSG = '`Gem.install` is unreliable in SketchUp, and can cause '\
29
+ 'extensions to clash.'.freeze
30
+
31
+ # Reference: http://rubocop.readthedocs.io/en/latest/development/
32
+ def_node_matcher :gem_install?, <<-PATTERN
33
+ (send (const nil? :Gem) :install ...)
34
+ PATTERN
35
+
36
+ def on_send(node)
37
+ return unless gem_install?(node)
38
+
39
+ range = range_with_receiver(node)
40
+ add_offense(node, location: range)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupRequirements
6
+ # Don't attempt to kill the Ruby interpreter by calling `exit` or `exit!`.
7
+ # SketchUp will trap `exit` and prevent that, with a message in the
8
+ # console. But `exit!` is not trapped and with terminate SketchUp without
9
+ # shutting down cleanly.
10
+ #
11
+ # Use `return`, `next`, `break` or `raise` instead.
12
+ class GetExtensionLicense < SketchUp::Cop
13
+
14
+ include RangeHelp
15
+ include SketchUp::NoCommentDisable
16
+
17
+ MSG_INVALID = 'Invalid extension GUID'.freeze
18
+
19
+ MSG_WRONG_TYPE = 'Only pass in extension GUID from local string '\
20
+ 'literals.'.freeze
21
+
22
+ MSG_TRAILING_SPACE = 'Extra space in extension GUID'.freeze
23
+
24
+ def_node_matcher :get_extension_license, <<-PATTERN
25
+ (send
26
+ (const
27
+ (const nil? :Sketchup) :Licensing) :get_extension_license
28
+ $_)
29
+ PATTERN
30
+
31
+ # rubocop:disable Metrics/LineLength
32
+ EXTENSION_ID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/
33
+ # rubocop:enable Metrics/LineLength
34
+
35
+ def on_send(node)
36
+ argument = get_extension_license(node)
37
+ return unless argument
38
+
39
+ if argument.lvar_type?
40
+ variable_name = argument.children.first
41
+ assignment_node = find_assignment(node, variable_name)
42
+ argument = assignment_node.children.last
43
+ end
44
+
45
+ if argument.str_type?
46
+ validate_extension_id(argument)
47
+ else
48
+ location = argument.loc.expression
49
+ add_offense(node, location: location, message: MSG_WRONG_TYPE)
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def find_assignment(node, variable_name)
56
+ scope = node
57
+ until scope.parent.nil?
58
+ scope = scope.parent
59
+ scope.each_child_node { |child|
60
+ # next unless child.is_a?(RuboCop::AST::Node)
61
+ next unless child.lvasgn_type?
62
+ next unless child.children.first == variable_name
63
+
64
+ return child
65
+ }
66
+ end
67
+ nil
68
+ end
69
+
70
+ def validate_extension_id(node)
71
+ extension_id = node.str_content
72
+
73
+ # Trailing spaces
74
+ if extension_id.rstrip.size < extension_id.size
75
+ end_pos = node.loc.end.begin_pos
76
+ begin_pos = node.loc.begin.end_pos + extension_id.rstrip.size
77
+ range = range_between(begin_pos, end_pos)
78
+ add_offense(node, location: range, message: MSG_TRAILING_SPACE)
79
+ return false
80
+ end
81
+
82
+ # Invalid format.
83
+ if extension_id !~ EXTENSION_ID_PATTERN
84
+ range = string_contents_range(node)
85
+ add_offense(node, location: range, message: MSG_INVALID)
86
+ return false
87
+ end
88
+
89
+ true
90
+ end
91
+
92
+ end
93
+ end
94
+ end
95
+ end
@@ -3,6 +3,12 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module SketchupRequirements
6
+ # Extensions in SketchUp all share the same Ruby environment on the user's
7
+ # machine. Because of this it's important that each extension isolate
8
+ # itself to avoid clashing with other extensions.
9
+ #
10
+ # Extensions submitted to Extension Warehouse is expected to not define
11
+ # global constants.
6
12
  class GlobalConstants < SketchUp::Cop
7
13
 
8
14
  include SketchUp::NoCommentDisable
@@ -19,8 +25,11 @@ module RuboCop
19
25
  # Constant assignment.
20
26
  def on_casgn(node)
21
27
  return if namespaced_constant?(node)
28
+
22
29
  namespace = Namespace.new(node.parent_module_name)
23
- add_offense(node, location: :name, severity: :error) if namespace.top_level?
30
+ return unless namespace.top_level?
31
+
32
+ add_offense(node, location: :name)
24
33
  end
25
34
 
26
35
  end
@@ -3,6 +3,12 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module SketchupRequirements
6
+ # Extensions in SketchUp all share the same Ruby environment on the user's
7
+ # machine. Because of this it's important that each extension isolate
8
+ # itself to avoid clashing with other extensions.
9
+ #
10
+ # Extensions submitted to Extension Warehouse is expected to not pollute
11
+ # the global namespace by including mix-in modules.
6
12
  class GlobalInclude < SketchUp::Cop
7
13
 
8
14
  include SketchUp::NoCommentDisable
@@ -16,7 +22,8 @@ module RuboCop
16
22
 
17
23
  def on_send(node)
18
24
  return unless global_include?(node)
19
- add_offense(node, severity: :error)
25
+
26
+ add_offense(node, location: :selector)
20
27
  end
21
28
 
22
29
  private
@@ -26,7 +33,7 @@ module RuboCop
26
33
  end
27
34
 
28
35
  def global_namespace?(node)
29
- ['Kernel', 'Object'].include?(node.parent_module_name)
36
+ %w[Kernel Object].include?(node.parent_module_name)
30
37
  end
31
38
 
32
39
  end
@@ -3,6 +3,12 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module SketchupRequirements
6
+ # Extensions in SketchUp all share the same Ruby environment on the user's
7
+ # machine. Because of this it's important that each extension isolate
8
+ # itself to avoid clashing with other extensions.
9
+ #
10
+ # Extensions submitted to Extension Warehouse is expected to not define
11
+ # global methods.
6
12
  class GlobalMethods < SketchUp::Cop
7
13
 
8
14
  include SketchUp::NoCommentDisable
@@ -44,9 +50,12 @@ module RuboCop
44
50
  # If a method is defined inside a block then parent_module_name
45
51
  # will return nil.
46
52
  return if node.parent_module_name.nil?
53
+
47
54
  namespace = Namespace.new(node.parent_module_name)
48
55
  end
49
- add_offense(node, location: :name, severity: :error) if namespace.top_level?
56
+ return unless namespace.top_level?
57
+
58
+ add_offense(node, location: :name)
50
59
  end
51
60
  alias on_defs on_def
52
61
 
@@ -3,12 +3,19 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module SketchupRequirements
6
+ # Extensions in SketchUp all share the same Ruby environment on the user's
7
+ # machine. Because of this it's important that each extension isolate
8
+ # itself to avoid clashing with other extensions.
9
+ #
10
+ # Extensions submitted to Extension Warehouse is expected to not define
11
+ # global variables.
12
+ #
6
13
  # This cops looks for uses of global variables.
7
14
  # It does not report offenses for built-in global variables.
8
15
  # Built-in global variables are allowed by default. Additionally
9
16
  # users can allow additional variables via the AllowedVariables option.
10
17
  #
11
- # Note that backreferences like $1, $2, etc are not global variables.
18
+ # Note that backreferences like `$1`, `$2`, etc are not global variables.
12
19
  class GlobalVariables < SketchUp::Cop
13
20
 
14
21
  include SketchUp::NoCommentDisable
@@ -45,11 +52,11 @@ module RuboCop
45
52
  $DEBUG $FILENAME $VERBOSE $SAFE
46
53
  $-0 $-a $-d $-F $-i $-I $-l $-p $-v $-w
47
54
  $CLASSPATH $JRUBY_VERSION $JRUBY_REVISION $ENV_JAVA
48
- ]
55
+ ].freeze
49
56
 
50
57
  SKETCHUP_VARS = %i[
51
58
  $loaded_files
52
- ]
59
+ ].freeze
53
60
 
54
61
  # Some globals, like DC's, are being read from so often that it's better
55
62
  # to ignore these to reduce noise.
@@ -78,7 +85,9 @@ module RuboCop
78
85
  def check(node)
79
86
  global_var, = *node
80
87
 
81
- add_offense(node, location: :name, severity: :error) unless allowed_var?(global_var)
88
+ return if allowed_var?(global_var)
89
+
90
+ add_offense(node, location: :name)
82
91
  end
83
92
  end
84
93
  end
@@ -3,14 +3,15 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module SketchupRequirements
6
- # Avoid using globals in general, but especially these which are known to
6
+ # Avoid using globals in general, but especially these which are known to
7
7
  # be in use by other extensions made by SketchUp.
8
8
  # They are still in use due to compatibility reasons.
9
9
  class LanguageHandlerGlobals < SketchUp::Cop
10
10
 
11
11
  include SketchUp::NoCommentDisable
12
12
 
13
- MSG = "Avoid globals in general, but especially these which are known to be in use.".freeze
13
+ MSG = 'Avoid globals in general, but especially these which are known '\
14
+ 'to be in use.'.freeze
14
15
 
15
16
  LH_GLOBALS = %i[
16
17
  $dc_strings
@@ -26,7 +27,7 @@ module RuboCop
26
27
  $unitsStrings
27
28
  $uStrings
28
29
  $wt_strings
29
- ]
30
+ ].freeze
30
31
 
31
32
  def hl_global_var?(global_var)
32
33
  LH_GLOBALS.include?(global_var)
@@ -35,7 +36,8 @@ module RuboCop
35
36
  def on_gvasgn(node)
36
37
  global_var, = *node
37
38
  return unless hl_global_var?(global_var)
38
- add_offense(node, location: :name, severity: :error)
39
+
40
+ add_offense(node, location: :name)
39
41
  end
40
42
 
41
43
  end