rubocop-sketchup 0.6.0 → 0.7.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 -355
  5. data/lib/rubocop-sketchup.rb +49 -48
  6. data/lib/rubocop/sketchup.rb +12 -12
  7. data/lib/rubocop/sketchup/config.rb +63 -63
  8. data/lib/rubocop/sketchup/cop.rb +111 -111
  9. data/lib/rubocop/sketchup/cop/bugs/material_name.rb +108 -0
  10. data/lib/rubocop/sketchup/cop/bugs/render_mode.rb +72 -0
  11. data/lib/rubocop/sketchup/cop/bugs/uniform_scaling.rb +36 -0
  12. data/lib/rubocop/sketchup/cop/deprecations/add_separator_to_menu.rb +25 -25
  13. data/lib/rubocop/sketchup/cop/deprecations/operation_next_transparent.rb +30 -30
  14. data/lib/rubocop/sketchup/cop/deprecations/require_all.rb +27 -27
  15. data/lib/rubocop/sketchup/cop/deprecations/set_texture_projection.rb +26 -26
  16. data/lib/rubocop/sketchup/cop/deprecations/show_ruby_panel.rb +25 -25
  17. data/lib/rubocop/sketchup/cop/deprecations/sketchup_set.rb +30 -30
  18. data/lib/rubocop/sketchup/cop/performance/openssl.rb +41 -41
  19. data/lib/rubocop/sketchup/cop/performance/operation_disable_ui.rb +33 -33
  20. data/lib/rubocop/sketchup/cop/performance/selection_bulk.rb +79 -79
  21. data/lib/rubocop/sketchup/cop/performance/type_check.rb +63 -63
  22. data/lib/rubocop/sketchup/cop/performance/typename.rb +24 -24
  23. data/lib/rubocop/sketchup/cop/requirements/api_namespace.rb +30 -30
  24. data/lib/rubocop/sketchup/cop/requirements/exit.rb +32 -32
  25. data/lib/rubocop/sketchup/cop/requirements/extension_namespace.rb +108 -108
  26. data/lib/rubocop/sketchup/cop/requirements/file_structure.rb +97 -97
  27. data/lib/rubocop/sketchup/cop/requirements/gem_install.rb +45 -45
  28. data/lib/rubocop/sketchup/cop/requirements/get_extension_license.rb +95 -95
  29. data/lib/rubocop/sketchup/cop/requirements/global_constants.rb +38 -38
  30. data/lib/rubocop/sketchup/cop/requirements/global_include.rb +42 -42
  31. data/lib/rubocop/sketchup/cop/requirements/global_methods.rb +65 -65
  32. data/lib/rubocop/sketchup/cop/requirements/global_variables.rb +95 -95
  33. data/lib/rubocop/sketchup/cop/requirements/language_handler_globals.rb +46 -46
  34. data/lib/rubocop/sketchup/cop/requirements/load_path.rb +83 -83
  35. data/lib/rubocop/sketchup/cop/requirements/minimal_registration.rb +73 -73
  36. data/lib/rubocop/sketchup/cop/requirements/observers_start_operation.rb +161 -161
  37. data/lib/rubocop/sketchup/cop/requirements/register_extension.rb +45 -45
  38. data/lib/rubocop/sketchup/cop/requirements/ruby_core_namespace.rb +291 -291
  39. data/lib/rubocop/sketchup/cop/requirements/ruby_stdlib_namespace.rb +634 -634
  40. data/lib/rubocop/sketchup/cop/requirements/shipped_extensions_namespace.rb +61 -61
  41. data/lib/rubocop/sketchup/cop/requirements/sketchup_extension.rb +119 -119
  42. data/lib/rubocop/sketchup/cop/requirements/sketchup_require.rb +163 -163
  43. data/lib/rubocop/sketchup/cop/suggestions/add_group.rb +49 -49
  44. data/lib/rubocop/sketchup/cop/suggestions/compatibility.rb +121 -117
  45. data/lib/rubocop/sketchup/cop/suggestions/dc_internals.rb +34 -34
  46. data/lib/rubocop/sketchup/cop/suggestions/file_encoding.rb +78 -78
  47. data/lib/rubocop/sketchup/cop/suggestions/model_entities.rb +58 -58
  48. data/lib/rubocop/sketchup/cop/suggestions/monkey_patched_api.rb +45 -45
  49. data/lib/rubocop/sketchup/cop/suggestions/operation_name.rb +137 -103
  50. data/lib/rubocop/sketchup/cop/suggestions/sketchup_find_support_file.rb +39 -39
  51. data/lib/rubocop/sketchup/cop/suggestions/tool_drawing_bounds.rb +44 -44
  52. data/lib/rubocop/sketchup/cop/suggestions/tool_invalidate.rb +66 -66
  53. data/lib/rubocop/sketchup/cop/suggestions/tool_user_input.rb +41 -41
  54. data/lib/rubocop/sketchup/cop/suggestions/toolbar_timer.rb +65 -65
  55. data/lib/rubocop/sketchup/dc_globals.rb +24 -24
  56. data/lib/rubocop/sketchup/dc_methods.rb +130 -130
  57. data/lib/rubocop/sketchup/extension_project.rb +65 -65
  58. data/lib/rubocop/sketchup/features.rb +738 -738
  59. data/lib/rubocop/sketchup/formatter/extension_review.rb +269 -259
  60. data/lib/rubocop/sketchup/inject.rb +19 -19
  61. data/lib/rubocop/sketchup/namespace.rb +47 -47
  62. data/lib/rubocop/sketchup/namespace_checker.rb +46 -46
  63. data/lib/rubocop/sketchup/no_comment_disable.rb +17 -17
  64. data/lib/rubocop/sketchup/range_help.rb +52 -52
  65. data/lib/rubocop/sketchup/sketchup_target_range.rb +75 -0
  66. data/lib/rubocop/sketchup/sketchup_version.rb +117 -87
  67. data/lib/rubocop/sketchup/tool_checker.rb +43 -43
  68. data/lib/rubocop/sketchup/version.rb +5 -5
  69. data/rubocop-sketchup.gemspec +27 -27
  70. metadata +8 -4
@@ -1,19 +1,19 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- # Ripped directly from rubocop-rspec.
5
- module SketchUp
6
- # Because RuboCop doesn't yet support plugins, we have to monkey patch in a
7
- # bit of our configuration.
8
- module Inject
9
- def self.defaults!
10
- path = CONFIG_DEFAULT.to_s
11
- hash = ConfigLoader.send(:load_yaml_configuration, path)
12
- config = RuboCop::Config.new(hash, path)
13
- puts "configuration from #{path}" if ConfigLoader.debug?
14
- config = ConfigLoader.merge_with_default(config, path)
15
- ConfigLoader.instance_variable_set(:@default_configuration, config)
16
- end
17
- end
18
- end
19
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # Ripped directly from rubocop-rspec.
5
+ module SketchUp
6
+ # Because RuboCop doesn't yet support plugins, we have to monkey patch in a
7
+ # bit of our configuration.
8
+ module Inject
9
+ def self.defaults!
10
+ path = CONFIG_DEFAULT.to_s
11
+ hash = ConfigLoader.send(:load_yaml_configuration, path)
12
+ config = RuboCop::Config.new(hash, path)
13
+ puts "configuration from #{path}" if ConfigLoader.debug?
14
+ config = ConfigLoader.merge_with_default(config, path)
15
+ ConfigLoader.instance_variable_set(:@default_configuration, config)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,47 +1,47 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module SketchUp
5
- class Namespace
6
-
7
- attr_reader :namespace
8
-
9
- SEPARATOR = '::'.freeze
10
-
11
- # @param [String] namespace
12
- def initialize(namespace)
13
- raise TypeError unless namespace.is_a?(String)
14
-
15
- @namespace = namespace
16
- end
17
-
18
- # Get the first component of a namespace relative to Object.
19
- # May return 'Object' if the namespace is in the global namespace.
20
- def first
21
- parts.find { |name| name != 'Object' } || 'Object'
22
- end
23
-
24
- # Get a namespace string that is relative to Object.
25
- def from_root
26
- items = parts
27
- items.shift if items.size > 1 && items.first == 'Object'
28
- items.join(SEPARATOR)
29
- end
30
-
31
- def join(other)
32
- self.class.new("#{@namespace}#{SEPARATOR}#{other}")
33
- end
34
-
35
- # Get the first component of a namespace relative to Object.
36
- # May return 'Object' if the namespace is in the global namespace.
37
- def parts
38
- namespace.split(SEPARATOR)
39
- end
40
-
41
- def top_level?
42
- %w[Kernel Object].include?(parts.first)
43
- end
44
-
45
- end
46
- end
47
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module SketchUp
5
+ class Namespace
6
+
7
+ attr_reader :namespace
8
+
9
+ SEPARATOR = '::'.freeze
10
+
11
+ # @param [String] namespace
12
+ def initialize(namespace)
13
+ raise TypeError unless namespace.is_a?(String)
14
+
15
+ @namespace = namespace
16
+ end
17
+
18
+ # Get the first component of a namespace relative to Object.
19
+ # May return 'Object' if the namespace is in the global namespace.
20
+ def first
21
+ parts.find { |name| name != 'Object' } || 'Object'
22
+ end
23
+
24
+ # Get a namespace string that is relative to Object.
25
+ def from_root
26
+ items = parts
27
+ items.shift if items.size > 1 && items.first == 'Object'
28
+ items.join(SEPARATOR)
29
+ end
30
+
31
+ def join(other)
32
+ self.class.new("#{@namespace}#{SEPARATOR}#{other}")
33
+ end
34
+
35
+ # Get the first component of a namespace relative to Object.
36
+ # May return 'Object' if the namespace is in the global namespace.
37
+ def parts
38
+ namespace.split(SEPARATOR)
39
+ end
40
+
41
+ def top_level?
42
+ %w[Kernel Object].include?(parts.first)
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -1,46 +1,46 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module SketchUp
5
- module NamespaceChecker
6
-
7
- def on_class(node)
8
- check_namespace(node)
9
- end
10
-
11
- def on_module(node)
12
- check_namespace(node)
13
- end
14
-
15
- def on_def(node)
16
- check_namespace(node)
17
- end
18
- alias on_defs on_def
19
-
20
- # Constant assignment.
21
- def on_casgn(node)
22
- check_namespace(node)
23
- end
24
-
25
- def check_namespace(node)
26
- return unless in_namespace?(node)
27
-
28
- add_offense(node, location: :name, severity: :error)
29
- end
30
-
31
- def in_namespace?(node)
32
- # parent_module_name might return nil if for instance a method is
33
- # defined within a block. (Apparently that is possible...)
34
- return false if node.parent_module_name.nil?
35
-
36
- namespace = SketchUp::Namespace.new(node.parent_module_name)
37
- namespaces.include?(namespace.first)
38
- end
39
-
40
- def namespaces
41
- raise NotImplementedError
42
- end
43
-
44
- end
45
- end
46
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module SketchUp
5
+ module NamespaceChecker
6
+
7
+ def on_class(node)
8
+ check_namespace(node)
9
+ end
10
+
11
+ def on_module(node)
12
+ check_namespace(node)
13
+ end
14
+
15
+ def on_def(node)
16
+ check_namespace(node)
17
+ end
18
+ alias on_defs on_def
19
+
20
+ # Constant assignment.
21
+ def on_casgn(node)
22
+ check_namespace(node)
23
+ end
24
+
25
+ def check_namespace(node)
26
+ return unless in_namespace?(node)
27
+
28
+ add_offense(node, location: :name, severity: :error)
29
+ end
30
+
31
+ def in_namespace?(node)
32
+ # parent_module_name might return nil if for instance a method is
33
+ # defined within a block. (Apparently that is possible...)
34
+ return false if node.parent_module_name.nil?
35
+
36
+ namespace = SketchUp::Namespace.new(node.parent_module_name)
37
+ namespaces.include?(namespace.first)
38
+ end
39
+
40
+ def namespaces
41
+ raise NotImplementedError
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -1,17 +1,17 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module SketchUp
5
- module NoCommentDisable
6
-
7
- private
8
-
9
- # This forces the cop to be run even if there is a source code comment
10
- # that tries to disable it.
11
- def enabled_line?(_line_number)
12
- true
13
- end
14
-
15
- end
16
- end
17
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module SketchUp
5
+ module NoCommentDisable
6
+
7
+ private
8
+
9
+ # This forces the cop to be run even if there is a source code comment
10
+ # that tries to disable it.
11
+ def enabled_line?(_line_number)
12
+ true
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -1,52 +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
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
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module SketchUp
5
+ # Mix-in module for Cops that are valid only for a given SketchUp version
6
+ # range. This mix-in uses the configured target SketchUp version to
7
+ # determine if it's relevant.
8
+ module SketchUpTargetRange
9
+
10
+ module ClassMethods
11
+
12
+ # @param [String] version
13
+ def define_sketchup_target_min_version(version)
14
+ @sketchup_target_min_version = SketchUpVersion.new(version)
15
+ nil
16
+ end
17
+
18
+ # @param [String] version
19
+ def define_sketchup_target_max_version(version)
20
+ @sketchup_target_max_version = SketchUpVersion.new(version)
21
+ nil
22
+ end
23
+
24
+ def sketchup_target_min_version
25
+ @sketchup_target_min_version
26
+ end
27
+
28
+ def sketchup_target_max_version
29
+ @sketchup_target_max_version
30
+ end
31
+
32
+ end # module ClassMethods
33
+
34
+ def self.included(mod)
35
+ mod.extend(ClassMethods)
36
+ end
37
+
38
+ def sketchup_target_min_version
39
+ self.class.sketchup_target_min_version
40
+ end
41
+
42
+ def sketchup_target_max_version
43
+ self.class.sketchup_target_max_version
44
+ end
45
+
46
+ def valid_for_target_sketchup_version?
47
+ # If no target version is configured, ignore this check.
48
+ return true unless sketchup_target_version?
49
+
50
+ # If no version is set - then it's valid for all known versions.
51
+ unless sketchup_target_min_version || sketchup_target_max_version
52
+ return true
53
+ end
54
+
55
+ # If there is a finite version range, check if the target SketchUp
56
+ # version is withing that.
57
+ if sketchup_target_min_version && sketchup_target_max_version
58
+ range = (sketchup_target_min_version..sketchup_target_max_version)
59
+ return range.include?(sketchup_target_version)
60
+ end
61
+
62
+ if sketchup_target_min_version
63
+ return sketchup_target_version >= sketchup_target_min_version
64
+ end
65
+
66
+ if sketchup_target_max_version
67
+ return sketchup_target_version <= sketchup_target_max_version
68
+ end
69
+
70
+ raise 'bug!' # Should not end up here.
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -1,87 +1,117 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module SketchUp
5
- class SketchUpVersion
6
-
7
- include Comparable
8
-
9
- attr_reader :version, :maintenance
10
-
11
- class InvalidVersion < StandardError; end
12
-
13
- def initialize(version)
14
- @version, @maintenance = parse_version(version)
15
- end
16
-
17
- def <=>(other)
18
- if version == other.version
19
- maintenance <=> other.maintenance
20
- else
21
- version <=> other.version
22
- end
23
- end
24
-
25
- def to_s
26
- string_version = version < 2013 ? version.to_f : version.to_i
27
- if maintenance > 0
28
- "SketchUp #{string_version} M#{maintenance}"
29
- else
30
- "SketchUp #{string_version}"
31
- end
32
- end
33
-
34
- private
35
-
36
- VERSION_NUMBER_REGEX = /^(?:SketchUp )?([0-9.]+)(?: M(\d+))?$/.freeze
37
-
38
- # This list is compiled from the list of versions reported by YARD when
39
- # running the `versions` template;
40
- #
41
- # yardoc -t versions -f text
42
- #
43
- # TODO(thomthom): Push the version template to the API stubs repository.
44
- VALID_VERSIONS = [
45
- [2018, 0],
46
- [2017, 0],
47
- [2016, 1],
48
- [2016, 0],
49
- [2015, 0],
50
- [2014, 0],
51
- [2013, 0],
52
- [8.0, 2],
53
- [8.0, 1],
54
- [8.0, 0],
55
- [7.1, 1],
56
- [7.1, 0],
57
- [7.0, 1],
58
- [7.0, 0],
59
- [6.0, 0],
60
- ].freeze
61
-
62
- def parse_version(version)
63
- v = 0
64
- m = 0
65
- if version.is_a?(String)
66
- # Treat all LayOut versions as SketchUp versions for now.
67
- normalised_version = version.gsub('LayOut', 'SketchUp')
68
- result = normalised_version.match(VERSION_NUMBER_REGEX)
69
- if result
70
- v = result.captures[0].to_f
71
- m = (result.captures[1] || '0').to_i
72
- end
73
- elsif version.is_a?(Numeric)
74
- v = version
75
- m = 0
76
- end
77
- version_parts = [v, m]
78
- unless VALID_VERSIONS.include?(version_parts)
79
- raise InvalidVersion, "#{version} is not a valid SketchUp version"
80
- end
81
-
82
- version_parts
83
- end
84
-
85
- end
86
- end
87
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module SketchUp
5
+ class SketchUpVersion
6
+
7
+ include Comparable
8
+
9
+ attr_reader :version, :maintenance
10
+
11
+ class InvalidVersion < StandardError; end
12
+
13
+ # @overload initialize(version_string)
14
+ # @param [String] version_string
15
+ #
16
+ # @overload initialize(version, maintenance)
17
+ # @param [Integer, Float] version
18
+ # @param [Integer] maintenance
19
+ def initialize(*args)
20
+ if args.size == 1
21
+ @version, @maintenance = parse_version(args.first)
22
+ elsif args.size == 2
23
+ validate(args)
24
+ @version, @maintenance = args
25
+ else
26
+ raise ArgumentError, "expected 1..2 arguments, got #{args.size}"
27
+ end
28
+ end
29
+
30
+ # @return [SketchUpVersion, nil]
31
+ def succ
32
+ version_parts = [@version, @maintenance]
33
+ index = VALID_VERSIONS.index(version_parts)
34
+ next_version_parts = VALID_VERSIONS[index + 1]
35
+ return nil if next_version_parts.nil?
36
+
37
+ self.class.new(*next_version_parts)
38
+ end
39
+
40
+ def <=>(other)
41
+ if version == other.version
42
+ maintenance <=> other.maintenance
43
+ else
44
+ version <=> other.version
45
+ end
46
+ end
47
+
48
+ # @return [String]
49
+ def to_s
50
+ string_version = version < 2013 ? version.to_f : version.to_i
51
+ if maintenance > 0
52
+ "SketchUp #{string_version} M#{maintenance}"
53
+ else
54
+ "SketchUp #{string_version}"
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ VERSION_NUMBER_REGEX = /^(?:SketchUp )?([0-9.]+)(?: M(\d+))?$/.freeze
61
+
62
+ # This list is compiled from the list of versions reported by YARD when
63
+ # running the `versions` template;
64
+ #
65
+ # yardoc -t versions -f text
66
+ #
67
+ # TODO(thomthom): Push the version template to the API stubs repository.
68
+ VALID_VERSIONS = [
69
+ [2018, 0],
70
+ [2017, 0],
71
+ [2016, 1],
72
+ [2016, 0],
73
+ [2015, 0],
74
+ [2014, 0],
75
+ [2013, 0],
76
+ [8.0, 2],
77
+ [8.0, 1],
78
+ [8.0, 0],
79
+ [7.1, 1],
80
+ [7.1, 0],
81
+ [7.0, 1],
82
+ [7.0, 0],
83
+ [6.0, 0],
84
+ ].reverse.freeze
85
+
86
+ # @param [String] version
87
+ # @return [Array(Float, Integer)]
88
+ def parse_version(version)
89
+ v = 0
90
+ m = 0
91
+ if version.is_a?(String)
92
+ # Treat all LayOut versions as SketchUp versions for now.
93
+ normalized_version = version.gsub('LayOut', 'SketchUp')
94
+ result = normalized_version.match(VERSION_NUMBER_REGEX)
95
+ if result
96
+ v = result.captures[0].to_f
97
+ m = (result.captures[1] || '0').to_i
98
+ end
99
+ elsif version.is_a?(Numeric)
100
+ v = version
101
+ m = 0
102
+ end
103
+ validate([v, m])
104
+ end
105
+
106
+ # @param [Array(Float, Integer)] version_parts
107
+ def validate(version_parts)
108
+ unless VALID_VERSIONS.include?(version_parts)
109
+ raise InvalidVersion, "#{version} is not a valid SketchUp version"
110
+ end
111
+
112
+ version_parts
113
+ end
114
+
115
+ end
116
+ end
117
+ end