chronicles 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ ---
2
+ abc_max: "10"
3
+ line_length: "80"
4
+ no_doc: "y"
5
+ no_readme: "y"
@@ -0,0 +1,6 @@
1
+ ---
2
+ ignore_files:
3
+ - spec
4
+ - config
5
+ minimum_churn_count: 0
6
+ start_date: "1 year ago"
@@ -0,0 +1,2 @@
1
+ ---
2
+ minimum_score: 5
@@ -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,3 @@
1
+ ---
2
+ warn_cyclo: 4
3
+ error_cyclo: 6
@@ -0,0 +1,8 @@
1
+ ---
2
+ output: tmp/coverage
3
+ filters: # The list of paths to be excluded from coverage checkup
4
+ - "spec/"
5
+ - "config/"
6
+ groups: # The list of groups to be shown in the coverage report
7
+ Libraries: "lib/"
8
+ Application: "app/"
@@ -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
@@ -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
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ module Chronicles
4
+
5
+ # The semantic version of the module.
6
+ # @see http://semver.org/ Semantic versioning 2.0
7
+ VERSION = "0.0.1".freeze
8
+
9
+ end # module Chronicles
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+
3
+ begin
4
+ require "hexx-suit"
5
+ Hexx::Suit.load_metrics_for(self)
6
+ rescue LoadError
7
+ require "hexx-rspec"
8
+ Hexx::RSpec.load_metrics_for(self)
9
+ end
10
+
11
+ # Loads the code under test
12
+ require "chronicles"
@@ -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