rubocop-sketchup 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupSuggestions
6
+ # After having drawn to the viewport from a tool, make sure to invalidate
7
+ # the view on `deactivate` and `suspend`.
8
+ #
9
+ # If you don't do that the things you drew might stick around for longer
10
+ # than the life-span of the tool and cause confusion for the user.
11
+ #
12
+ # @example
13
+ # # good
14
+ # class ExampleTool
15
+ #
16
+ # def deactivate(view)
17
+ # view_invalidate
18
+ # end
19
+ #
20
+ # def suspend(view)
21
+ # view_invalidate
22
+ # end
23
+ #
24
+ # def draw(view)
25
+ # view.draw(GL_LINES, @points)
26
+ # end
27
+ #
28
+ # end
29
+ class ToolInvalidate < Cop
30
+
31
+ include SketchUp::ToolChecker
32
+
33
+ MSG_MISSING_INVALIDATE_METHOD = 'When drawing to the viewport, make '\
34
+ 'sure to `suspend` and `deactivate` calls `view.invalidate`.'.freeze
35
+
36
+ MSG_MISSING_INVALIDATE = 'When drawing to the viewport, make sure to '\
37
+ 'call `view.invalidate` when the tool becomes inactive.'.freeze
38
+
39
+ def_node_search :view_invalidate?, <<-PATTERN
40
+ (send (lvar :view) :invalidate ...)
41
+ PATTERN
42
+
43
+ def on_tool_class(class_node, body_methods)
44
+ return unless find_method(body_methods, :draw)
45
+
46
+ check_method_invalidate(:deactivate, body_methods, class_node)
47
+ check_method_invalidate(:suspend, body_methods, class_node)
48
+ end
49
+
50
+ private
51
+
52
+ def check_method_invalidate(method_name, body_methods, class_node)
53
+ method_node = find_method(body_methods, method_name)
54
+ if method_node
55
+ return if view_invalidate?(method_node)
56
+
57
+ add_offense(method_node, message: MSG_MISSING_INVALIDATE)
58
+ else
59
+ add_offense(class_node, message: MSG_MISSING_INVALIDATE_METHOD)
60
+ end
61
+ end
62
+
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupSuggestions
6
+ # When a tool takes user input via `onUserText`, make sure to define
7
+ # `enableVCB?` so that the VCB is enabled.
8
+ #
9
+ # @example
10
+ # # good
11
+ # class ExampleTool
12
+ #
13
+ # def enableVCB?
14
+ # true
15
+ # end
16
+ #
17
+ # def onUserText(text, view)
18
+ # # ...
19
+ # end
20
+ #
21
+ # end
22
+ class ToolUserInput < Cop
23
+
24
+ include SketchUp::ToolChecker
25
+
26
+ MSG_MISSING_ENABLE_VCB = 'When accepting user input, make sure to '\
27
+ 'define `enableVCB?`.'.freeze
28
+
29
+ def on_tool_class(class_node, body_methods)
30
+ return unless find_method(body_methods, :onUserText)
31
+
32
+ method_node = find_method(body_methods, :enableVCB?)
33
+ return if method_node
34
+
35
+ add_offense(class_node, message: MSG_MISSING_ENABLE_VCB)
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupSuggestions
6
+ # Wrapping `toolbar.restore` in `UI.start_timer` is redundant. It was a
7
+ # workaround for an issue in a very old version of SketchUp. There is no
8
+ # need to still be using this workaround.
9
+ #
10
+ # @example Creating a new toolbar
11
+ # # bad
12
+ # toolbar = UI::Toolbar.new('Example')
13
+ # # ...
14
+ # toolbar.restore
15
+ # UI.start_timer(0.1, false) {
16
+ # toolbar.restore
17
+ # }
18
+ #
19
+ # # good
20
+ # toolbar = UI::Toolbar.new('Example')
21
+ # # ...
22
+ # toolbar.restore
23
+ class ToolbarTimer < Cop
24
+
25
+ include RangeHelp
26
+
27
+ MSG = 'Wrapping `toolbar.restore` in `UI.start_timer` is '\
28
+ 'redundant.'.freeze
29
+
30
+ def_node_matcher :toolbar_new?, <<-PATTERN
31
+ (send (const (const nil? :UI) :Toolbar) :new _)
32
+ PATTERN
33
+
34
+ def_node_search :ui_start_timer_restore, <<-PATTERN
35
+ (block
36
+ (send
37
+ (const nil? :UI) :start_timer
38
+ (float _)
39
+ (false))
40
+ (args)
41
+ (send
42
+ $_ :restore))
43
+ PATTERN
44
+
45
+ def on_send(node)
46
+ return unless toolbar_new?(node)
47
+ return unless node.parent.assignment?
48
+
49
+ assignment_node = node.parent
50
+ toolbar_variable_name = assignment_node.children.first
51
+
52
+ receiver = ui_start_timer_restore(assignment_node.parent).first
53
+ return unless receiver && receiver.variable?
54
+
55
+ receiver_variable_name = receiver.children.first
56
+
57
+ return unless receiver_variable_name == toolbar_variable_name
58
+
59
+ add_offense(receiver.parent)
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+ end
@@ -53,37 +53,57 @@ module RuboCop
53
53
 
54
54
  private
55
55
 
56
+ def default_severity
57
+ sketchup_severity || super
58
+ end
59
+
60
+ def sketchup_severity
61
+ case self.class.department
62
+ when :SketchupRequirements
63
+ :error
64
+ when :SketchupDeprecations
65
+ :warning
66
+ when :SketchupPerformance
67
+ :warning
68
+ when :SketchupSuggestions
69
+ :convention
70
+ end
71
+ end
72
+
56
73
  def department_name
57
74
  self.class.department.to_s
58
75
  end
59
76
 
60
77
  def relevant_rubocop_sketchup_file?(file)
61
- !(department_exclude_pattern =~ file)
78
+ !sketchup_excluded?(file)
62
79
  end
63
80
 
64
- def department_exclude_pattern
65
- if department_exclude_config?
66
- patterns = department_exclude_config.map(&Regexp.public_method(:new))
67
- Regexp.union(patterns)
68
- else
69
- DEFAULT_CONFIGURATION
70
- .fetch(department_name)
71
- .fetch('Exclude')
72
- .map(&Regexp.public_method(:new))
81
+ def sketchup_excluded?(file)
82
+ matches_file?(file, sketchup_exclude_pattern) ||
83
+ matches_file?(file, sketchup_department_exclude_pattern)
84
+ end
85
+
86
+ def matches_file?(file, patterns)
87
+ path = nil
88
+ patterns.any? do |pattern|
89
+ # Try to match the absolute path, as Exclude properties are absolute.
90
+ next true if match_path?(pattern, file)
91
+
92
+ # Try with relative path.
93
+ path ||= config.path_relative_to_config(file)
94
+ match_path?(pattern, path)
73
95
  end
74
96
  end
75
97
 
76
- def department_exclude_config?
77
- return false unless all_cops_config.key?('SketchUp')
78
- sketchup_config = all_cops_config.fetch('SketchUp')
79
- return false unless sketchup_config.key?(department_name)
80
- sketchup_config.fetch(department_name).key?('Exclude')
98
+ def sketchup_department_exclude_pattern
99
+ sketchup_cops_config
100
+ .fetch(department_name, {})
101
+ .fetch('Exclude', [])
81
102
  end
82
103
 
83
- def department_exclude_config
104
+ def sketchup_exclude_pattern
84
105
  sketchup_cops_config
85
- .fetch(department_name)
86
- .fetch('Exclude')
106
+ .fetch('Exclude', [])
87
107
  end
88
108
 
89
109
  end
@@ -11,7 +11,7 @@ module RuboCop
11
11
  $dc_REPORTER_NAME
12
12
  $dc_MANAGER_NAME
13
13
  $dc_observers
14
- ]
14
+ ].freeze
15
15
 
16
16
  private
17
17
 
@@ -7,123 +7,123 @@ module RuboCop
7
7
  DC_METHODS = [
8
8
  {
9
9
  name: :rotx,
10
- path: 'Geom::Transformation'
10
+ path: 'Geom::Transformation',
11
11
  },
12
12
  {
13
13
  name: :roty,
14
- path: 'Geom::Transformation'
14
+ path: 'Geom::Transformation',
15
15
  },
16
16
  {
17
17
  name: :rotz,
18
- path: 'Geom::Transformation'
18
+ path: 'Geom::Transformation',
19
19
  },
20
20
  {
21
21
  name: :xscale,
22
- path: 'Geom::Transformation'
22
+ path: 'Geom::Transformation',
23
23
  },
24
24
  {
25
25
  name: :yscale,
26
- path: 'Geom::Transformation'
26
+ path: 'Geom::Transformation',
27
27
  },
28
28
  {
29
29
  name: :zscale,
30
- path: 'Geom::Transformation'
30
+ path: 'Geom::Transformation',
31
31
  },
32
32
 
33
33
  {
34
34
  name: :copy,
35
35
  path: 'Sketchup::Camera',
36
- variables: [:camera, :cam]
36
+ variables: [:camera, :cam],
37
37
  },
38
38
  {
39
39
  name: :update,
40
40
  path: 'Sketchup::Camera',
41
- variables: [:camera, :cam]
41
+ variables: [:camera, :cam],
42
42
  },
43
43
  {
44
44
  name: :same_camera_params?,
45
- path: 'Sketchup::Camera'
45
+ path: 'Sketchup::Camera',
46
46
  },
47
47
 
48
48
  {
49
49
  name: :copy,
50
50
  path: 'Sketchup::ComponentInstance',
51
- variables: [:instance, :inst]
51
+ variables: [:instance, :inst],
52
52
  },
53
53
  {
54
54
  name: :description,
55
55
  path: 'Sketchup::ComponentInstance',
56
- variables: [:instance, :inst]
56
+ variables: [:instance, :inst],
57
57
  },
58
58
 
59
59
  {
60
60
  name: :local_transformation,
61
- path: 'Sketchup::Drawingelement'
61
+ path: 'Sketchup::Drawingelement',
62
62
  },
63
63
  {
64
64
  name: :scaled_size,
65
- path: 'Sketchup::Drawingelement'
65
+ path: 'Sketchup::Drawingelement',
66
66
  },
67
67
  {
68
68
  name: :unscaled_size,
69
- path: 'Sketchup::Drawingelement'
69
+ path: 'Sketchup::Drawingelement',
70
70
  },
71
71
  {
72
72
  name: :set_last_size,
73
- path: 'Sketchup::Drawingelement'
73
+ path: 'Sketchup::Drawingelement',
74
74
  },
75
75
  {
76
76
  name: :last_scaling_factors,
77
- path: 'Sketchup::Drawingelement'
77
+ path: 'Sketchup::Drawingelement',
78
78
  },
79
79
 
80
80
  {
81
81
  name: :get_attributes,
82
- path: 'Sketchup::Entity'
82
+ path: 'Sketchup::Entity',
83
83
  },
84
84
  {
85
85
  name: :has_attributes?,
86
- path: 'Sketchup::Entity'
86
+ path: 'Sketchup::Entity',
87
87
  },
88
88
 
89
89
  {
90
90
  name: :typename,
91
91
  path: 'Sketchup::Model',
92
- variables: [:model, :mod]
92
+ variables: [:model, :mod],
93
93
  },
94
94
  {
95
95
  name: :entityID,
96
96
  path: 'Sketchup::Model',
97
- variables: [:model, :mod]
97
+ variables: [:model, :mod],
98
98
  },
99
99
  {
100
100
  name: :delete_attribute,
101
101
  path: 'Sketchup::Model',
102
- variables: [:model, :mod]
102
+ variables: [:model, :mod],
103
103
  },
104
104
  {
105
105
  name: :layer,
106
106
  path: 'Sketchup::Model',
107
- variables: [:model, :mod]
107
+ variables: [:model, :mod],
108
108
  },
109
109
 
110
110
  {
111
111
  name: :last_width=,
112
- path: 'UI::WebDialog'
112
+ path: 'UI::WebDialog',
113
113
  },
114
114
  {
115
115
  name: :last_height=,
116
- path: 'UI::WebDialog'
116
+ path: 'UI::WebDialog',
117
117
  },
118
118
  {
119
119
  name: :last_width,
120
- path: 'UI::WebDialog'
120
+ path: 'UI::WebDialog',
121
121
  },
122
122
  {
123
123
  name: :last_height,
124
- path: 'UI::WebDialog'
124
+ path: 'UI::WebDialog',
125
125
  },
126
- ]
126
+ ].freeze
127
127
 
128
128
  end
129
129
  end
@@ -20,7 +20,7 @@ module RuboCop
20
20
 
21
21
  # @return [Pathname]
22
22
  def relative_source_path
23
- Pathname.new(sketchup_source_path_config)
23
+ Pathname.new(extension_source_path_config)
24
24
  end
25
25
 
26
26
  # @return [Pathname]
@@ -39,10 +39,27 @@ module RuboCop
39
39
  # @param [RuboCop::ProcessedSource] processed_source
40
40
  def root_file?(processed_source)
41
41
  filename = path_relative_to_source(processed_source)
42
- filename.extname.downcase == '.rb' &&
42
+ filename.extname.casecmp('.rb').zero? &&
43
43
  filename.parent.to_s == '.'
44
44
  end
45
45
 
46
+ def extension_root_files
47
+ Dir.glob("#{source_path}/*.rb").map { |path| Pathname.new(path) }
48
+ end
49
+
50
+ def extension_root_file
51
+ unless extension_root_files.size == 1
52
+ num_files = extension_root_files.size
53
+ raise "More than one root extension file (#{num_files})"
54
+ end
55
+
56
+ extension_root_files.first
57
+ end
58
+
59
+ def extension_directory
60
+ extension_root_file.dirname
61
+ end
62
+
46
63
  end
47
64
  end
48
65
  end
@@ -12,7 +12,7 @@ module RuboCop
12
12
  class ExtensionReviewFormatter < BaseFormatter
13
13
  ELLIPSES = '<span class="extra-code">...</span>'.freeze
14
14
  TEMPLATE_PATH =
15
- File.expand_path('../../../../../assets/output.html.erb', __FILE__)
15
+ File.expand_path('../../../../assets/output.html.erb', __dir__)
16
16
 
17
17
  Color = Struct.new(:red, :green, :blue, :alpha) do
18
18
  def to_s
@@ -42,11 +42,14 @@ module RuboCop
42
42
  def file_finished(file, offenses)
43
43
  files << file
44
44
  offenses.each { |offense|
45
+ # Report only SketchUp related cops.
46
+ next unless offense.cop_name.start_with?('Sketchup')
47
+
45
48
  report = OpenStruct.new(path: file, offense: offense)
46
49
  categories[offense.cop_name] ||= []
47
50
  categories[offense.cop_name] << report
51
+ summary.offense_count += 1
48
52
  }
49
- summary.offense_count += offenses.count
50
53
  end
51
54
 
52
55
  def finished(inspected_files)
@@ -71,22 +74,22 @@ module RuboCop
71
74
  include TextUtil
72
75
 
73
76
  SEVERITY_COLORS = {
74
- refactor: Color.new(0xED, 0x9C, 0x28, 1.0),
75
- convention: Color.new(0xED, 0x9C, 0x28, 1.0),
76
- warning: Color.new(0x96, 0x28, 0xEF, 1.0),
77
+ refactor: Color.new(0x29, 0x6B, 0xF0, 1.0),
78
+ convention: Color.new(0x29, 0x6B, 0xF0, 1.0),
79
+ warning: Color.new(0xED, 0x9C, 0x28, 1.0),
77
80
  error: Color.new(0xD2, 0x32, 0x2D, 1.0),
78
- fatal: Color.new(0xD2, 0x32, 0x2D, 1.0)
81
+ fatal: Color.new(0xD2, 0x32, 0x2D, 1.0),
79
82
  }.freeze
80
83
 
81
84
  LOGO_IMAGE_PATH =
82
- File.expand_path('../../../../../assets/logo.png', __FILE__)
85
+ File.expand_path('../../../../assets/logo.png', __dir__)
83
86
 
84
87
  SORT_ORDER = %w[
85
88
  SketchupRequirements
86
89
  SketchupDeprecations
87
90
  SketchupPerformance
88
91
  SketchupSuggestions
89
- ]
92
+ ].freeze
90
93
 
91
94
  DEPARTMENT_DESCRIPTIONS = {
92
95
  'SketchupRequirements' => <<-DESCRIPTION,
@@ -125,7 +128,7 @@ module RuboCop
125
128
  This department is not a requirement for submission to
126
129
  Extension Warehouse.
127
130
  DESCRIPTION
128
- }
131
+ }.freeze
129
132
 
130
133
  attr_reader :categories, :files, :summary
131
134
 
@@ -150,6 +153,7 @@ module RuboCop
150
153
  count = 0
151
154
  categories.each { |category, offenses|
152
155
  next unless department(category) == dep
156
+
153
157
  count += offenses.size
154
158
  }
155
159
  count
@@ -176,7 +180,18 @@ module RuboCop
176
180
  # Then sort by cop name.
177
181
  a_department, a_name = a[0].split('/')
178
182
  b_department, b_name = b[0].split('/')
179
- n = SORT_ORDER.index(a_department) <=> SORT_ORDER.index(b_department)
183
+ # Sort SketchUp cops at the top, then all the rest comes after.
184
+ # First sorting by department.
185
+ sort_order_a = SORT_ORDER.index(a_department)
186
+ sort_order_b = SORT_ORDER.index(b_department)
187
+ if sort_order_a.nil? && sort_order_b.nil?
188
+ n = a_department <=> b_department
189
+ else
190
+ sort_order_a ||= SORT_ORDER.size
191
+ sort_order_b ||= SORT_ORDER.size
192
+ n = sort_order_a <=> sort_order_b
193
+ end
194
+ # Them sort by name if departments match.
180
195
  n == 0 ? a_name <=> b_name : n
181
196
  }.to_h
182
197
  end
@@ -187,9 +202,14 @@ module RuboCop
187
202
  end
188
203
 
189
204
  def decorated_message(offense)
190
- offense.message.gsub(/`(.+?)`/) do
191
- "<code>#{Regexp.last_match(1)}</code>"
192
- end
205
+ offense.message
206
+ .gsub(/`(.+?)`/) do
207
+ "<code>#{Regexp.last_match(1)}</code>"
208
+ end
209
+ .gsub(/\((http[^ ]+)\)/) do
210
+ url = Regexp.last_match(1)
211
+ "<br><a href=\"#{url}\">#{url}</a>"
212
+ end
193
213
  end
194
214
 
195
215
  def highlighted_source_line(offense)
@@ -225,8 +245,8 @@ module RuboCop
225
245
  "offense_#{title}"
226
246
  end
227
247
 
228
- def escape(s)
229
- CGI.escapeHTML(s)
248
+ def escape(string)
249
+ CGI.escapeHTML(string)
230
250
  end
231
251
 
232
252
  def base64_encoded_logo_image
@@ -16,4 +16,4 @@ module RuboCop
16
16
  end
17
17
  end
18
18
  end
19
- end
19
+ end
@@ -11,6 +11,7 @@ module RuboCop
11
11
  # @param [String] namespace
12
12
  def initialize(namespace)
13
13
  raise TypeError unless namespace.is_a?(String)
14
+
14
15
  @namespace = namespace
15
16
  end
16
17
 
@@ -23,13 +23,16 @@ module RuboCop
23
23
  end
24
24
 
25
25
  def check_namespace(node)
26
- add_offense(node, location: :name, severity: :error) if in_namespace?(node)
26
+ return unless in_namespace?(node)
27
+
28
+ add_offense(node, location: :name, severity: :error)
27
29
  end
28
30
 
29
31
  def in_namespace?(node)
30
32
  # parent_module_name might return nil if for instance a method is
31
33
  # defined within a block. (Apparently that is possible...)
32
34
  return false if node.parent_module_name.nil?
35
+
33
36
  namespace = SketchUp::Namespace.new(node.parent_module_name)
34
37
  namespaces.include?(namespace.first)
35
38
  end
@@ -8,7 +8,7 @@ module RuboCop
8
8
 
9
9
  # This forces the cop to be run even if there is a source code comment
10
10
  # that tries to disable it.
11
- def enabled_line?(line_number)
11
+ def enabled_line?(_line_number)
12
12
  true
13
13
  end
14
14
 
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Methods that calculate and return Parser::Source::Ranges
6
+ module RangeHelp
7
+
8
+ private
9
+
10
+ def range_with_receiver(node)
11
+ receiver = node.receiver
12
+ loc_begin = if receiver.send_type?
13
+ receiver.loc.selector.begin_pos
14
+ else
15
+ receiver.loc.expression.begin_pos
16
+ end
17
+ loc_end = node.loc.selector.end_pos
18
+ range_between(loc_begin, loc_end)
19
+ end
20
+
21
+ def string_contents_range(node)
22
+ begin_pos = node.loc.begin.end_pos
23
+ end_pos = node.loc.end.begin_pos
24
+ range_between(begin_pos, end_pos)
25
+ end
26
+
27
+ def arguments_range(node)
28
+ begin_pos = node.arguments.first.loc.expression.begin_pos
29
+ end_pos = node.arguments.last.loc.expression.end_pos
30
+ range_between(begin_pos, end_pos)
31
+ end
32
+
33
+ def conditional_range(node)
34
+ if node.modifier_form?
35
+ range_between(node.loc.keyword.begin_pos,
36
+ node.loc.expression.end_pos)
37
+ else
38
+ :expression
39
+ end
40
+ end
41
+
42
+ def file_ext_range(argument_node)
43
+ filename = argument_node.str_content
44
+ ext_size = File.extname(filename).size
45
+ end_pos = argument_node.loc.end.begin_pos
46
+ begin_pos = end_pos - ext_size
47
+ range_between(begin_pos, end_pos)
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -57,7 +57,7 @@ module RuboCop
57
57
  [7.0, 1],
58
58
  [7.0, 0],
59
59
  [6.0, 0],
60
- ]
60
+ ].freeze
61
61
 
62
62
  def parse_version(version)
63
63
  v = 0
@@ -71,12 +71,14 @@ module RuboCop
71
71
  m = (result.captures[1] || '0').to_i
72
72
  end
73
73
  elsif version.is_a?(Numeric)
74
- v, m = [version, 0]
74
+ v = version
75
+ m = 0
75
76
  end
76
77
  version_parts = [v, m]
77
78
  unless VALID_VERSIONS.include?(version_parts)
78
79
  raise InvalidVersion, "#{version} is not a valid SketchUp version"
79
80
  end
81
+
80
82
  version_parts
81
83
  end
82
84