rubocop-sketchup 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fba3184334c70efb554cf67e75f076c52364e70e
4
+ data.tar.gz: f6e53f835f85a1a6a431901a0a4b9ee734a205df
5
+ SHA512:
6
+ metadata.gz: e3f65b200bc51f212498cfd5fde5d311e3b0279f92c44832d60a5ceb2d54828bd423c0aa4e24abdc3abc8ccdd10d890d2df38cefb9c399cf8a486248b16d62fc
7
+ data.tar.gz: 6ed3c4b0f7203e628108d688a4ee5a11e2be2c40abb6e1d4e4dfd67e9c3464aeb5df893876aa4b288cdc0c7faca2f7e9dd8c516c833971382fc0cef87d20bf67
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'rake', '~> 10.0', require: false
7
+ gem 'rspec', '~> 3.4', require: false
8
+ end
@@ -0,0 +1,12 @@
1
+ require 'rubocop'
2
+ require 'rubocop/sketchup/version'
3
+
4
+ require 'rubocop/sketchup/namespace'
5
+ require 'rubocop/sketchup/namespace_checker'
6
+ require 'rubocop/sketchup/no_comment_disable'
7
+
8
+ # Load all custom cops.
9
+ pattern = File.join(__dir__, 'rubocop', 'sketchup', '**/*rb')
10
+ Dir.glob(pattern) { |file|
11
+ require file
12
+ }
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupDeprecations
6
+ # Weak warning. (Question?)
7
+ class OperationNextTransparent < Cop
8
+ MSG = 'Third argument is deprecated.'.freeze
9
+
10
+ def on_send(node)
11
+ _, method_name, *args = *node
12
+ return unless method_name == :start_operation
13
+ return if args.size < 3
14
+ argument = args[2]
15
+ next_transparent = argument.type == :true
16
+ add_offense(argument, :expression) if next_transparent
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchUp
6
+ class Namespace
7
+
8
+ attr_reader :namespace
9
+
10
+ SEPARATOR = '::'.freeze
11
+
12
+ # @param [String] namespace
13
+ def initialize(namespace)
14
+ @namespace = namespace
15
+ end
16
+
17
+ # Get the first component of a namespace relative to Object.
18
+ # May return 'Object' if the namespace is in the global namespace.
19
+ def first
20
+ parts.find { |name| name != 'Object' } || 'Object'
21
+ end
22
+
23
+ # Get a namespace string that is relative to Object.
24
+ def from_root
25
+ items = parts
26
+ items.shift if items.size > 1 && items.first == 'Object'
27
+ items.join(SEPARATOR)
28
+ end
29
+
30
+ def join(other)
31
+ self.class.new("#{@namespace}#{SEPARATOR}#{other}")
32
+ end
33
+
34
+ # Get the first component of a namespace relative to Object.
35
+ # May return 'Object' if the namespace is in the global namespace.
36
+ def parts
37
+ namespace.split(SEPARATOR)
38
+ end
39
+
40
+ def top_level?
41
+ parts.last == 'Object'
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Sketchup
6
+ module NamespaceChecker
7
+
8
+ include OnMethodDef
9
+
10
+ def on_class(node)
11
+ check_namespace(node)
12
+ end
13
+
14
+ def on_module(node)
15
+ check_namespace(node)
16
+ end
17
+
18
+ def on_method_def(node, method_name, _args, _body)
19
+ check_namespace(node)
20
+ end
21
+
22
+ # Constant assignment.
23
+ def on_casgn(node)
24
+ check_namespace(node)
25
+ end
26
+
27
+ def check_namespace(node)
28
+ add_offense(node, :name, nil, :error) if in_namespace?(node)
29
+ end
30
+
31
+ def in_namespace?(node)
32
+ namespace = SketchUp::Namespace.new(node.parent_module_name)
33
+ namespaces.include?(namespace.first)
34
+ end
35
+
36
+ def namespaces
37
+ raise NotImplementedError
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
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
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupPerformance
6
+ # Weak warning. (Question?)
7
+ class OperationDisableUI < Cop
8
+ MSG = 'Operations should disable the UI for performance gain.'.freeze
9
+
10
+ def on_send(node)
11
+ _, method_name, *args = *node
12
+ return unless method_name == :start_operation
13
+ if args.size < 2
14
+ add_offense(node, :expression)
15
+ return
16
+ end
17
+ argument = args[1]
18
+ disable_ui = argument.children.first
19
+ return if disable_ui
20
+ add_offense(argument, :expression)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupPerformance
6
+ class Typename < Cop
7
+ MSG = '.typename is very slow, prefer .is_a? instead.'.freeze
8
+
9
+ def on_send(node)
10
+ _, method_name = *node
11
+ return unless method_name == :typename
12
+ # TODO(thomthom): Should we try to detect use of #typename
13
+ # in context of comparing against a string?
14
+ add_offense(node, :expression)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupRequirements
6
+ class ApiNamespace < Cop
7
+
8
+ include NoCommentDisable
9
+ include Sketchup::NamespaceChecker
10
+
11
+ MSG = 'Do not modify the SketchUp API.'.freeze
12
+
13
+ NAMESPACES = %w(
14
+ Geom Layout Sketchup SketchupExtension UI
15
+ ).freeze
16
+
17
+ def namespaces
18
+ NAMESPACES
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop/sketchup/requirements/api_namespace'
4
+ require 'rubocop/sketchup/requirements/ruby_core_namespace'
5
+ require 'rubocop/sketchup/requirements/ruby_stdlib_namespace'
6
+
7
+ module RuboCop
8
+ module Cop
9
+ module SketchupRequirements
10
+ class ExtensionNamespace < Cop
11
+
12
+ include NoCommentDisable
13
+ include SketchUp
14
+
15
+ def on_class(node)
16
+ check_class_or_module(node)
17
+ end
18
+
19
+ def on_module(node)
20
+ check_class_or_module(node)
21
+ end
22
+
23
+ def check_class_or_module(node)
24
+ name = node.defined_module_name
25
+ parent = Namespace.new(node.parent_module_name)
26
+ # Don't want to process anything that aren't top level namespaces.
27
+ return unless parent.top_level?
28
+ check_namespace(node, parent.join(name))
29
+ end
30
+
31
+ # Class variables are normally frowned upon since they leak through all
32
+ # instances. However, in this case this is exactly what we want.
33
+ # The Cop picks up the first top level namespace it encounters and then
34
+ # keep track of whether it detects more top level namespaces.
35
+ @@namespace = nil
36
+ def check_namespace(node, namespace)
37
+ # Make sure the namespace isn't part of reserved namespaces that other
38
+ # cops are checking.
39
+ return if reserved?(namespace)
40
+ # Remember the first namespace encountered and log an offence if
41
+ # more top level namespaces are registered.
42
+ top = namespace.first
43
+ @@namespace ||= top
44
+ return if @@namespace == top
45
+ add_offense(node, :name, nil, :error)
46
+ end
47
+
48
+ def reserved?(namespace)
49
+ top = namespace.first
50
+ return true if RubyCoreNamespace::NAMESPACES.include?(top)
51
+ return true if RubyStdLibNamespace::NAMESPACES.include?(top)
52
+ return true if ApiNamespace::NAMESPACES.include?(top)
53
+ false
54
+ end
55
+
56
+ def message(node)
57
+ namespace = Namespace.new(node.defined_module_name).from_root
58
+ format('Use a single root namespace. (Found %s; Previously found %s)', namespace, @@namespace)
59
+ end
60
+
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupRequirements
6
+ class GlobalConstants < Cop
7
+
8
+ include NoCommentDisable
9
+ include SketchUp
10
+
11
+ MSG = 'Do not introduce global constants.'.freeze
12
+
13
+ # Constant assignment.
14
+ def on_casgn(node)
15
+ namespace = Namespace.new(node.parent_module_name)
16
+ add_offense(node, :name, nil, :error) if namespace.top_level?
17
+ end
18
+
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupRequirements
6
+ class GlobalMethods < Cop
7
+
8
+ include NoCommentDisable
9
+ include OnMethodDef
10
+ include SketchUp
11
+
12
+ MSG = 'Do not introduce global methods.'.freeze
13
+
14
+ # Reference: http://www.rubydoc.info/gems/rubocop/RuboCop/NodePattern
15
+ #
16
+ # Matchers for methods defined with this syntax:
17
+ #
18
+ # def Example.foo
19
+ # end
20
+ #
21
+ # def (Example::Foo).bar
22
+ # end
23
+
24
+ def_node_matcher :class_method?, <<-PATTERN
25
+ (defs
26
+ (const _ _) ...
27
+ )
28
+ PATTERN
29
+
30
+ def_node_matcher :class_method, <<-PATTERN
31
+ (defs
32
+ {
33
+ (const nil $_)
34
+ (const (const nil $_) ...)
35
+ }
36
+ ...
37
+ )
38
+ PATTERN
39
+
40
+ def on_method_def(node, method_name, _args, _body)
41
+ class_method_parent = class_method(node)
42
+ if class_method_parent
43
+ namespace = Namespace.new(class_method_parent.to_s)
44
+ else
45
+ namespace = Namespace.new(node.parent_module_name)
46
+ end
47
+ add_offense(node, :name, nil, :error) if namespace.top_level?
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module SketchupRequirements
6
+ # This cops looks for uses of global variables.
7
+ # It does not report offenses for built-in global variables.
8
+ # Built-in global variables are allowed by default. Additionally
9
+ # users can allow additional variables via the AllowedVariables option.
10
+ #
11
+ # Note that backreferences like $1, $2, etc are not global variables.
12
+ class GlobalVariables < Cop
13
+ include NoCommentDisable
14
+ MSG = 'Do not introduce global variables.'.freeze
15
+
16
+ # predefined global variables their English aliases
17
+ # http://www.zenspider.com/Languages/Ruby/QuickRef.html
18
+ BUILT_IN_VARS = %w(
19
+ $: $LOAD_PATH
20
+ $" $LOADED_FEATURES
21
+ $0 $PROGRAM_NAME
22
+ $! $ERROR_INFO
23
+ $@ $ERROR_POSITION
24
+ $; $FS $FIELD_SEPARATOR
25
+ $, $OFS $OUTPUT_FIELD_SEPARATOR
26
+ $/ $RS $INPUT_RECORD_SEPARATOR
27
+ $\\ $ORS $OUTPUT_RECORD_SEPARATOR
28
+ $. $NR $INPUT_LINE_NUMBER
29
+ $_ $LAST_READ_LINE
30
+ $> $DEFAULT_OUTPUT
31
+ $< $DEFAULT_INPUT
32
+ $$ $PID $PROCESS_ID
33
+ $? $CHILD_STATUS
34
+ $~ $LAST_MATCH_INFO
35
+ $= $IGNORECASE
36
+ $* $ARGV
37
+ $& $MATCH
38
+ $` $PREMATCH
39
+ $' $POSTMATCH
40
+ $+ $LAST_PAREN_MATCH
41
+ $stdin $stdout $stderr
42
+ $DEBUG $FILENAME $VERBOSE $SAFE
43
+ $-0 $-a $-d $-F $-i $-I $-l $-p $-v $-w
44
+ $CLASSPATH $JRUBY_VERSION $JRUBY_REVISION $ENV_JAVA
45
+ ).map(&:to_sym)
46
+
47
+ def allowed_var?(global_var)
48
+ BUILT_IN_VARS.include?(global_var)
49
+ end
50
+
51
+ def on_gvar(node)
52
+ check(node)
53
+ end
54
+
55
+ def on_gvasgn(node)
56
+ check(node)
57
+ end
58
+
59
+ def check(node)
60
+ global_var, = *node
61
+
62
+ add_offense(node, :name, nil, :error) unless allowed_var?(global_var)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end