abstract_mapper 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.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +9 -0
  4. data/.metrics +9 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +2 -0
  7. data/.travis.yml +19 -0
  8. data/.yardopts +3 -0
  9. data/CHANGELOG.md +3 -0
  10. data/Gemfile +9 -0
  11. data/Guardfile +14 -0
  12. data/LICENSE +21 -0
  13. data/README.md +239 -0
  14. data/Rakefile +34 -0
  15. data/abstract_mapper.gemspec +26 -0
  16. data/config/metrics/STYLEGUIDE +230 -0
  17. data/config/metrics/cane.yml +5 -0
  18. data/config/metrics/churn.yml +6 -0
  19. data/config/metrics/flay.yml +2 -0
  20. data/config/metrics/metric_fu.yml +15 -0
  21. data/config/metrics/reek.yml +1 -0
  22. data/config/metrics/roodi.yml +24 -0
  23. data/config/metrics/rubocop.yml +76 -0
  24. data/config/metrics/saikuro.yml +3 -0
  25. data/config/metrics/simplecov.yml +6 -0
  26. data/config/metrics/yardstick.yml +37 -0
  27. data/lib/abstract_mapper/branch.rb +110 -0
  28. data/lib/abstract_mapper/builder.rb +84 -0
  29. data/lib/abstract_mapper/commands.rb +71 -0
  30. data/lib/abstract_mapper/dsl.rb +62 -0
  31. data/lib/abstract_mapper/errors/unknown_command.rb +25 -0
  32. data/lib/abstract_mapper/errors/wrong_node.rb +23 -0
  33. data/lib/abstract_mapper/errors/wrong_rule.rb +23 -0
  34. data/lib/abstract_mapper/functions.rb +76 -0
  35. data/lib/abstract_mapper/node.rb +76 -0
  36. data/lib/abstract_mapper/optimizer.rb +48 -0
  37. data/lib/abstract_mapper/pair_rule.rb +66 -0
  38. data/lib/abstract_mapper/rspec.rb +7 -0
  39. data/lib/abstract_mapper/rule.rb +52 -0
  40. data/lib/abstract_mapper/rules.rb +61 -0
  41. data/lib/abstract_mapper/settings.rb +95 -0
  42. data/lib/abstract_mapper/sole_rule.rb +58 -0
  43. data/lib/abstract_mapper/version.rb +9 -0
  44. data/lib/abstract_mapper.rb +82 -0
  45. data/lib/rspec/functions.rb +25 -0
  46. data/lib/rspec/mapper.rb +40 -0
  47. data/lib/rspec/nodes.rb +58 -0
  48. data/lib/rspec/rules.rb +59 -0
  49. data/spec/integration/faceter.rb +62 -0
  50. data/spec/integration/mapper_definition_spec.rb +33 -0
  51. data/spec/integration/rspec_examples_spec.rb +77 -0
  52. data/spec/spec_helper.rb +20 -0
  53. data/spec/unit/abstract_mapper/branch_spec.rb +126 -0
  54. data/spec/unit/abstract_mapper/builder_spec.rb +78 -0
  55. data/spec/unit/abstract_mapper/commands_spec.rb +105 -0
  56. data/spec/unit/abstract_mapper/dsl_spec.rb +82 -0
  57. data/spec/unit/abstract_mapper/errors/unknown_command_spec.rb +21 -0
  58. data/spec/unit/abstract_mapper/errors/wrong_node_spec.rb +21 -0
  59. data/spec/unit/abstract_mapper/errors/wrong_rule_spec.rb +23 -0
  60. data/spec/unit/abstract_mapper/functions/compact_spec.rb +25 -0
  61. data/spec/unit/abstract_mapper/functions/filter_spec.rb +26 -0
  62. data/spec/unit/abstract_mapper/functions/subclass_spec.rb +66 -0
  63. data/spec/unit/abstract_mapper/node_spec.rb +84 -0
  64. data/spec/unit/abstract_mapper/optimizer_spec.rb +48 -0
  65. data/spec/unit/abstract_mapper/pair_rule_spec.rb +59 -0
  66. data/spec/unit/abstract_mapper/rule_spec.rb +83 -0
  67. data/spec/unit/abstract_mapper/rules_spec.rb +88 -0
  68. data/spec/unit/abstract_mapper/settings_spec.rb +113 -0
  69. data/spec/unit/abstract_mapper/sole_rule_spec.rb +51 -0
  70. data/spec/unit/abstract_mapper_spec.rb +36 -0
  71. metadata +171 -0
@@ -0,0 +1,66 @@
1
+ # encoding: utf-8
2
+
3
+ require "abstract_mapper/rspec"
4
+
5
+ describe AbstractMapper::Functions, "#subclass?" do
6
+
7
+ let(:klass) { Class.new }
8
+ let(:modul) { Module.new }
9
+
10
+ it_behaves_like :transforming_immutable_data do
11
+ let(:arguments) { [:subclass?, klass] }
12
+
13
+ let(:input) { Class.new }
14
+ let(:output) { false }
15
+ end
16
+
17
+ it_behaves_like :transforming_immutable_data do
18
+ let(:arguments) { [:subclass?, klass] }
19
+
20
+ let(:input) { Class.new(Class.new(klass)) }
21
+ let(:output) { true }
22
+ end
23
+
24
+ it_behaves_like :transforming_immutable_data do
25
+ let(:arguments) { [:subclass?, modul] }
26
+
27
+ let(:input) { Class.new }
28
+ let(:output) { false }
29
+ end
30
+
31
+ it_behaves_like :transforming_immutable_data do
32
+ let(:arguments) { [:subclass?, modul] }
33
+
34
+ let(:input) { Class.new.send :include, modul }
35
+ let(:output) { true }
36
+ end
37
+
38
+ it_behaves_like :transforming_immutable_data do
39
+ let(:arguments) { [:subclass?, modul] }
40
+
41
+ let(:input) { Class.new.send :extend, modul }
42
+ let(:output) { false }
43
+ end
44
+
45
+ it_behaves_like :transforming_immutable_data do
46
+ let(:arguments) { [:subclass?, modul] }
47
+
48
+ let(:input) { Module.new }
49
+ let(:output) { false }
50
+ end
51
+
52
+ it_behaves_like :transforming_immutable_data do
53
+ let(:arguments) { [:subclass?, modul] }
54
+
55
+ let(:input) { Module.new.send :include, modul }
56
+ let(:output) { true }
57
+ end
58
+
59
+ it_behaves_like :transforming_immutable_data do
60
+ let(:arguments) { [:subclass?, modul] }
61
+
62
+ let(:input) { Module.new.send :extend, modul }
63
+ let(:output) { false }
64
+ end
65
+
66
+ end # describe AbstractMapper::Functions#subclass?
@@ -0,0 +1,84 @@
1
+ # encoding: utf-8
2
+
3
+ describe AbstractMapper::Node do
4
+
5
+ let(:test) { AbstractMapper::Test::Node = Class.new(described_class) }
6
+ let(:node) { test.new(*attributes) }
7
+ let(:attributes) { [:foo, :bar] }
8
+
9
+ describe ".new" do
10
+
11
+ subject { node }
12
+ it { is_expected.to be_frozen }
13
+
14
+ end # describe .new
15
+
16
+ describe "#attributes" do
17
+
18
+ subject { node.attributes }
19
+
20
+ it { is_expected.to eql attributes }
21
+ it { is_expected.to be_frozen }
22
+
23
+ it "doesn't freeze the source" do
24
+ expect { subject }.not_to change { attributes.frozen? }
25
+ end
26
+
27
+ end # describe #attributes
28
+
29
+ describe "#block" do
30
+
31
+ subject { node.block }
32
+
33
+ context "when block is absent" do
34
+
35
+ let(:node) { test.new(*attributes) }
36
+ it { is_expected.to eql nil }
37
+
38
+ end # context
39
+
40
+ context "when block is present" do
41
+
42
+ let(:block) { proc { :foo } }
43
+ let(:node) { test.new(*attributes, &block) }
44
+ it { is_expected.to eql block }
45
+
46
+ end # context
47
+
48
+ end # describe #block
49
+
50
+ describe "#to_s" do
51
+
52
+ subject { node.to_s }
53
+
54
+ context "without attributes" do
55
+
56
+ let(:node) { test.new }
57
+ it { is_expected.to eql "Node" }
58
+
59
+ end # context
60
+
61
+ context "with attributes" do
62
+
63
+ let(:node) { test.new(*attributes) }
64
+ it { is_expected.to eql "Node(:foo, :bar)" }
65
+
66
+ end # context
67
+
68
+ end # describe #to_s
69
+
70
+ describe "#inspect" do
71
+
72
+ subject { node.inspect }
73
+ it { is_expected.to eql "<Node(:foo, :bar)>" }
74
+
75
+ end # describe #inspect
76
+
77
+ describe "#transproc" do
78
+
79
+ subject { node.transproc[:foo] }
80
+ it { is_expected.to eql :foo }
81
+
82
+ end # describe #transproc
83
+
84
+ end # describe AbstractMapper::Node
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+
3
+ describe AbstractMapper::Optimizer do
4
+
5
+ let(:optimizer) { test.new rules }
6
+ let(:test) { Class.new(described_class) }
7
+ let(:rules) { AbstractMapper::Rules.new }
8
+
9
+ describe ".new" do
10
+
11
+ subject { optimizer }
12
+ it { is_expected.to be_frozen }
13
+
14
+ end # describe .new
15
+
16
+ describe "#rules" do
17
+
18
+ subject { optimizer.rules }
19
+ it { is_expected.to eql rules }
20
+
21
+ end # describe #rules
22
+
23
+ describe "#update" do
24
+
25
+ subject { optimizer.update(tree) }
26
+
27
+ let(:rules) { AbstractMapper::Rules.new([rule]) }
28
+ let(:rule) { Class.new(AbstractMapper::PairRule) }
29
+ let(:tree) { AbstractMapper::Branch.new { [node3, node4] } }
30
+ let(:node1) { AbstractMapper::Node.new(1) }
31
+ let(:node2) { AbstractMapper::Node.new(2) }
32
+ let(:node3) { AbstractMapper::Node.new(3) }
33
+ let(:node4) { AbstractMapper::Test::Foo.new(4) { [node1, node2] } }
34
+
35
+ before { AbstractMapper::Test::Foo = Class.new(AbstractMapper::Branch) }
36
+ before { rule.send(:define_method, :optimize?) { true } }
37
+ before { rule.send(:define_method, :optimize) { nodes.reverse } }
38
+
39
+ it "optimizes the tree deeply" do
40
+ expect(tree.inspect)
41
+ .to eql "<Root [<Node(3)>, <Foo(4) [<Node(1)>, <Node(2)>]>]>"
42
+ expect(subject.inspect)
43
+ .to eql "<Root [<Foo(4) [<Node(2)>, <Node(1)>]>, <Node(3)>]>"
44
+ end
45
+
46
+ end # describe #update
47
+
48
+ end # describe AbstractMapper::Optimize
@@ -0,0 +1,59 @@
1
+ # encoding: utf-8
2
+
3
+ describe AbstractMapper::PairRule do
4
+
5
+ let(:rule) { test.new(left, right) }
6
+ let(:test) { AbstractMapper::Test::Rule = Class.new(described_class) }
7
+ let(:nodes) { [left, right] }
8
+ let(:left) { double }
9
+ let(:right) { double }
10
+
11
+ describe ".composer" do
12
+
13
+ subject { test.composer }
14
+ it { is_expected.to eql :compact }
15
+
16
+ end # describe .pair?
17
+
18
+ describe ".new" do
19
+
20
+ subject { rule }
21
+
22
+ it { is_expected.to be_kind_of AbstractMapper::Rule }
23
+ it { is_expected.to be_frozen }
24
+
25
+ it "requires second argument" do
26
+ expect { test.new(left) }.to raise_error(ArgumentError)
27
+ end
28
+
29
+ end # describe .new
30
+
31
+ describe "#left" do
32
+
33
+ subject { rule.left }
34
+ it { is_expected.to eql left }
35
+
36
+ end # describe #left
37
+
38
+ describe "#right" do
39
+
40
+ subject { rule.right }
41
+ it { is_expected.to eql right }
42
+
43
+ end # describe #right
44
+
45
+ describe "#transproc" do
46
+
47
+ before do
48
+ test.send(:define_method, :optimize?) { left == right }
49
+ test.send(:define_method, :optimize) { left + right }
50
+ end
51
+
52
+ subject { test.transproc[array] }
53
+
54
+ let(:array) { [1, 1, 2, 5] }
55
+ it { is_expected.to eql [4, 5] }
56
+
57
+ end # describe #transproc
58
+
59
+ end # describe AbstractMapper::PairRule
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+
3
+ describe AbstractMapper::Rule do
4
+
5
+ let(:rule) { test.new(*nodes) }
6
+ let(:test) { AbstractMapper::Test::Rule = Class.new(described_class) }
7
+ let(:nodes) { [node] }
8
+ let(:node) { double }
9
+
10
+ describe ".new" do
11
+
12
+ subject { rule }
13
+ it { is_expected.to be_frozen }
14
+
15
+ end # describe .new
16
+
17
+ describe "#nodes" do
18
+
19
+ subject { rule.nodes }
20
+
21
+ it { is_expected.to eql nodes }
22
+ it { is_expected.to be_frozen }
23
+
24
+ it "doesn't freeze the source" do
25
+ expect { subject }.not_to change { nodes.frozen? }
26
+ end
27
+
28
+ end # describe #nodes
29
+
30
+ describe "#call" do
31
+
32
+ subject { rule.call }
33
+
34
+ before { test.send(:define_method, :optimize?) { true } }
35
+ before { test.send(:define_method, :optimize) { [:foo] } }
36
+
37
+ context "when #optimize? returns true" do
38
+
39
+ before { test.send(:define_method, :optimize?) { true } }
40
+ it { is_expected.to eql [:foo] }
41
+
42
+ end # context
43
+
44
+ context "when #optimize? returns false" do
45
+
46
+ before { test.send(:define_method, :optimize?) { false } }
47
+ it { is_expected.to eql [node] }
48
+
49
+ end # context
50
+
51
+ context "when #optimize returns non-array" do
52
+
53
+ before { test.send(:define_method, :optimize) { :foo } }
54
+ it { is_expected.to eql [:foo] }
55
+
56
+ end # contex
57
+
58
+ context "when #optimize returns nils" do
59
+
60
+ before { test.send(:define_method, :optimize) { [nil, nil] } }
61
+ it { is_expected.to eql [] }
62
+
63
+ end # contex
64
+
65
+ end # describe #call
66
+
67
+ describe ".transproc" do
68
+
69
+ before do
70
+ test.send(:define_method, :optimize?) { true }
71
+ test.send(:define_method, :optimize) { nodes.reverse }
72
+ allow(test).to receive(:composer) { :compact }
73
+ end
74
+
75
+ subject { test.transproc[array] }
76
+
77
+ let(:array) { [1, 2, 3] }
78
+
79
+ it { is_expected.to eql [2, 3, 1] }
80
+
81
+ end # describe .transproc
82
+
83
+ end # describe AbstractMapper::Rule
@@ -0,0 +1,88 @@
1
+ # encoding: utf-8
2
+
3
+ describe AbstractMapper::Rules do
4
+
5
+ let(:rules) { described_class.new }
6
+ let(:foo) { AbstractMapper::Test::Foo = Class.new(AbstractMapper::SoleRule) }
7
+ let(:bar) { AbstractMapper::Test::Bar = Class.new(AbstractMapper::PairRule) }
8
+
9
+ describe ".new" do
10
+
11
+ subject { rules }
12
+ it { is_expected.to be_frozen }
13
+
14
+ end # describe .new
15
+
16
+ describe "#registry" do
17
+
18
+ subject { rules.registry }
19
+
20
+ context "by default" do
21
+
22
+ let(:rules) { described_class.new }
23
+ it { is_expected.to eql [] }
24
+ it { is_expected.to be_frozen }
25
+
26
+ end # context
27
+
28
+ context "initialized" do
29
+
30
+ let(:rules) { described_class.new registry }
31
+ let(:registry) { [foo, bar] }
32
+
33
+ it { is_expected.to eql registry }
34
+ it { is_expected.to be_frozen }
35
+
36
+ it "doesn't freezes the source" do
37
+ expect { subject }.not_to change { registry.frozen? }
38
+ end
39
+
40
+ end # context
41
+
42
+ end # describe #registry
43
+
44
+ describe "#<<" do
45
+
46
+ subject { rules << bar }
47
+
48
+ let(:rules) { described_class.new [foo] }
49
+
50
+ it "updates the registry" do
51
+ expect(subject).to be_kind_of described_class
52
+ expect(subject.registry).to eql [foo, bar]
53
+ end
54
+
55
+ end # describe #<<
56
+
57
+ describe "#[]" do
58
+
59
+ before do
60
+ foo.send(:define_method, :optimize?) { true }
61
+ foo.send(:define_method, :optimize) { node + 1 }
62
+ bar.send(:define_method, :optimize?) { left == right }
63
+ bar.send(:define_method, :optimize) { left + right }
64
+ end
65
+
66
+ context "when no rule is set" do
67
+
68
+ let(:nodes) { [1, 1, 2, 5] }
69
+
70
+ subject { rules[nodes] }
71
+ it { is_expected.to eql nodes }
72
+
73
+ end # context
74
+
75
+ context "when rules are set" do
76
+
77
+ let(:rules) { described_class.new [foo, bar, foo] }
78
+ let(:nodes) { [1, 1, 2] }
79
+
80
+ subject { rules[nodes] }
81
+ it { is_expected.to eql [6, 4] }
82
+ # [1, 1, 2] -foo-> [2, 2, 3] -foo-> [3, 3, 4] -bar-> [6, 4]
83
+
84
+ end # context
85
+
86
+ end # describe #[]
87
+
88
+ end # describe AbstractMapper::Rules
@@ -0,0 +1,113 @@
1
+ # encoding: utf-8
2
+
3
+ describe AbstractMapper::Settings do
4
+
5
+ let!(:rule) do
6
+ AbstractMapper::Test::Rule = Class.new(AbstractMapper::SoleRule)
7
+ end
8
+ let!(:node) do
9
+ AbstractMapper::Test::Node = Class.new(AbstractMapper::Node)
10
+ end
11
+
12
+ let(:settings) do
13
+ described_class.new do
14
+ command :foo, AbstractMapper::Test::Node
15
+ rule AbstractMapper::Test::Rule
16
+ end
17
+ end
18
+
19
+ describe ".new" do
20
+
21
+ context "with a valid block" do
22
+
23
+ subject { settings }
24
+ it { is_expected.to be_frozen }
25
+
26
+ end # context
27
+
28
+ context "with invalid command" do
29
+
30
+ subject { described_class.new { command :foo, String } }
31
+ it "fails" do
32
+ expect { subject }.to raise_error do |error|
33
+ expect(error).to be_kind_of AbstractMapper::Errors::WrongNode
34
+ expect(error.message).to include "String"
35
+ end
36
+ end
37
+
38
+ end # context
39
+
40
+ context "with invalid rule" do
41
+
42
+ subject { described_class.new { rule String } }
43
+ it "fails" do
44
+ expect { subject }.to raise_error do |error|
45
+ expect(error).to be_kind_of AbstractMapper::Errors::WrongRule
46
+ expect(error.message).to include "String"
47
+ end
48
+ end
49
+
50
+ end # context
51
+
52
+ context "without a block" do
53
+
54
+ subject { described_class.new }
55
+ it "doesn't fail" do
56
+ expect { subject }.not_to raise_error
57
+ end
58
+
59
+ end # context
60
+
61
+ end # describe .new
62
+
63
+ describe "#commands" do
64
+
65
+ subject { settings.commands }
66
+
67
+ it { is_expected.to be_kind_of AbstractMapper::Commands }
68
+
69
+ it "contains registered commands" do
70
+ expect(subject.registry).to eql(foo: node)
71
+ end
72
+
73
+ end # describe #commands
74
+
75
+ describe "#rules" do
76
+
77
+ subject { settings.rules }
78
+
79
+ it { is_expected.to be_kind_of AbstractMapper::Rules }
80
+
81
+ it "contains registered rules" do
82
+ expect(subject.registry).to eql [rule]
83
+ end
84
+
85
+ end # describe #rules
86
+
87
+ describe "#builder" do
88
+
89
+ subject { settings.builder }
90
+
91
+ it "subclasses AbstractMapper::Builder" do
92
+ expect(subject.superclass).to eql AbstractMapper::Builder
93
+ end
94
+
95
+ it "uses registered commands" do
96
+ expect(subject.commands).to eql settings.commands
97
+ end
98
+
99
+ end # describe #builder
100
+
101
+ describe "#optimizer" do
102
+
103
+ subject { settings.optimizer }
104
+
105
+ it { is_expected.to be_kind_of AbstractMapper::Optimizer }
106
+
107
+ it "uses registered rules" do
108
+ expect(subject.rules).to eql settings.rules
109
+ end
110
+
111
+ end # describe #optimizer
112
+
113
+ end # describe AbstractMapper::Settings
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ describe AbstractMapper::SoleRule do
4
+
5
+ let(:rule) { test.new(node) }
6
+ let(:test) { AbstractMapper::Test::Rule = Class.new(described_class) }
7
+ let(:nodes) { [node] }
8
+ let(:node) { double }
9
+
10
+ describe ".composer" do
11
+
12
+ subject { test.composer }
13
+ it { is_expected.to eql :filter }
14
+
15
+ end # describe .pair?
16
+
17
+ describe ".new" do
18
+
19
+ subject { rule }
20
+
21
+ it { is_expected.to be_kind_of AbstractMapper::Rule }
22
+ it { is_expected.to be_frozen }
23
+
24
+ it "denies second argument" do
25
+ expect { test.new(node, node) }.to raise_error(ArgumentError)
26
+ end
27
+
28
+ end # describe .new
29
+
30
+ describe "#node" do
31
+
32
+ subject { rule.node }
33
+ it { is_expected.to eql node }
34
+
35
+ end # describe #node
36
+
37
+ describe "#transproc" do
38
+
39
+ before do
40
+ test.send(:define_method, :optimize?) { node > 3 }
41
+ test.send(:define_method, :optimize) { -node if node < 7 }
42
+ end
43
+
44
+ subject { test.transproc[array] }
45
+
46
+ let(:array) { [5, 1, 38, 4] }
47
+ it { is_expected.to eql [-5, 1, -4] }
48
+
49
+ end # describe #transproc
50
+
51
+ end # describe AbstractMapper::SoleRule
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ describe AbstractMapper do
4
+
5
+ let(:test) { Class.new(described_class) }
6
+ let(:tree) { double transproc: transproc }
7
+ let(:transproc) { double }
8
+
9
+ let(:mapper) do
10
+ allow(transproc).to receive(:call) { |input| "called: #{input}" }
11
+ allow(test).to receive(:finalize) { tree }
12
+ test.new
13
+ end
14
+
15
+ describe ".new" do
16
+
17
+ subject { mapper }
18
+ it { is_expected.to be_frozen }
19
+
20
+ end # describe .new
21
+
22
+ describe "#tree" do
23
+
24
+ subject { mapper.tree }
25
+ it { is_expected.to eql tree }
26
+
27
+ end # describe #tree
28
+
29
+ describe "#call" do
30
+
31
+ subject { mapper.call :foo }
32
+ it { is_expected.to eql "called: foo" }
33
+
34
+ end # describe #call
35
+
36
+ end # describe AbstractMapper