rubocop-sketchup 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +8 -0
- data/lib/rubocop-sketchup.rb +12 -0
- data/lib/rubocop/sketchup/deprecations/operation_next_transparent.rb +21 -0
- data/lib/rubocop/sketchup/namespace.rb +47 -0
- data/lib/rubocop/sketchup/namespace_checker.rb +43 -0
- data/lib/rubocop/sketchup/no_comment_disable.rb +17 -0
- data/lib/rubocop/sketchup/performance/operation_disable_ui.rb +25 -0
- data/lib/rubocop/sketchup/performance/typename.rb +19 -0
- data/lib/rubocop/sketchup/requirements/api_namespace.rb +24 -0
- data/lib/rubocop/sketchup/requirements/extension_namespace.rb +64 -0
- data/lib/rubocop/sketchup/requirements/global_constants.rb +22 -0
- data/lib/rubocop/sketchup/requirements/global_methods.rb +53 -0
- data/lib/rubocop/sketchup/requirements/global_variables.rb +67 -0
- data/lib/rubocop/sketchup/requirements/load_path.rb +80 -0
- data/lib/rubocop/sketchup/requirements/ruby_core_namespace.rb +285 -0
- data/lib/rubocop/sketchup/requirements/ruby_stdlib_namespace.rb +628 -0
- data/lib/rubocop/sketchup/suggestions/model_entities.rb +33 -0
- data/lib/rubocop/sketchup/suggestions/operation_name.rb +32 -0
- data/lib/rubocop/sketchup/version.rb +5 -0
- data/rubocop-sketchup.gemspec +27 -0
- metadata +91 -0
checksums.yaml
ADDED
@@ -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,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
|