katuv 0.0.1 → 0.0.2
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.
- data/.gitignore +1 -0
- data/.travis.yml +6 -0
- data/CHANGELOG +5 -0
- data/Gemfile +7 -0
- data/NOTES.md +50 -0
- data/README.md +1 -1
- data/Rakefile +35 -1
- data/lib/katuv.rb +10 -3
- data/lib/katuv/dsl.rb +46 -0
- data/lib/katuv/naming_behavior.rb +22 -0
- data/lib/katuv/node.rb +4 -105
- data/lib/katuv/node_behavior.rb +27 -0
- data/lib/katuv/object_set.rb +9 -0
- data/lib/katuv/version.rb +1 -1
- data/lib/katuv/visitor_behavior.rb +16 -0
- data/spec/dsl_spec.rb +31 -0
- data/spec/node_spec.rb +61 -0
- data/spec/object_set_spec.rb +5 -0
- data/spec/shared/naming_behavior_examples.rb +11 -0
- data/spec/shared/visitor_behavior_examples.rb +165 -0
- data/spec/spec_helper.rb +3 -0
- metadata +42 -4
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/CHANGELOG
ADDED
data/Gemfile
CHANGED
data/NOTES.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Random ideas
|
2
|
+
|
3
|
+
- Make Katuv have it's own DSL, to specify dsls. eg:
|
4
|
+
|
5
|
+
katuv do
|
6
|
+
nonterminal 'foo' do
|
7
|
+
terminal 'bar'
|
8
|
+
nonterminal 'baz', name: false
|
9
|
+
end
|
10
|
+
|
11
|
+
nonterminal baz do
|
12
|
+
multiple 'quux'
|
13
|
+
multiple 'qwix'
|
14
|
+
nonterminal 'bang'
|
15
|
+
end
|
16
|
+
|
17
|
+
terminal 'quux'
|
18
|
+
|
19
|
+
nonterminal 'qwix' do
|
20
|
+
terminal 'rumplestiltskin'
|
21
|
+
end
|
22
|
+
|
23
|
+
nonterminal 'bang' do
|
24
|
+
nonterminal 'bang', allow_blank: true
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
Which would build all the appropriate classes automatically for a DSL like:
|
30
|
+
|
31
|
+
|
32
|
+
foo 'name' do
|
33
|
+
bar 'name'
|
34
|
+
baz do
|
35
|
+
quux '1'
|
36
|
+
quux '2'
|
37
|
+
qwix do
|
38
|
+
rumplestiltskin 'yep'
|
39
|
+
end
|
40
|
+
|
41
|
+
bang do
|
42
|
+
bang do
|
43
|
+
bang
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
- Bonus points if the above is self-hosting.
|
50
|
+
- More points if it can generate code or operate 'in-memory'
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Katuv
|
1
|
+
# Katuv [](http://badge.fury.io/rb/katuv) [](http://travis-ci.org/jfredett/katuv) [](https://codeclimate.com/github/jfredett/katuv) [](https://coveralls.io/r/jfredett/katuv)
|
2
2
|
|
3
3
|
Katuv is a tool for defining and transforming Embedded Ruby DSLs (EDSLs). It
|
4
4
|
provides a simple facility to define DSL components and their connections.
|
data/Rakefile
CHANGED
@@ -1 +1,35 @@
|
|
1
|
-
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
desc 'run specs'
|
7
|
+
RSpec::Core::RakeTask.new do |task|
|
8
|
+
task.rspec_opts = ["-c", "-f progress"]
|
9
|
+
end
|
10
|
+
|
11
|
+
task :default => :spec
|
12
|
+
|
13
|
+
|
14
|
+
task :flog do
|
15
|
+
puts "#### FLOG ####"
|
16
|
+
system 'flog lib/*'
|
17
|
+
puts "##############"
|
18
|
+
end
|
19
|
+
|
20
|
+
task :flay do
|
21
|
+
puts "#### FLAY ####"
|
22
|
+
system 'flay lib/*'
|
23
|
+
puts "##############"
|
24
|
+
end
|
25
|
+
|
26
|
+
task :mutant, [:klass] do |_, args|
|
27
|
+
puts "#### MUTANT TESTING ####"
|
28
|
+
system "mutant -I lib -r katuv --rspec-full #{args[:name] || '::Katuv'}"
|
29
|
+
puts "########################"
|
30
|
+
end
|
31
|
+
|
32
|
+
task :metrics => [:flog, :flay]
|
33
|
+
|
34
|
+
|
35
|
+
task :all => [:spec, :mutant, :metrics]
|
data/lib/katuv.rb
CHANGED
@@ -1,5 +1,12 @@
|
|
1
|
+
module Katuv; end
|
2
|
+
|
1
3
|
require "katuv/version"
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
5
|
+
require 'katuv/object_set'
|
6
|
+
|
7
|
+
require 'katuv/visitor_behavior'
|
8
|
+
require 'katuv/naming_behavior'
|
9
|
+
require 'katuv/node_behavior'
|
10
|
+
require 'katuv/dsl'
|
11
|
+
|
12
|
+
require 'katuv/node'
|
data/lib/katuv/dsl.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
module Katuv
|
2
|
+
module DSL
|
3
|
+
def nonterminal(type)
|
4
|
+
raise "NonterminalInTerminalError" if terminal?
|
5
|
+
define_method(_type_to_method_name(type)) do |name=nil, opts={}, &block|
|
6
|
+
if children.has_key?(type) and children[type]
|
7
|
+
children[type].run(&block)
|
8
|
+
else
|
9
|
+
children[type] = type.new(name, opts.merge({parent: self}), &block)
|
10
|
+
end
|
11
|
+
children[type]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def terminal(type)
|
16
|
+
#should only allow one.
|
17
|
+
raise "InvalidNodeTypeError" unless type.terminal?
|
18
|
+
define_method(_type_to_method_name(type)) do |name=nil, opts={}, &block|
|
19
|
+
raise "TerminalAlreadySetError" if children.has_key?(type)
|
20
|
+
children[type] = type.new(name, opts.merge({parent: self}), &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
def terminal!
|
24
|
+
define_singleton_method(:terminal?) { true }
|
25
|
+
end
|
26
|
+
def terminal?; false end
|
27
|
+
|
28
|
+
def multiple(type)
|
29
|
+
#should store an entry in #children that is a list of all the instances
|
30
|
+
#it sees of this type. eg, `file 'x'; file 'y' #=> children[File] = [File<@name=x>, File<@name=y>]
|
31
|
+
raise "InvalidNodeTypeError" unless type.terminal?
|
32
|
+
define_method(_type_to_method_name(type)) do |name, opts={}, &block|
|
33
|
+
children[type] ||= ObjectSet.new
|
34
|
+
children[type] << type.new(name, opts.merge({parent: self}), &block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def _type_to_method_name(type)
|
39
|
+
if type.respond_to?(:name)
|
40
|
+
type.name
|
41
|
+
else
|
42
|
+
type.to_s
|
43
|
+
end.split('::').last.downcase
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Katuv
|
2
|
+
module NamingBehavior
|
3
|
+
def name
|
4
|
+
@name ||= self.class.name
|
5
|
+
end
|
6
|
+
|
7
|
+
#this is terrible
|
8
|
+
def method_name
|
9
|
+
#get the classname
|
10
|
+
self.class.name.to_s.
|
11
|
+
#remove the module
|
12
|
+
split('::').last.
|
13
|
+
#convert FooBar -> _Foo_Bar
|
14
|
+
gsub(/[A-Z]/, '_\&').
|
15
|
+
#drop the leading _
|
16
|
+
sub(/^_/, '').
|
17
|
+
#downcase everything to get foo_bar
|
18
|
+
downcase
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
data/lib/katuv/node.rb
CHANGED
@@ -1,114 +1,13 @@
|
|
1
|
-
# Represents a single node in the AST of a project structure
|
2
1
|
module Katuv
|
3
2
|
module Node
|
4
3
|
def self.included(base)
|
5
|
-
base.send(:include,
|
6
|
-
base.send(:extend, ClassMethods)
|
4
|
+
base.send(:include, VisitorBehavior)
|
7
5
|
base.send(:include, Enumerable)
|
8
|
-
end
|
9
|
-
|
10
|
-
module InstanceMethods
|
11
|
-
#this is terrible
|
12
|
-
def method_name
|
13
|
-
#get the classname
|
14
|
-
self.class.name.
|
15
|
-
#remove the module
|
16
|
-
to_s.split('::').last.
|
17
|
-
#convert FooBar -> _Foo_Bar
|
18
|
-
gsub(/[A-Z]/, '_\&').
|
19
|
-
#drop the leading _
|
20
|
-
gsub(/^_/, '').
|
21
|
-
#downcase everything to get foo_bar
|
22
|
-
downcase.to_sym
|
23
|
-
end
|
24
|
-
|
25
|
-
def visit(visitor)
|
26
|
-
visitor.before_visit!(self)
|
27
|
-
visitor.call(self)
|
28
|
-
|
29
|
-
each do |c|
|
30
|
-
c.visit(visitor)
|
31
|
-
end
|
32
|
-
|
33
|
-
visitor.after_visit!(self)
|
34
|
-
nil
|
35
|
-
end
|
36
|
-
|
37
|
-
def run
|
38
|
-
end
|
39
|
-
|
40
|
-
def each(&block)
|
41
|
-
children.values.each(&block)
|
42
|
-
end
|
43
|
-
|
44
|
-
def children
|
45
|
-
@children ||= {}
|
46
|
-
end
|
47
|
-
|
48
|
-
def name
|
49
|
-
@name || self.class.name
|
50
|
-
end
|
51
|
-
|
52
|
-
def initialize(name = nil, opts = {}, &block)
|
53
|
-
@parent = opts[:parent]
|
54
|
-
@name = name
|
55
|
-
@opts = opts
|
56
|
-
instance_eval &block if block_given?
|
57
|
-
end
|
58
|
-
attr_reader :parent, :name
|
59
|
-
|
60
|
-
def terminal?
|
61
|
-
self.class.terminal?
|
62
|
-
end
|
63
|
-
|
64
|
-
def has_children?
|
65
|
-
children.any?
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
module ClassMethods
|
70
|
-
def nonterminal(type)
|
71
|
-
raise "NonterminalInTerminalError" if terminal?
|
72
|
-
define_method(_type_to_method_name(type)) do |name=nil, opts={}, &block|
|
73
|
-
if children.has_key?(type) and children[type]
|
74
|
-
children[type].run(&block)
|
75
|
-
else
|
76
|
-
children[type] = type.new(name, opts.merge({parent: self}), &block)
|
77
|
-
end
|
78
|
-
children[type]
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def terminal(type)
|
83
|
-
#should only allow one.
|
84
|
-
raise "InvalidNodeTypeError" unless type.terminal?
|
85
|
-
define_method(_type_to_method_name(type)) do |name=nil, opts={}, &block|
|
86
|
-
raise "TerminalAlreadySetError" if children.has_key?(type)
|
87
|
-
children[type] = type.new(name, opts.merge({parent: self}), &block)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
def terminal!
|
91
|
-
define_singleton_method(:terminal?) { true }
|
92
|
-
end
|
93
|
-
def terminal?; false end
|
94
6
|
|
95
|
-
|
96
|
-
|
97
|
-
#it sees of this type. eg, `file 'x'; file 'y' #=> children[File] = [File<@name=x>, File<@name=y>]
|
98
|
-
raise "InvalidNodeTypeError" unless type.terminal?
|
99
|
-
define_method(_type_to_method_name(type)) do |name, opts={}, &block|
|
100
|
-
children[type] ||= ObjectSet.new
|
101
|
-
children[type] << type.new(name, opts.merge({parent: self}), &block)
|
102
|
-
end
|
103
|
-
end
|
7
|
+
base.send(:include, NamingBehavior)
|
8
|
+
base.send(:include, NodeBehavior)
|
104
9
|
|
105
|
-
|
106
|
-
if type.respond_to?(:name)
|
107
|
-
type.name
|
108
|
-
else
|
109
|
-
type.to_s
|
110
|
-
end.split('::').last.downcase
|
111
|
-
end
|
10
|
+
base.send(:extend, DSL)
|
112
11
|
end
|
113
12
|
end
|
114
13
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Katuv
|
2
|
+
module NodeBehavior
|
3
|
+
def initialize(name = nil, opts = {}, &block)
|
4
|
+
@parent = opts[:parent]
|
5
|
+
@name = name
|
6
|
+
@opts = opts
|
7
|
+
instance_eval &block if block_given?
|
8
|
+
end
|
9
|
+
attr_reader :parent, :name
|
10
|
+
|
11
|
+
def terminal?
|
12
|
+
self.class.terminal?
|
13
|
+
end
|
14
|
+
|
15
|
+
def each(&block)
|
16
|
+
children.values.each(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def children
|
20
|
+
@children ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def has_children?
|
24
|
+
children.any?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/katuv/version.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Katuv
|
2
|
+
module VisitorBehavior
|
3
|
+
def visit(visitor)
|
4
|
+
visitor.before(self) if visitor.respond_to? :before
|
5
|
+
|
6
|
+
if visitor.respond_to? method_name
|
7
|
+
visitor.send(method_name.to_sym, self)
|
8
|
+
else
|
9
|
+
visitor.unknown(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
visitor.after(self) if visitor.respond_to? :after
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/spec/dsl_spec.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'The Katuv DSL' do
|
4
|
+
before :all do
|
5
|
+
class Example
|
6
|
+
end
|
7
|
+
end
|
8
|
+
subject { Example }
|
9
|
+
|
10
|
+
context 'before inclusion' do
|
11
|
+
describe 'api' do
|
12
|
+
it { should_not respond_to :terminal }
|
13
|
+
it { should_not respond_to :nonterminal }
|
14
|
+
it { should_not respond_to :multiple }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'after inclusion' do
|
19
|
+
before do
|
20
|
+
class Example
|
21
|
+
include Katuv::Node
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'api' do
|
26
|
+
it { should respond_to :terminal }
|
27
|
+
it { should respond_to :nonterminal }
|
28
|
+
it { should respond_to :multiple }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/spec/node_spec.rb
CHANGED
@@ -1 +1,62 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Katuv::Node do
|
4
|
+
before :all do
|
5
|
+
class ExampleTerminal
|
6
|
+
include Katuv::Node
|
7
|
+
terminal!
|
8
|
+
end
|
9
|
+
|
10
|
+
class ExampleNonterminal
|
11
|
+
include Katuv::Node
|
12
|
+
|
13
|
+
terminal ExampleTerminal
|
14
|
+
nonterminal ExampleNonterminal
|
15
|
+
end
|
16
|
+
|
17
|
+
class Example
|
18
|
+
include Katuv::Node
|
19
|
+
terminal ExampleTerminal
|
20
|
+
nonterminal ExampleNonterminal
|
21
|
+
end
|
22
|
+
end
|
23
|
+
after :all do
|
24
|
+
Object.send(:remove_const, :Example)
|
25
|
+
Object.send(:remove_const, :ExampleTerminal)
|
26
|
+
Object.send(:remove_const, :ExampleNonterminal)
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'Example' do
|
30
|
+
subject { Example.new }
|
31
|
+
it_should_behave_like 'a nameable class'
|
32
|
+
it_should_behave_like 'a class with the naming behavior'
|
33
|
+
it_should_behave_like 'a visitable class'
|
34
|
+
it_should_behave_like 'a class with the visitable behavior'
|
35
|
+
|
36
|
+
its(:method_name) { should == "example" }
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'ExampleTerminal' do
|
40
|
+
subject { ExampleTerminal.new }
|
41
|
+
|
42
|
+
it_should_behave_like 'a nameable class'
|
43
|
+
it_should_behave_like 'a class with the naming behavior'
|
44
|
+
it_should_behave_like 'a visitable class'
|
45
|
+
it_should_behave_like 'a class with the visitable behavior'
|
46
|
+
|
47
|
+
its(:method_name) { should == "example_terminal" }
|
48
|
+
|
49
|
+
it { should be_terminal }
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'ExampleNonterminal' do
|
53
|
+
subject { ExampleNonterminal.new }
|
54
|
+
|
55
|
+
it_should_behave_like 'a nameable class'
|
56
|
+
it_should_behave_like 'a class with the naming behavior'
|
57
|
+
it_should_behave_like 'a visitable class'
|
58
|
+
it_should_behave_like 'a class with the visitable behavior'
|
59
|
+
|
60
|
+
its(:method_name) { should == "example_nonterminal" }
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
shared_examples_for 'a nameable class' do
|
2
|
+
its(:class) { should respond_to :name }
|
3
|
+
end
|
4
|
+
|
5
|
+
shared_examples_for 'a class with the naming behavior' do
|
6
|
+
it { should respond_to :name }
|
7
|
+
it { should respond_to :method_name }
|
8
|
+
|
9
|
+
its(:method_name) { should_not =~ /[A-Z]/ } #no capitals
|
10
|
+
its(:method_name) { should_not =~ /[\t\n\r ]/ } #no spaces
|
11
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
shared_examples_for 'a visitable class' do
|
2
|
+
it { should respond_to :each }
|
3
|
+
it { should respond_to :method_name }
|
4
|
+
end
|
5
|
+
|
6
|
+
shared_examples_for 'a class with the visitable behavior' do
|
7
|
+
let(:visitor) { double('visitor') }
|
8
|
+
before { visitor.stub(:unknown) }
|
9
|
+
|
10
|
+
context 'with before hook' do
|
11
|
+
before { visitor.stub(:before) }
|
12
|
+
|
13
|
+
it 'calls the before hook' do
|
14
|
+
subject.visit(visitor)
|
15
|
+
visitor.should have_received :before
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with after hook' do
|
19
|
+
before { visitor.stub(:after) }
|
20
|
+
|
21
|
+
it 'calls the after hook' do
|
22
|
+
subject.visit(visitor)
|
23
|
+
visitor.should have_received :after
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with class-dispatch method defined' do
|
27
|
+
before { visitor.stub(subject.method_name.to_sym) }
|
28
|
+
|
29
|
+
it 'calls the appropriate class method' do
|
30
|
+
subject.visit(visitor)
|
31
|
+
visitor.should have_received subject.method_name.to_sym
|
32
|
+
end
|
33
|
+
|
34
|
+
it "doesn't call the 'unknown' catchall method" do
|
35
|
+
subject.visit(visitor)
|
36
|
+
visitor.should_not have_received :unknown
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'with no class-dispatch method defined' do
|
41
|
+
before { visitor.stub(:unknown) }
|
42
|
+
|
43
|
+
it "calls the 'unknown' catchall method" do
|
44
|
+
subject.visit(visitor)
|
45
|
+
visitor.should have_received :unknown
|
46
|
+
end
|
47
|
+
|
48
|
+
it "doesn't call the class-dispatch method" do
|
49
|
+
subject.visit(visitor)
|
50
|
+
visitor.should_not have_received subject.method_name.to_sym
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'without after hook' do
|
56
|
+
it 'calls the after hook' do
|
57
|
+
subject.visit(visitor)
|
58
|
+
visitor.should_not have_received :after
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with class-dispatch method defined' do
|
62
|
+
before { visitor.stub(subject.method_name.to_sym) }
|
63
|
+
|
64
|
+
it 'calls the appropriate class method' do
|
65
|
+
subject.visit(visitor)
|
66
|
+
visitor.should have_received subject.method_name.to_sym
|
67
|
+
end
|
68
|
+
|
69
|
+
it "doesn't call the 'unknown' catchall method" do
|
70
|
+
subject.visit(visitor)
|
71
|
+
visitor.should_not have_received :unknown
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'with no class-dispatch method defined' do
|
76
|
+
it "calls the 'unknown' catchall method" do
|
77
|
+
subject.visit(visitor)
|
78
|
+
visitor.should have_received :unknown
|
79
|
+
end
|
80
|
+
|
81
|
+
it "doesn't call the class-dispatch method" do
|
82
|
+
subject.visit(visitor)
|
83
|
+
visitor.should_not have_received subject.method_name.to_sym
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'without before hook' do
|
90
|
+
it 'calls the before hook' do
|
91
|
+
subject.visit(visitor)
|
92
|
+
visitor.should_not have_received :before
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'with after hook' do
|
96
|
+
before { visitor.stub(:after) }
|
97
|
+
|
98
|
+
it 'calls the after hook' do
|
99
|
+
subject.visit(visitor)
|
100
|
+
visitor.should have_received :after
|
101
|
+
end
|
102
|
+
|
103
|
+
context 'with class-dispatch method defined' do
|
104
|
+
before { visitor.stub(subject.method_name.to_sym) }
|
105
|
+
|
106
|
+
it 'calls the appropriate class method' do
|
107
|
+
subject.visit(visitor)
|
108
|
+
visitor.should have_received subject.method_name.to_sym
|
109
|
+
end
|
110
|
+
|
111
|
+
it "doesn't call the 'unknown' catchall method" do
|
112
|
+
subject.visit(visitor)
|
113
|
+
visitor.should_not have_received :unknown
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'with no class-dispatch method defined' do
|
118
|
+
|
119
|
+
it "calls the 'unknown' catchall method" do
|
120
|
+
subject.visit(visitor)
|
121
|
+
visitor.should have_received :unknown
|
122
|
+
end
|
123
|
+
it "doesn't call the class-dispatch method" do
|
124
|
+
subject.visit(visitor)
|
125
|
+
visitor.should_not have_received subject.method_name.to_sym
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'without after hook' do
|
132
|
+
it 'does not call the after hook' do
|
133
|
+
subject.visit(visitor)
|
134
|
+
visitor.should_not have_received :after
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'with class-dispatch method defined' do
|
138
|
+
before { visitor.stub(subject.method_name.to_sym) }
|
139
|
+
|
140
|
+
it 'calls the appropriate class method' do
|
141
|
+
subject.visit(visitor)
|
142
|
+
visitor.should have_received subject.method_name.to_sym
|
143
|
+
end
|
144
|
+
|
145
|
+
it "doesn't call the 'unknown' catchall method" do
|
146
|
+
subject.visit(visitor)
|
147
|
+
visitor.should_not have_received :unknown
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'with no class-dispatch method defined' do
|
152
|
+
|
153
|
+
it "calls the 'unknown' catchall method" do
|
154
|
+
subject.visit(visitor)
|
155
|
+
visitor.should have_received :unknown
|
156
|
+
end
|
157
|
+
|
158
|
+
it "doesn't call the class-dispatch method" do
|
159
|
+
subject.visit(visitor)
|
160
|
+
visitor.should_not have_received subject.method_name.to_sym
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
name: katuv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Joe Fredette
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-29 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: A tool for parsing and transforming internal Ruby DSLs
|
15
15
|
email:
|
@@ -22,10 +22,16 @@ files:
|
|
22
22
|
LmdpdGlnbm9yZQ==
|
23
23
|
- !binary |-
|
24
24
|
LnJ2bXJj
|
25
|
+
- !binary |-
|
26
|
+
LnRyYXZpcy55bWw=
|
27
|
+
- !binary |-
|
28
|
+
Q0hBTkdFTE9H
|
25
29
|
- !binary |-
|
26
30
|
R2VtZmlsZQ==
|
27
31
|
- !binary |-
|
28
32
|
TElDRU5TRS50eHQ=
|
33
|
+
- !binary |-
|
34
|
+
Tk9URVMubWQ=
|
29
35
|
- !binary |-
|
30
36
|
UkVBRE1FLm1k
|
31
37
|
- !binary |-
|
@@ -34,12 +40,30 @@ files:
|
|
34
40
|
a2F0dXYuZ2Vtc3BlYw==
|
35
41
|
- !binary |-
|
36
42
|
bGliL2thdHV2LnJi
|
43
|
+
- !binary |-
|
44
|
+
bGliL2thdHV2L2RzbC5yYg==
|
45
|
+
- !binary |-
|
46
|
+
bGliL2thdHV2L25hbWluZ19iZWhhdmlvci5yYg==
|
37
47
|
- !binary |-
|
38
48
|
bGliL2thdHV2L25vZGUucmI=
|
49
|
+
- !binary |-
|
50
|
+
bGliL2thdHV2L25vZGVfYmVoYXZpb3IucmI=
|
51
|
+
- !binary |-
|
52
|
+
bGliL2thdHV2L29iamVjdF9zZXQucmI=
|
39
53
|
- !binary |-
|
40
54
|
bGliL2thdHV2L3ZlcnNpb24ucmI=
|
55
|
+
- !binary |-
|
56
|
+
bGliL2thdHV2L3Zpc2l0b3JfYmVoYXZpb3IucmI=
|
57
|
+
- !binary |-
|
58
|
+
c3BlYy9kc2xfc3BlYy5yYg==
|
41
59
|
- !binary |-
|
42
60
|
c3BlYy9ub2RlX3NwZWMucmI=
|
61
|
+
- !binary |-
|
62
|
+
c3BlYy9vYmplY3Rfc2V0X3NwZWMucmI=
|
63
|
+
- !binary |-
|
64
|
+
c3BlYy9zaGFyZWQvbmFtaW5nX2JlaGF2aW9yX2V4YW1wbGVzLnJi
|
65
|
+
- !binary |-
|
66
|
+
c3BlYy9zaGFyZWQvdmlzaXRvcl9iZWhhdmlvcl9leGFtcGxlcy5yYg==
|
43
67
|
- !binary |-
|
44
68
|
c3BlYy9zcGVjX2hlbHBlci5yYg==
|
45
69
|
homepage: ''
|
@@ -49,17 +73,23 @@ rdoc_options: []
|
|
49
73
|
require_paths:
|
50
74
|
- lib
|
51
75
|
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
52
77
|
requirements:
|
53
78
|
- - ! '>='
|
54
79
|
- !ruby/object:Gem::Version
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
hash: 2002549777813010636
|
55
83
|
version: '0'
|
56
|
-
none: false
|
57
84
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
58
86
|
requirements:
|
59
87
|
- - ! '>='
|
60
88
|
- !ruby/object:Gem::Version
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
hash: 2002549777813010636
|
61
92
|
version: '0'
|
62
|
-
none: false
|
63
93
|
requirements: []
|
64
94
|
rubyforge_project:
|
65
95
|
rubygems_version: 1.8.25
|
@@ -67,7 +97,15 @@ signing_key:
|
|
67
97
|
specification_version: 3
|
68
98
|
summary: A tool for parsing and transforming internal Ruby DSLs
|
69
99
|
test_files:
|
100
|
+
- !binary |-
|
101
|
+
c3BlYy9kc2xfc3BlYy5yYg==
|
70
102
|
- !binary |-
|
71
103
|
c3BlYy9ub2RlX3NwZWMucmI=
|
104
|
+
- !binary |-
|
105
|
+
c3BlYy9vYmplY3Rfc2V0X3NwZWMucmI=
|
106
|
+
- !binary |-
|
107
|
+
c3BlYy9zaGFyZWQvbmFtaW5nX2JlaGF2aW9yX2V4YW1wbGVzLnJi
|
108
|
+
- !binary |-
|
109
|
+
c3BlYy9zaGFyZWQvdmlzaXRvcl9iZWhhdmlvcl9leGFtcGxlcy5yYg==
|
72
110
|
- !binary |-
|
73
111
|
c3BlYy9zcGVjX2hlbHBlci5yYg==
|