chronicles 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.
- checksums.yaml +7 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +9 -0
- data/.metrics +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +9 -0
- data/.yardopts +3 -0
- data/Gemfile +5 -0
- data/Guardfile +15 -0
- data/LICENSE +21 -0
- data/README.md +198 -0
- data/Rakefile +22 -0
- data/chronicles.gemspec +22 -0
- data/config/metrics/STYLEGUIDE +230 -0
- data/config/metrics/cane.yml +5 -0
- data/config/metrics/churn.yml +6 -0
- data/config/metrics/flay.yml +2 -0
- data/config/metrics/metric_fu.yml +15 -0
- data/config/metrics/reek.yml +1 -0
- data/config/metrics/roodi.yml +24 -0
- data/config/metrics/rubocop.yml +77 -0
- data/config/metrics/saikuro.yml +3 -0
- data/config/metrics/simplecov.yml +8 -0
- data/config/metrics/yardstick.yml +37 -0
- data/lib/chronicles.rb +80 -0
- data/lib/chronicles/injector.rb +28 -0
- data/lib/chronicles/methods.rb +53 -0
- data/lib/chronicles/updater.rb +50 -0
- data/lib/chronicles/version.rb +9 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/tests/chronicles/injector_spec.rb +82 -0
- data/spec/tests/chronicles/methods_spec.rb +88 -0
- data/spec/tests/chronicles/updater_spec.rb +143 -0
- data/spec/tests/chronicles_spec.rb +197 -0
- metadata +99 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
folders: # The list of folders to be used by any metric.
|
|
3
|
+
- lib
|
|
4
|
+
- app
|
|
5
|
+
metrics: # The list of allowed metrics. The other metrics are disabled.
|
|
6
|
+
- cane
|
|
7
|
+
- churn
|
|
8
|
+
- flay
|
|
9
|
+
- flog
|
|
10
|
+
- reek
|
|
11
|
+
- roodi
|
|
12
|
+
- saikuro
|
|
13
|
+
format: html
|
|
14
|
+
output: tmp/metric_fu
|
|
15
|
+
verbose: false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
---
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
AssignmentInConditionalCheck:
|
|
3
|
+
CaseMissingElseCheck:
|
|
4
|
+
ClassLineCountCheck:
|
|
5
|
+
line_count: 300
|
|
6
|
+
ClassNameCheck:
|
|
7
|
+
pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
|
|
8
|
+
ClassVariableCheck:
|
|
9
|
+
CyclomaticComplexityBlockCheck:
|
|
10
|
+
complexity: 4
|
|
11
|
+
CyclomaticComplexityMethodCheck:
|
|
12
|
+
complexity: 8
|
|
13
|
+
EmptyRescueBodyCheck:
|
|
14
|
+
ForLoopCheck:
|
|
15
|
+
MethodLineCountCheck:
|
|
16
|
+
line_count: 20
|
|
17
|
+
MethodNameCheck:
|
|
18
|
+
pattern: !ruby/regexp /^[\||\^|\&|\!]$|^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/
|
|
19
|
+
ModuleLineCountCheck:
|
|
20
|
+
line_count: 300
|
|
21
|
+
ModuleNameCheck:
|
|
22
|
+
pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
|
|
23
|
+
ParameterNumberCheck:
|
|
24
|
+
parameter_count: 5
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
# settings added by the 'hexx-suit' module
|
|
3
|
+
# output: "tmp/rubocop"
|
|
4
|
+
# format: "html"
|
|
5
|
+
|
|
6
|
+
AllCops:
|
|
7
|
+
Exclude:
|
|
8
|
+
- '**/db/schema.rb'
|
|
9
|
+
|
|
10
|
+
Lint/HandleExceptions:
|
|
11
|
+
Exclude:
|
|
12
|
+
- '**/*_spec.rb'
|
|
13
|
+
|
|
14
|
+
Lint/RescueException:
|
|
15
|
+
Exclude:
|
|
16
|
+
- '**/*_spec.rb'
|
|
17
|
+
|
|
18
|
+
Style/AccessorMethodName:
|
|
19
|
+
Exclude:
|
|
20
|
+
- '**/*_spec.rb'
|
|
21
|
+
|
|
22
|
+
Style/AsciiComments:
|
|
23
|
+
Enabled: false
|
|
24
|
+
|
|
25
|
+
Style/ClassAndModuleChildren:
|
|
26
|
+
Exclude:
|
|
27
|
+
- '**/*_spec.rb'
|
|
28
|
+
|
|
29
|
+
Style/Documentation:
|
|
30
|
+
Enabled: false
|
|
31
|
+
|
|
32
|
+
Style/EmptyLinesAroundBlockBody:
|
|
33
|
+
Enabled: false
|
|
34
|
+
|
|
35
|
+
Style/EmptyLinesAroundClassBody:
|
|
36
|
+
Enabled: false
|
|
37
|
+
|
|
38
|
+
Style/EmptyLinesAroundMethodBody:
|
|
39
|
+
Enabled: false
|
|
40
|
+
|
|
41
|
+
Style/EmptyLinesAroundModuleBody:
|
|
42
|
+
Enabled: false
|
|
43
|
+
|
|
44
|
+
Style/EmptyLineBetweenDefs:
|
|
45
|
+
Enabled: false
|
|
46
|
+
|
|
47
|
+
Style/FileName:
|
|
48
|
+
Enabled: false
|
|
49
|
+
|
|
50
|
+
Style/MethodCallParentheses:
|
|
51
|
+
Exclude:
|
|
52
|
+
- '**/updater.rb'
|
|
53
|
+
|
|
54
|
+
Style/RaiseArgs:
|
|
55
|
+
EnforcedStyle: compact
|
|
56
|
+
|
|
57
|
+
Style/SingleLineMethods:
|
|
58
|
+
Exclude:
|
|
59
|
+
- '**/*_spec.rb'
|
|
60
|
+
|
|
61
|
+
Style/SingleSpaceBeforeFirstArg:
|
|
62
|
+
Enabled: false
|
|
63
|
+
|
|
64
|
+
Style/SpecialGlobalVars:
|
|
65
|
+
Exclude:
|
|
66
|
+
- '**/Gemfile'
|
|
67
|
+
- '**/*.gemspec'
|
|
68
|
+
|
|
69
|
+
Style/StringLiterals:
|
|
70
|
+
EnforcedStyle: double_quotes
|
|
71
|
+
|
|
72
|
+
Style/StringLiteralsInInterpolation:
|
|
73
|
+
EnforcedStyle: double_quotes
|
|
74
|
+
|
|
75
|
+
Style/TrivialAccessors:
|
|
76
|
+
Exclude:
|
|
77
|
+
- '**/*_spec.rb'
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Settings added by the 'hexx-suit' gem
|
|
3
|
+
output: "tmp/yardstick/output.log"
|
|
4
|
+
path: "lib/**/*.rb"
|
|
5
|
+
rules:
|
|
6
|
+
ApiTag::Presence:
|
|
7
|
+
enabled: true
|
|
8
|
+
exclude: []
|
|
9
|
+
ApiTag::Inclusion:
|
|
10
|
+
enabled: true
|
|
11
|
+
exclude: []
|
|
12
|
+
ApiTag::ProtectedMethod:
|
|
13
|
+
enabled: true
|
|
14
|
+
exclude: []
|
|
15
|
+
ApiTag::PrivateMethod:
|
|
16
|
+
enabled: false
|
|
17
|
+
exclude: []
|
|
18
|
+
ExampleTag:
|
|
19
|
+
enabled: true
|
|
20
|
+
exclude: []
|
|
21
|
+
ReturnTag:
|
|
22
|
+
enabled: true
|
|
23
|
+
exclude: []
|
|
24
|
+
Summary::Presence:
|
|
25
|
+
enabled: true
|
|
26
|
+
exclude: []
|
|
27
|
+
Summary::Length:
|
|
28
|
+
enabled: true
|
|
29
|
+
exclude: []
|
|
30
|
+
Summary::Delimiter:
|
|
31
|
+
enabled: true
|
|
32
|
+
exclude: []
|
|
33
|
+
Summary::SingleLine:
|
|
34
|
+
enabled: true
|
|
35
|
+
exclude: []
|
|
36
|
+
threshold: 100
|
|
37
|
+
verbose: false
|
data/lib/chronicles.rb
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require_relative "chronicles/version"
|
|
4
|
+
require_relative "chronicles/methods"
|
|
5
|
+
require_relative "chronicles/updater"
|
|
6
|
+
require_relative "chronicles/injector"
|
|
7
|
+
|
|
8
|
+
# The module adds features to keep chronicles of object's methods calls
|
|
9
|
+
module Chronicles
|
|
10
|
+
|
|
11
|
+
# @!attribute [r] chronicles
|
|
12
|
+
# Returns the array of object methods having been called
|
|
13
|
+
#
|
|
14
|
+
# @return [Array<Symbol>]
|
|
15
|
+
def chronicles
|
|
16
|
+
@chronicles ||= []
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Starts registation of calls of the selected methods of the object
|
|
20
|
+
#
|
|
21
|
+
# @example
|
|
22
|
+
# class Test
|
|
23
|
+
# include Chronicles
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# test = Test.new
|
|
27
|
+
# test.start_chronicles only: :foo
|
|
28
|
+
# test.foo
|
|
29
|
+
# test.bar
|
|
30
|
+
# test.baz
|
|
31
|
+
# test.foo
|
|
32
|
+
# test.chronicles # => [:foo, :foo]
|
|
33
|
+
#
|
|
34
|
+
# @param [Hash] options
|
|
35
|
+
# describes the selection of methods to include to chronicles
|
|
36
|
+
# @option options [Boolean] :public (true)
|
|
37
|
+
# whether public methods should be looked after
|
|
38
|
+
# @option options [Boolean] :protected (true)
|
|
39
|
+
# whether protected methods should be looked after
|
|
40
|
+
# @option options [Boolean] :private (true)
|
|
41
|
+
# whether private methods should be looked after
|
|
42
|
+
# @option options [Array<#to_sym>] :except ([])
|
|
43
|
+
# the whitelist of methods that shouldn't be looked after
|
|
44
|
+
# @option options [Array<#to_sym>] :only ([])
|
|
45
|
+
# the whitelist of methods that should be looked after
|
|
46
|
+
#
|
|
47
|
+
# @return [undefined]
|
|
48
|
+
def start_chronicles(**options)
|
|
49
|
+
Injector.new(self, "chronicles << __method__", options).run
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Stops registation of calls of the selected methods of the object
|
|
53
|
+
#
|
|
54
|
+
# @example
|
|
55
|
+
# class Test
|
|
56
|
+
# include Chronicles
|
|
57
|
+
# end
|
|
58
|
+
#
|
|
59
|
+
# test = Test.new
|
|
60
|
+
# test.start_chronicles
|
|
61
|
+
# test.foo
|
|
62
|
+
# test.bar
|
|
63
|
+
# test.baz
|
|
64
|
+
# test.chronicles # => [:foo, :bar, :baz]
|
|
65
|
+
#
|
|
66
|
+
# test.stop_chronicles except: :foo
|
|
67
|
+
# test.foo
|
|
68
|
+
# test.bar
|
|
69
|
+
# test.baz
|
|
70
|
+
# test.chronicles # => [:foo, :bar, :baz, :foo]
|
|
71
|
+
#
|
|
72
|
+
# @param (see #start_chronicles)
|
|
73
|
+
# @option (see #start_chronicles)
|
|
74
|
+
#
|
|
75
|
+
# @return [undefined]
|
|
76
|
+
def stop_chronicles(**options)
|
|
77
|
+
Injector.new(self, options).run
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end # module Chronicles
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Chronicles
|
|
4
|
+
|
|
5
|
+
# Injects the code to object methods selected by options
|
|
6
|
+
#
|
|
7
|
+
# @private
|
|
8
|
+
class Injector
|
|
9
|
+
|
|
10
|
+
attr_reader :object, :code, :list
|
|
11
|
+
|
|
12
|
+
def initialize(object, code = nil, **options)
|
|
13
|
+
@object = object
|
|
14
|
+
@code = code
|
|
15
|
+
@list = Methods.new(object, options)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def updaters
|
|
19
|
+
list.map { |name| Updater.new(object, name, code) }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def run
|
|
23
|
+
updaters.each(&:run)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end # class Injector
|
|
27
|
+
|
|
28
|
+
end # module Chronicles
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Chronicles
|
|
4
|
+
|
|
5
|
+
# Array of object methods selected by options
|
|
6
|
+
#
|
|
7
|
+
# @private
|
|
8
|
+
class Methods < Array
|
|
9
|
+
|
|
10
|
+
def initialize(object, **options)
|
|
11
|
+
@object = object
|
|
12
|
+
@options = options
|
|
13
|
+
super(whitelist.empty? ? list : list & whitelist)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
attr_reader :object, :options
|
|
19
|
+
|
|
20
|
+
def list
|
|
21
|
+
[public_list, protected_list, private_list].flatten.compact - blacklist
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def whitelist
|
|
25
|
+
Array(options[:only]).map(&:to_sym)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def blacklist
|
|
29
|
+
Array(options[:except]).map(&:to_sym)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def public_list
|
|
33
|
+
return if options[:public].equal?(false)
|
|
34
|
+
object.public_methods - Object.public_instance_methods - own_list
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def own_list
|
|
38
|
+
%i(chronicles start_chronicles stop_chronicles)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def protected_list
|
|
42
|
+
return if options[:protected].equal?(false)
|
|
43
|
+
object.protected_methods
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def private_list
|
|
47
|
+
return if options[:private].equal?(false)
|
|
48
|
+
object.private_methods - Object.private_instance_methods
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end # class Methods
|
|
52
|
+
|
|
53
|
+
end # module Chronicles
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module Chronicles
|
|
4
|
+
|
|
5
|
+
# Reloads object method
|
|
6
|
+
#
|
|
7
|
+
# @private
|
|
8
|
+
class Updater
|
|
9
|
+
|
|
10
|
+
def initialize(object, name, code = nil)
|
|
11
|
+
@object = object
|
|
12
|
+
@name = name
|
|
13
|
+
@code = code
|
|
14
|
+
type
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
attr_reader :object, :name, :code
|
|
18
|
+
|
|
19
|
+
def type
|
|
20
|
+
@type ||= %w(public private protected).detect do |item|
|
|
21
|
+
object.public_send("#{ item }_methods").include? name
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def klass
|
|
26
|
+
object.singleton_class
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def run
|
|
30
|
+
redefine_method
|
|
31
|
+
protect_method
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def redefine_method
|
|
37
|
+
code = code()
|
|
38
|
+
klass.__send__ :define_method, name do |*args|
|
|
39
|
+
instance_eval(code) if code
|
|
40
|
+
super(*args)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def protect_method
|
|
45
|
+
klass.instance_eval "#{ type } :#{ name }"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end # class Updater
|
|
49
|
+
|
|
50
|
+
end # module Chronicles
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
describe Chronicles::Injector do
|
|
4
|
+
|
|
5
|
+
let(:object) { double foo: nil, bar: nil, baz: nil }
|
|
6
|
+
let(:options) { { only: %i(foo bar), private: false } }
|
|
7
|
+
let(:code) { "chronicles << __method__" }
|
|
8
|
+
subject { described_class.new object, code, options }
|
|
9
|
+
|
|
10
|
+
describe "#object" do
|
|
11
|
+
|
|
12
|
+
it "is initialized" do
|
|
13
|
+
expect(subject.object).to eq object
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end # describe #object
|
|
17
|
+
|
|
18
|
+
describe "#list" do
|
|
19
|
+
|
|
20
|
+
let(:list) { Chronicles::Methods.new(object, options).to_a }
|
|
21
|
+
|
|
22
|
+
it "is initialized" do
|
|
23
|
+
expect(subject.list).to eq list
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end # describe #list
|
|
27
|
+
|
|
28
|
+
describe "#code" do
|
|
29
|
+
|
|
30
|
+
it "is initialized" do
|
|
31
|
+
expect(subject.code).to eq code
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "can be nil" do
|
|
35
|
+
subject = described_class.new object, options
|
|
36
|
+
expect(subject.code).to be_nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end # describe #code
|
|
40
|
+
|
|
41
|
+
describe "#updaters" do
|
|
42
|
+
|
|
43
|
+
let(:list) { %i(foo bar baz) }
|
|
44
|
+
before { allow(subject).to receive(:list).and_return list }
|
|
45
|
+
|
|
46
|
+
it "returns updaters" do
|
|
47
|
+
subject.updaters.each do |updater|
|
|
48
|
+
expect(updater).to be_kind_of Chronicles::Updater
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "constructed for #object" do
|
|
53
|
+
subject.updaters.each do |updater|
|
|
54
|
+
expect(updater.object).to eq subject.object
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "constructed for #list of methods" do
|
|
59
|
+
expect(subject.updaters.map(&:name)).to eq subject.list
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "constructed for #code" do
|
|
63
|
+
subject.updaters.each do |updater|
|
|
64
|
+
expect(updater.code).to eq subject.code
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
end # describe #updaters
|
|
69
|
+
|
|
70
|
+
describe ".run" do
|
|
71
|
+
|
|
72
|
+
let(:updaters) { 2.times.map { double run: nil } }
|
|
73
|
+
before { allow(subject).to receive(:updaters).and_return updaters }
|
|
74
|
+
|
|
75
|
+
it "runs updaters" do
|
|
76
|
+
updaters.each { |updater| expect(updater).to receive(:run) }
|
|
77
|
+
subject.run
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end # describe .run
|
|
81
|
+
|
|
82
|
+
end # describe Chronicles::Injector
|