rubocop-sketchup 1.2.0 → 1.4.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 (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,95 +1,95 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
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
- #
13
- # This cops looks for uses of global variables.
14
- # It does not report offenses for built-in global variables.
15
- # Built-in global variables are allowed by default. Additionally
16
- # users can allow additional variables via the AllowedVariables option.
17
- #
18
- # Note that backreferences like `$1`, `$2`, etc are not global variables.
19
- class GlobalVariables < SketchUp::Cop
20
-
21
- include SketchUp::NoCommentDisable
22
- include SketchUp::DynamicComponentGlobals
23
-
24
- MSG = 'Do not introduce global variables.'
25
-
26
- # predefined global variables their English aliases
27
- # http://www.zenspider.com/Languages/Ruby/QuickRef.html
28
- BUILT_IN_VARS = %i[
29
- $: $LOAD_PATH
30
- $" $LOADED_FEATURES
31
- $0 $PROGRAM_NAME
32
- $! $ERROR_INFO
33
- $@ $ERROR_POSITION
34
- $; $FS $FIELD_SEPARATOR
35
- $, $OFS $OUTPUT_FIELD_SEPARATOR
36
- $/ $RS $INPUT_RECORD_SEPARATOR
37
- $\\ $ORS $OUTPUT_RECORD_SEPARATOR
38
- $. $NR $INPUT_LINE_NUMBER
39
- $_ $LAST_READ_LINE
40
- $> $DEFAULT_OUTPUT
41
- $< $DEFAULT_INPUT
42
- $$ $PID $PROCESS_ID
43
- $? $CHILD_STATUS
44
- $~ $LAST_MATCH_INFO
45
- $= $IGNORECASE
46
- $* $ARGV
47
- $& $MATCH
48
- $` $PREMATCH
49
- $' $POSTMATCH
50
- $+ $LAST_PAREN_MATCH
51
- $stdin $stdout $stderr
52
- $DEBUG $FILENAME $VERBOSE $SAFE
53
- $-0 $-a $-d $-F $-i $-I $-l $-p $-v $-w
54
- $CLASSPATH $JRUBY_VERSION $JRUBY_REVISION $ENV_JAVA
55
- ].freeze
56
-
57
- SKETCHUP_VARS = %i[
58
- $loaded_files
59
- ].freeze
60
-
61
- # Some globals, like DC's, are being read from so often that it's better
62
- # to ignore these to reduce noise.
63
- READ_ONLY_VARS = DC_GLOBALS
64
-
65
- ALLOWED_VARS = BUILT_IN_VARS | SKETCHUP_VARS
66
-
67
-
68
- def allowed_var?(global_var)
69
- ALLOWED_VARS.include?(global_var)
70
- end
71
-
72
- def read_allowed?(global_var)
73
- READ_ONLY_VARS.include?(global_var)
74
- end
75
-
76
- def on_gvar(node)
77
- global_var, = *node
78
- check(node) unless read_allowed?(global_var)
79
- end
80
-
81
- def on_gvasgn(node)
82
- check(node)
83
- end
84
-
85
- def check(node)
86
- global_var, = *node
87
-
88
- return if allowed_var?(global_var)
89
-
90
- add_offense(node, location: :name)
91
- end
92
- end
93
- end
94
- end
95
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
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
+ #
13
+ # This cops looks for uses of global variables.
14
+ # It does not report offenses for built-in global variables.
15
+ # Built-in global variables are allowed by default. Additionally
16
+ # users can allow additional variables via the AllowedVariables option.
17
+ #
18
+ # Note that backreferences like `$1`, `$2`, etc are not global variables.
19
+ class GlobalVariables < SketchUp::Cop
20
+
21
+ include SketchUp::NoCommentDisable
22
+ include SketchUp::DynamicComponentGlobals
23
+
24
+ MSG = 'Do not introduce global variables.'
25
+
26
+ # predefined global variables their English aliases
27
+ # http://www.zenspider.com/Languages/Ruby/QuickRef.html
28
+ BUILT_IN_VARS = %i[
29
+ $: $LOAD_PATH
30
+ $" $LOADED_FEATURES
31
+ $0 $PROGRAM_NAME
32
+ $! $ERROR_INFO
33
+ $@ $ERROR_POSITION
34
+ $; $FS $FIELD_SEPARATOR
35
+ $, $OFS $OUTPUT_FIELD_SEPARATOR
36
+ $/ $RS $INPUT_RECORD_SEPARATOR
37
+ $\\ $ORS $OUTPUT_RECORD_SEPARATOR
38
+ $. $NR $INPUT_LINE_NUMBER
39
+ $_ $LAST_READ_LINE
40
+ $> $DEFAULT_OUTPUT
41
+ $< $DEFAULT_INPUT
42
+ $$ $PID $PROCESS_ID
43
+ $? $CHILD_STATUS
44
+ $~ $LAST_MATCH_INFO
45
+ $= $IGNORECASE
46
+ $* $ARGV
47
+ $& $MATCH
48
+ $` $PREMATCH
49
+ $' $POSTMATCH
50
+ $+ $LAST_PAREN_MATCH
51
+ $stdin $stdout $stderr
52
+ $DEBUG $FILENAME $VERBOSE $SAFE
53
+ $-0 $-a $-d $-F $-i $-I $-l $-p $-v $-w
54
+ $CLASSPATH $JRUBY_VERSION $JRUBY_REVISION $ENV_JAVA
55
+ ].freeze
56
+
57
+ SKETCHUP_VARS = %i[
58
+ $loaded_files
59
+ ].freeze
60
+
61
+ # Some globals, like DC's, are being read from so often that it's better
62
+ # to ignore these to reduce noise.
63
+ READ_ONLY_VARS = DC_GLOBALS
64
+
65
+ ALLOWED_VARS = BUILT_IN_VARS | SKETCHUP_VARS
66
+
67
+
68
+ def allowed_var?(global_var)
69
+ ALLOWED_VARS.include?(global_var)
70
+ end
71
+
72
+ def read_allowed?(global_var)
73
+ READ_ONLY_VARS.include?(global_var)
74
+ end
75
+
76
+ def on_gvar(node)
77
+ global_var, = *node
78
+ check(node) unless read_allowed?(global_var)
79
+ end
80
+
81
+ def on_gvasgn(node)
82
+ check(node)
83
+ end
84
+
85
+ def check(node)
86
+ global_var, = *node
87
+
88
+ return if allowed_var?(global_var)
89
+
90
+ add_offense(node, location: :name)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -1,46 +1,46 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module SketchupRequirements
6
- # Avoid using globals in general, but especially these which are known to
7
- # be in use by other extensions made by SketchUp.
8
- # They are still in use due to compatibility reasons.
9
- class LanguageHandlerGlobals < SketchUp::Cop
10
-
11
- include SketchUp::NoCommentDisable
12
-
13
- MSG = 'Avoid globals in general, but especially these which are known '\
14
- 'to be in use.'
15
-
16
- LH_GLOBALS = %i[
17
- $dc_strings
18
- $devl_strings
19
- $exStrings
20
- $fs_strings
21
- $make_pano_string
22
- $oceanStrings
23
- $sn_strings
24
- $ssf_strings
25
- $suStrings
26
- $tStrings
27
- $unitsStrings
28
- $uStrings
29
- $wt_strings
30
- ].freeze
31
-
32
- def hl_global_var?(global_var)
33
- LH_GLOBALS.include?(global_var)
34
- end
35
-
36
- def on_gvasgn(node)
37
- global_var, = *node
38
- return unless hl_global_var?(global_var)
39
-
40
- add_offense(node, location: :name)
41
- end
42
-
43
- end
44
- end
45
- end
46
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupRequirements
6
+ # Avoid using globals in general, but especially these which are known to
7
+ # be in use by other extensions made by SketchUp.
8
+ # They are still in use due to compatibility reasons.
9
+ class LanguageHandlerGlobals < SketchUp::Cop
10
+
11
+ include SketchUp::NoCommentDisable
12
+
13
+ MSG = 'Avoid globals in general, but especially these which are ' \
14
+ 'known to be in use.'
15
+
16
+ LH_GLOBALS = %i[
17
+ $dc_strings
18
+ $devl_strings
19
+ $exStrings
20
+ $fs_strings
21
+ $make_pano_string
22
+ $oceanStrings
23
+ $sn_strings
24
+ $ssf_strings
25
+ $suStrings
26
+ $tStrings
27
+ $unitsStrings
28
+ $uStrings
29
+ $wt_strings
30
+ ].freeze
31
+
32
+ def hl_global_var?(global_var)
33
+ LH_GLOBALS.include?(global_var)
34
+ end
35
+
36
+ def on_gvasgn(node)
37
+ global_var, = *node
38
+ return unless hl_global_var?(global_var)
39
+
40
+ add_offense(node, location: :name)
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,83 +1,83 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module SketchupRequirements
6
- # Do not modify the load path. Modifying `$LOAD_PATH` is bad practice
7
- # because it can cause extensions to inadvertently load the wrong file.
8
- class LoadPath < SketchUp::Cop
9
-
10
- include SketchUp::NoCommentDisable
11
-
12
- MSG = 'Do not modify the load path.'
13
-
14
- def_node_matcher :load_path_mutator?, <<-PATTERN
15
- (send
16
- (gvar #load_path?) $#mutator?
17
- ...
18
- )
19
- PATTERN
20
-
21
- LOAD_PATH_ALIASES = %i[
22
- $: $LOAD_PATH
23
- ].freeze
24
-
25
- MUTATORS = %i[
26
- <<
27
- []=
28
- clear
29
- collect!
30
- compact!
31
- concat
32
- delete
33
- delete_at
34
- delete_if
35
- drop
36
- drop_while
37
- fill
38
- flatten!
39
- insert
40
- keep_if
41
- map!
42
- pop
43
- push
44
- reject!
45
- replace
46
- reverse!
47
- rotate!
48
- select!
49
- shift
50
- shuffle!
51
- slice!
52
- sort!
53
- sort_by!
54
- uniq!
55
- unshift
56
- ].freeze
57
-
58
- def load_path?(sym)
59
- LOAD_PATH_ALIASES.include?(sym)
60
- end
61
-
62
- def mutator?(sym)
63
- MUTATORS.include?(sym)
64
- end
65
-
66
- def on_gvasgn(node)
67
- global_var, = *node
68
- return unless load_path?(global_var)
69
-
70
- add_offense(node, location: :expression)
71
- end
72
-
73
- def on_send(node)
74
- method_name = load_path_mutator?(node)
75
- return unless method_name
76
-
77
- add_offense(node, location: :expression)
78
- end
79
-
80
- end
81
- end
82
- end
83
- end
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupRequirements
6
+ # Do not modify the load path. Modifying `$LOAD_PATH` is bad practice
7
+ # because it can cause extensions to inadvertently load the wrong file.
8
+ class LoadPath < SketchUp::Cop
9
+
10
+ include SketchUp::NoCommentDisable
11
+
12
+ MSG = 'Do not modify the load path.'
13
+
14
+ def_node_matcher :load_path_mutator?, <<-PATTERN
15
+ (send
16
+ (gvar #load_path?) $#mutator?
17
+ ...
18
+ )
19
+ PATTERN
20
+
21
+ LOAD_PATH_ALIASES = %i[
22
+ $: $LOAD_PATH
23
+ ].freeze
24
+
25
+ MUTATORS = %i[
26
+ <<
27
+ []=
28
+ clear
29
+ collect!
30
+ compact!
31
+ concat
32
+ delete
33
+ delete_at
34
+ delete_if
35
+ drop
36
+ drop_while
37
+ fill
38
+ flatten!
39
+ insert
40
+ keep_if
41
+ map!
42
+ pop
43
+ push
44
+ reject!
45
+ replace
46
+ reverse!
47
+ rotate!
48
+ select!
49
+ shift
50
+ shuffle!
51
+ slice!
52
+ sort!
53
+ sort_by!
54
+ uniq!
55
+ unshift
56
+ ].freeze
57
+
58
+ def load_path?(sym)
59
+ LOAD_PATH_ALIASES.include?(sym)
60
+ end
61
+
62
+ def mutator?(sym)
63
+ MUTATORS.include?(sym)
64
+ end
65
+
66
+ def on_gvasgn(node)
67
+ global_var, = *node
68
+ return unless load_path?(global_var)
69
+
70
+ add_offense(node, location: :expression)
71
+ end
72
+
73
+ def on_send(node)
74
+ method_name = load_path_mutator?(node)
75
+ return unless method_name
76
+
77
+ add_offense(node, location: :expression)
78
+ end
79
+
80
+ end
81
+ end
82
+ end
83
+ end
@@ -1,73 +1,73 @@
1
- # frozen_string_literal: true
2
-
3
- require 'pathname'
4
-
5
- module RuboCop
6
- module Cop
7
- module SketchupRequirements
8
- # Don't load extension files in the root file registering the extension.
9
- # Extensions should not load additional files when it's disabled.
10
- #
11
- # @example Bad - Extension will always load.
12
- # module Example
13
- # require 'example/main' # BAD! This will load even when extension
14
- # # is disabled.
15
- # unless file_loaded?(__FILE__)
16
- # extension = SketchupExtension.new('Hello World', 'example/main')
17
- # Sketchup.register_extension(extension, true)
18
- # file_loaded(__FILE__)
19
- # end
20
- # end
21
- #
22
- # @example Good - Extension doesn't load anything unless its enabled.
23
- # module Example
24
- # unless file_loaded?(__FILE__)
25
- # extension = SketchupExtension.new('Hello World', 'example/main')
26
- # Sketchup.register_extension(extension, true)
27
- # file_loaded(__FILE__)
28
- # end
29
- # end
30
- class MinimalRegistration < SketchUp::Cop
31
-
32
- include SketchUp::NoCommentDisable
33
- include SketchUp::ExtensionProject
34
-
35
- MSG = "Don't load extension files in the root file registering the "\
36
- 'extension.'
37
-
38
- # Reference: http://rubocop.readthedocs.io/en/latest/node_pattern/
39
- def_node_matcher :require_filename, <<-PATTERN
40
- {
41
- (send {(const nil? :Sketchup) nil?} {:require :load} (str $_))
42
- (send nil? :require_relative (str $_))
43
- }
44
- PATTERN
45
-
46
- def investigate(processed_source)
47
- if root_file?(processed_source)
48
- filename = processed_source.buffer.name
49
- @extension_basename = File.basename(filename, '.*')
50
- end
51
- end
52
-
53
- def extension_file?(filename)
54
- return false unless filename.include?('/')
55
-
56
- first_directory = filename.split('/').first
57
- @extension_basename.casecmp(first_directory) == 0
58
- end
59
-
60
- def on_send(node)
61
- return unless @extension_basename
62
-
63
- filename = require_filename(node)
64
- return if filename.nil?
65
- return unless extension_file?(filename)
66
-
67
- add_offense(node)
68
- end
69
-
70
- end
71
- end
72
- end
73
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+
5
+ module RuboCop
6
+ module Cop
7
+ module SketchupRequirements
8
+ # Don't load extension files in the root file registering the extension.
9
+ # Extensions should not load additional files when it's disabled.
10
+ #
11
+ # @example Bad - Extension will always load.
12
+ # module Example
13
+ # require 'example/main' # BAD! This will load even when extension
14
+ # # is disabled.
15
+ # unless file_loaded?(__FILE__)
16
+ # extension = SketchupExtension.new('Hello World', 'example/main')
17
+ # Sketchup.register_extension(extension, true)
18
+ # file_loaded(__FILE__)
19
+ # end
20
+ # end
21
+ #
22
+ # @example Good - Extension doesn't load anything unless its enabled.
23
+ # module Example
24
+ # unless file_loaded?(__FILE__)
25
+ # extension = SketchupExtension.new('Hello World', 'example/main')
26
+ # Sketchup.register_extension(extension, true)
27
+ # file_loaded(__FILE__)
28
+ # end
29
+ # end
30
+ class MinimalRegistration < SketchUp::Cop
31
+
32
+ include SketchUp::NoCommentDisable
33
+ include SketchUp::ExtensionProject
34
+
35
+ MSG = "Don't load extension files in the root file registering the " \
36
+ 'extension.'
37
+
38
+ # Reference: http://rubocop.readthedocs.io/en/latest/node_pattern/
39
+ def_node_matcher :require_filename, <<-PATTERN
40
+ {
41
+ (send {(const nil? :Sketchup) nil?} {:require :load} (str $_))
42
+ (send nil? :require_relative (str $_))
43
+ }
44
+ PATTERN
45
+
46
+ def investigate(processed_source)
47
+ if root_file?(processed_source)
48
+ filename = processed_source.buffer.name
49
+ @extension_basename = File.basename(filename, '.*')
50
+ end
51
+ end
52
+
53
+ def extension_file?(filename)
54
+ return false unless filename.include?('/')
55
+
56
+ first_directory = filename.split('/').first
57
+ @extension_basename.casecmp(first_directory) == 0
58
+ end
59
+
60
+ def on_send(node)
61
+ return unless @extension_basename
62
+
63
+ filename = require_filename(node)
64
+ return if filename.nil?
65
+ return unless extension_file?(filename)
66
+
67
+ add_offense(node)
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end