rspectre 0.0.4 → 0.1.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.
- checksums.yaml +4 -4
- data/bin/rspectre +3 -3
- data/lib/rspectre/auto_corrector.rb +2 -2
- data/lib/rspectre/keyword_struct.rb +48 -0
- data/lib/rspectre/linter/unused_shared_setup.rb +17 -17
- data/lib/rspectre/linter.rb +3 -3
- data/lib/rspectre/node.rb +6 -2
- data/lib/rspectre/offense.rb +4 -4
- data/lib/rspectre/runner.rb +3 -3
- data/lib/rspectre/source_map/parser.rb +1 -1
- data/lib/rspectre/source_map.rb +24 -7
- data/lib/rspectre/tracker.rb +2 -2
- data/lib/rspectre/version.rb +1 -1
- data/lib/rspectre.rb +2 -2
- metadata +13 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87d88a2681d80d0f13e8cad1a0b5147c92d0ced19dede1657a74261cd4f9a8ae
|
4
|
+
data.tar.gz: 865b52f9b37fd3fa54b154dedb4196a4ce5bfcf20a0e8b8493e6bcd3611e8690
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cebc09f233bd5f6f2fd76c6f0741866472badae3a6a8f9c6012cfac379af4f2c4585827e0f73b0cd0e3b39848c0376dead07fad7bbd209666f10d8cc3242ed55
|
7
|
+
data.tar.gz: '09049b6500de8e538fa07a7e110e4671392e209b4345d1da8253c15901ce9af450cc54cfc330f19bcff1c5d05dd129df62ebcdc34c850d4daa92fa94e15056db'
|
data/bin/rspectre
CHANGED
@@ -20,8 +20,8 @@ OptionParser.new do |opts|
|
|
20
20
|
opts.on(
|
21
21
|
'--auto-correct',
|
22
22
|
'Enables auto-correct.',
|
23
|
-
'When auto-correct is enabled, rspectre will modify your source files in place and delete
|
24
|
-
' unused test setup.'
|
23
|
+
'When auto-correct is enabled, rspectre will modify your source files in place and delete ' \
|
24
|
+
'any unused test setup.'
|
25
25
|
) do |value|
|
26
26
|
options[:'auto-correct'] = value
|
27
27
|
end
|
@@ -29,4 +29,4 @@ end.parse(ARGV)
|
|
29
29
|
|
30
30
|
rspec, auto_correct = options.fetch_values(:rspec, :'auto-correct')
|
31
31
|
|
32
|
-
RSpectre::Runner.new(rspec, auto_correct).lint
|
32
|
+
RSpectre::Runner.new(rspec_arguments: rspec, auto_correct: auto_correct).lint
|
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
module RSpectre
|
4
4
|
class AutoCorrector < Parser::TreeRewriter
|
5
|
-
include
|
5
|
+
include KeywordStruct.new(:filename, :nodes, :buffer)
|
6
6
|
|
7
7
|
def initialize(filename, nodes)
|
8
8
|
buffer = Parser::Source::Buffer.new("(#{filename})")
|
9
9
|
buffer.source = File.read(filename)
|
10
10
|
|
11
|
-
super(filename, nodes, buffer)
|
11
|
+
super(filename: filename, nodes: nodes, buffer: buffer)
|
12
12
|
end
|
13
13
|
|
14
14
|
def correct
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpectre
|
4
|
+
# Heavily influenced by dkubb/equalizer, mbj/concord, and mbj/anima
|
5
|
+
class KeywordStruct < Module
|
6
|
+
def initialize(*names) # rubocop:disable Lint/MissingSuper
|
7
|
+
raise 'Specify at least one keyword name!' if names.empty?
|
8
|
+
|
9
|
+
names.each do |name|
|
10
|
+
next if /\A\w+\z/.match?(name)
|
11
|
+
|
12
|
+
raise "Invalid keyword name #{name.inspect}!"
|
13
|
+
end
|
14
|
+
|
15
|
+
@module =
|
16
|
+
Module.new do
|
17
|
+
attr_reader(*names)
|
18
|
+
|
19
|
+
define_method(:eql?) do |other|
|
20
|
+
other.instance_of?(self.class) && names.all? do |name|
|
21
|
+
__send__(name).eql?(other.__send__(name))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
alias_method :==, :eql?
|
25
|
+
|
26
|
+
define_method(:hash) do
|
27
|
+
[self.class, *names.map { |name| __send__(name) }].hash
|
28
|
+
end
|
29
|
+
|
30
|
+
define_method(:inspect) do
|
31
|
+
class_name = self.class.name || self.class.inspect
|
32
|
+
attributes = names.map { |name| "#{name}=#{__send__(name).inspect}" }.join(' ')
|
33
|
+
"#<#{class_name} #{attributes}>"
|
34
|
+
end
|
35
|
+
end.tap do |generated_module|
|
36
|
+
generated_module.class_eval(<<~RUBY, __FILE__, __LINE__ + 1) # rubocop:disable Style/DocumentDynamicEvalDefinition
|
37
|
+
def initialize(#{names.map { |name| "#{name}:" }.join(', ')})
|
38
|
+
#{names.map { |name| "@#{name} = #{name}" }.join("\n ")}
|
39
|
+
end
|
40
|
+
RUBY
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def included(descendant)
|
45
|
+
descendant.include(@module)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -10,21 +10,21 @@ module RSpectre
|
|
10
10
|
original_method = receiver.method(method)
|
11
11
|
|
12
12
|
# Overwrite the class method using define_singleton_method
|
13
|
-
receiver.__send__(:define_singleton_method, method) do |name, *args, &block|
|
13
|
+
receiver.__send__(:define_singleton_method, method) do |name, *args, **kwargs, &block|
|
14
14
|
# When we can locate the source of the node, tag it
|
15
15
|
if (node = UnusedSharedSetup.register(method, caller_locations))
|
16
|
-
# And call the
|
17
|
-
original_method.(name, *args) do |*shared_args|
|
16
|
+
# And call the original
|
17
|
+
original_method.(name, *args, **kwargs) do |*shared_args, **shared_kwargs|
|
18
18
|
# But record that it was used in a `before`
|
19
19
|
before { UnusedSharedSetup.record(node) }
|
20
20
|
|
21
21
|
# And then perform the original block in a `class_exec` like the original block was
|
22
22
|
# supposed to be
|
23
|
-
class_exec(*shared_args, &block)
|
23
|
+
class_exec(*shared_args, **shared_kwargs, &block)
|
24
24
|
end
|
25
25
|
else
|
26
26
|
# If we couldn't locate the source, just delegate to the original method.
|
27
|
-
original_method.(name, *args, &block)
|
27
|
+
original_method.(name, *args, **kwargs, &block)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
@@ -46,39 +46,39 @@ module RSpectre
|
|
46
46
|
# terms of the old method. I think we can probably do some kind of module inclusion to reduce
|
47
47
|
# this duplication (which is effectively what happens here anyway, i think), but this works
|
48
48
|
# for now.
|
49
|
-
def example_group.shared_examples(name, *args, &block)
|
49
|
+
def example_group.shared_examples(name, *args, **kwargs, &block)
|
50
50
|
if (node = UnusedSharedSetup.register(:shared_examples, caller_locations))
|
51
|
-
super(name, *args) do |*shared_args|
|
51
|
+
super(name, *args, **kwargs) do |*shared_args, **shared_kwargs|
|
52
52
|
before { UnusedSharedSetup.record(node) }
|
53
53
|
|
54
|
-
class_exec(*shared_args, &block)
|
54
|
+
class_exec(*shared_args, **shared_kwargs, &block)
|
55
55
|
end
|
56
56
|
else
|
57
|
-
super(name, *args, &block)
|
57
|
+
super(name, *args, **kwargs, &block)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
def example_group.shared_examples_for(name, *args, &block)
|
61
|
+
def example_group.shared_examples_for(name, *args, **kwargs, &block)
|
62
62
|
if (node = UnusedSharedSetup.register(:shared_examples_for, caller_locations))
|
63
|
-
super(name, *args) do |*shared_args|
|
63
|
+
super(name, *args, **kwargs) do |*shared_args, **shared_kwargs|
|
64
64
|
before { UnusedSharedSetup.record(node) }
|
65
65
|
|
66
|
-
class_exec(*shared_args, &block)
|
66
|
+
class_exec(*shared_args, **shared_kwargs, &block)
|
67
67
|
end
|
68
68
|
else
|
69
|
-
super(name, *args, &block)
|
69
|
+
super(name, *args, **kwargs, &block)
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
def example_group.shared_context(name, *args, &block)
|
73
|
+
def example_group.shared_context(name, *args, **kwargs, &block)
|
74
74
|
if (node = UnusedSharedSetup.register(:shared_context, caller_locations))
|
75
|
-
super(name, *args) do |*shared_args|
|
75
|
+
super(name, *args, **kwargs) do |*shared_args, **shared_kwargs|
|
76
76
|
before { UnusedSharedSetup.record(node) }
|
77
77
|
|
78
|
-
class_exec(*shared_args, &block)
|
78
|
+
class_exec(*shared_args, **shared_kwargs, &block)
|
79
79
|
end
|
80
80
|
else
|
81
|
-
super(name, *args, &block)
|
81
|
+
super(name, *args, **kwargs, &block)
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
data/lib/rspectre/linter.rb
CHANGED
@@ -19,7 +19,7 @@ module RSpectre
|
|
19
19
|
raw_node = node_map(file).find_method(selector, line)
|
20
20
|
|
21
21
|
if raw_node
|
22
|
-
node = RSpectre::Node.new(file, line, raw_node)
|
22
|
+
node = RSpectre::Node.new(file: file, line: line, node: raw_node)
|
23
23
|
TRACKER.register(self::TAG, node)
|
24
24
|
if block_given?
|
25
25
|
yield node
|
@@ -40,10 +40,10 @@ module RSpectre
|
|
40
40
|
def self.prepend_behavior(scope, method_name)
|
41
41
|
original_method = scope.instance_method(method_name)
|
42
42
|
|
43
|
-
scope.__send__(:define_method, method_name) do |*args, &block|
|
43
|
+
scope.__send__(:define_method, method_name) do |*args, **kwargs, &block|
|
44
44
|
yield
|
45
45
|
|
46
|
-
original_method.
|
46
|
+
original_method.bind_call(self, *args, **kwargs, &block)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
data/lib/rspectre/node.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module RSpectre
|
4
4
|
class Node
|
5
|
-
include
|
5
|
+
include KeywordStruct.new(:file, :line, :node)
|
6
6
|
|
7
7
|
def start_column
|
8
8
|
location.column + 1
|
@@ -27,7 +27,11 @@ module RSpectre
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def location
|
30
|
-
node.
|
30
|
+
if node.type.equal?(:block)
|
31
|
+
node.children.first.location
|
32
|
+
else
|
33
|
+
node.location
|
34
|
+
end
|
31
35
|
end
|
32
36
|
end
|
33
37
|
end
|
data/lib/rspectre/offense.rb
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
module RSpectre
|
4
4
|
class Offense
|
5
|
-
include
|
5
|
+
include KeywordStruct.new(:file, :line, :source_line, :start_column, :end_column, :type)
|
6
6
|
|
7
7
|
DESCRIPTIONS = {
|
8
8
|
'UnusedLet' => 'Unused `let` definition.',
|
9
9
|
'UnusedSubject' => 'Unused `subject` definition.',
|
10
|
-
'UnusedSharedSetup' => 'Unused `shared_examples`, `shared_examples_for`, or'\
|
11
|
-
'
|
10
|
+
'UnusedSharedSetup' => 'Unused `shared_examples`, `shared_examples_for`, or ' \
|
11
|
+
'`shared_context` definition.'
|
12
12
|
}.freeze
|
13
13
|
|
14
14
|
def self.parse(type, node)
|
@@ -23,7 +23,7 @@ module RSpectre
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def warn
|
26
|
-
puts
|
26
|
+
puts self
|
27
27
|
end
|
28
28
|
|
29
29
|
def to_s
|
data/lib/rspectre/runner.rb
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
module RSpectre
|
4
4
|
class Runner
|
5
|
-
include
|
5
|
+
include KeywordStruct.new(:rspec_arguments, :auto_correct)
|
6
6
|
|
7
7
|
EXIT_SUCCESS = 0
|
8
8
|
|
9
|
-
def initialize(
|
9
|
+
def initialize(**)
|
10
10
|
super
|
11
11
|
@rspec_output = StringIO.new
|
12
12
|
end
|
@@ -39,7 +39,7 @@ module RSpectre
|
|
39
39
|
|
40
40
|
abort(
|
41
41
|
Color.red(
|
42
|
-
'Running the specs failed. Either your tests do not pass '\
|
42
|
+
'Running the specs failed. Either your tests do not pass ' \
|
43
43
|
'normally or this is a bug in RSpectre.'
|
44
44
|
) + <<~TEXT
|
45
45
|
|
data/lib/rspectre/source_map.rb
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
module RSpectre
|
4
4
|
class SourceMap
|
5
|
-
include
|
5
|
+
include KeywordStruct.new(:map)
|
6
6
|
|
7
7
|
def initialize
|
8
|
-
super(Hash.new { [] })
|
8
|
+
super(map: Hash.new { [] })
|
9
9
|
end
|
10
10
|
private_class_method :new
|
11
11
|
|
12
12
|
def self.parse(file)
|
13
|
-
self::Parser.new(file).populate(new)
|
13
|
+
self::Parser.new(file: file).populate(new)
|
14
14
|
end
|
15
15
|
|
16
16
|
def add(node)
|
@@ -32,18 +32,35 @@ module RSpectre
|
|
32
32
|
private
|
33
33
|
|
34
34
|
def find_methods(target_selector, line)
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
block_candidates =
|
36
|
+
block_nodes(line).select do |node|
|
37
|
+
send, = *node
|
38
|
+
matching_send?(send, target_selector)
|
39
|
+
end
|
38
40
|
|
39
|
-
|
41
|
+
if block_candidates.any?
|
42
|
+
block_candidates
|
43
|
+
else
|
44
|
+
send_nodes(line).select do |node|
|
45
|
+
matching_send?(node, target_selector)
|
46
|
+
end
|
40
47
|
end
|
41
48
|
end
|
42
49
|
|
50
|
+
def matching_send?(node, method_name)
|
51
|
+
_receiver, selector = *node
|
52
|
+
|
53
|
+
selector.equal?(method_name)
|
54
|
+
end
|
55
|
+
|
43
56
|
def block_nodes(line)
|
44
57
|
map.fetch(line, []).select { |node| node.type.equal?(:block) }
|
45
58
|
end
|
46
59
|
|
60
|
+
def send_nodes(line)
|
61
|
+
map.fetch(line, []).select { |node| node.type.equal?(:send) }
|
62
|
+
end
|
63
|
+
|
47
64
|
class Null < self
|
48
65
|
public_class_method :new
|
49
66
|
|
data/lib/rspectre/tracker.rb
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
module RSpectre
|
4
4
|
class Tracker
|
5
|
-
include
|
5
|
+
include KeywordStruct.new(:registry, :tracker)
|
6
6
|
|
7
7
|
def initialize
|
8
|
-
super(Hash.new { Set.new }, Hash.new { Set.new })
|
8
|
+
super(registry: Hash.new { Set.new }, tracker: Hash.new { Set.new })
|
9
9
|
end
|
10
10
|
|
11
11
|
def register(type, node)
|
data/lib/rspectre/version.rb
CHANGED
data/lib/rspectre.rb
CHANGED
@@ -6,11 +6,11 @@ require 'pathname'
|
|
6
6
|
require 'set'
|
7
7
|
require 'stringio'
|
8
8
|
|
9
|
-
require 'anima'
|
10
|
-
require 'concord'
|
11
9
|
require 'parser/current'
|
12
10
|
require 'rspec'
|
13
11
|
|
12
|
+
require 'rspectre/keyword_struct'
|
13
|
+
|
14
14
|
require 'rspectre/auto_corrector'
|
15
15
|
require 'rspectre/color'
|
16
16
|
require 'rspectre/node'
|
metadata
CHANGED
@@ -1,71 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspectre
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Gollahon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: anima
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0.3'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0.3'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: concord
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0.1'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0.1'
|
41
13
|
- !ruby/object:Gem::Dependency
|
42
14
|
name: parser
|
43
15
|
requirement: !ruby/object:Gem::Requirement
|
44
16
|
requirements:
|
45
17
|
- - ">="
|
46
18
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
19
|
+
version: 3.2.2.1
|
48
20
|
type: :runtime
|
49
21
|
prerelease: false
|
50
22
|
version_requirements: !ruby/object:Gem::Requirement
|
51
23
|
requirements:
|
52
24
|
- - ">="
|
53
25
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
26
|
+
version: 3.2.2.1
|
55
27
|
- !ruby/object:Gem::Dependency
|
56
28
|
name: rspec
|
57
29
|
requirement: !ruby/object:Gem::Requirement
|
58
30
|
requirements:
|
59
31
|
- - "~>"
|
60
32
|
- !ruby/object:Gem::Version
|
61
|
-
version: '3.
|
33
|
+
version: '3.9'
|
62
34
|
type: :runtime
|
63
35
|
prerelease: false
|
64
36
|
version_requirements: !ruby/object:Gem::Requirement
|
65
37
|
requirements:
|
66
38
|
- - "~>"
|
67
39
|
- !ruby/object:Gem::Version
|
68
|
-
version: '3.
|
40
|
+
version: '3.9'
|
69
41
|
- !ruby/object:Gem::Dependency
|
70
42
|
name: pry
|
71
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,28 +58,28 @@ dependencies:
|
|
86
58
|
requirements:
|
87
59
|
- - "~>"
|
88
60
|
- !ruby/object:Gem::Version
|
89
|
-
version: 1.
|
61
|
+
version: 1.51.0
|
90
62
|
type: :development
|
91
63
|
prerelease: false
|
92
64
|
version_requirements: !ruby/object:Gem::Requirement
|
93
65
|
requirements:
|
94
66
|
- - "~>"
|
95
67
|
- !ruby/object:Gem::Version
|
96
|
-
version: 1.
|
68
|
+
version: 1.51.0
|
97
69
|
- !ruby/object:Gem::Dependency
|
98
70
|
name: rubocop-rspec
|
99
71
|
requirement: !ruby/object:Gem::Requirement
|
100
72
|
requirements:
|
101
73
|
- - "~>"
|
102
74
|
- !ruby/object:Gem::Version
|
103
|
-
version: 2.
|
75
|
+
version: 2.22.0
|
104
76
|
type: :development
|
105
77
|
prerelease: false
|
106
78
|
version_requirements: !ruby/object:Gem::Requirement
|
107
79
|
requirements:
|
108
80
|
- - "~>"
|
109
81
|
- !ruby/object:Gem::Version
|
110
|
-
version: 2.
|
82
|
+
version: 2.22.0
|
111
83
|
description:
|
112
84
|
email:
|
113
85
|
executables:
|
@@ -119,6 +91,7 @@ files:
|
|
119
91
|
- lib/rspectre.rb
|
120
92
|
- lib/rspectre/auto_corrector.rb
|
121
93
|
- lib/rspectre/color.rb
|
94
|
+
- lib/rspectre/keyword_struct.rb
|
122
95
|
- lib/rspectre/linter.rb
|
123
96
|
- lib/rspectre/linter/unused_let.rb
|
124
97
|
- lib/rspectre/linter/unused_shared_setup.rb
|
@@ -144,14 +117,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
144
117
|
requirements:
|
145
118
|
- - ">="
|
146
119
|
- !ruby/object:Gem::Version
|
147
|
-
version: '
|
120
|
+
version: '3.0'
|
148
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
122
|
requirements:
|
150
123
|
- - ">="
|
151
124
|
- !ruby/object:Gem::Version
|
152
125
|
version: '0'
|
153
126
|
requirements: []
|
154
|
-
rubygems_version: 3.
|
127
|
+
rubygems_version: 3.4.10
|
155
128
|
signing_key:
|
156
129
|
specification_version: 4
|
157
130
|
summary: A tool for linting RSpec test suites.
|