hutch-xamplr 1.2.0 → 1.3.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.
Files changed (37) hide show
  1. data/CHANGES.txt +14 -0
  2. data/README.rdoc +24 -4
  3. data/Rakefile +3 -3
  4. data/VERSION.yml +2 -2
  5. data/examples/employees/final/xampl-gen.rb +38 -0
  6. data/examples/employees/final/xml/ddd-final.xml +86 -0
  7. data/examples/employees/first/xampl-gen.rb +38 -0
  8. data/examples/employees/first/xml/ddd-first.xml +48 -0
  9. data/examples/employees/twist/twist.graphml +333 -0
  10. data/examples/employees/twist/xampl-gen.rb +38 -0
  11. data/examples/employees/twist/xml/twist.xml +90 -0
  12. data/examples/employees/xamplr-twist.xml +2 -0
  13. data/examples/employees/yuml-diagrams/ddd-final.png +0 -0
  14. data/examples/employees/yuml-diagrams/ddd-final.yuml +8 -0
  15. data/examples/employees/yuml-diagrams/ddd-first.png +0 -0
  16. data/examples/employees/yuml-diagrams/ddd-first.yuml +7 -0
  17. data/examples/employees/yuml-diagrams/final-yed.png +0 -0
  18. data/examples/employees/yuml-diagrams/first-yed.png +0 -0
  19. data/examples/employees/yuml-diagrams/twist.png +0 -0
  20. data/examples/employees/yuml-diagrams/twist.yuml +12 -0
  21. data/examples/employees/yuml-diagrams/xamplr-final-no-mixins.png +0 -0
  22. data/examples/employees/yuml-diagrams/xamplr-final-simplified.png +0 -0
  23. data/examples/employees/yuml-diagrams/xamplr-final-with-mixins.png +0 -0
  24. data/examples/employees/yuml-diagrams/yuml-simplified.txt +19 -0
  25. data/examples/employees/yuml-diagrams/yuml-with-mixins.txt +53 -0
  26. data/examples/employees/yuml-diagrams/yuml.txt +27 -0
  27. data/examples/random-people-shared-addresses/xampl-gen.rb +2 -0
  28. data/examples/random-people/xampl-gen.rb +2 -0
  29. data/examples/read-testing/xampl-gen.rb +2 -0
  30. data/examples/tokyo-cabinet-experimental/xampl-gen.rb +2 -0
  31. data/lib/xamplr-generator.rb +0 -1
  32. data/lib/xamplr.rb +1 -1
  33. data/lib/xamplr/graphml-out.rb +0 -12
  34. data/lib/xamplr/persisters/tokyo-cabinet.rb +12 -2
  35. data/lib/xamplr/xampl-generator.rb +4 -0
  36. data/lib/xamplr/yuml-out.rb +136 -0
  37. metadata +30 -4
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby -w -I..
2
+
3
+ if $0 == __FILE__ then
4
+
5
+ class File
6
+ def File.sjoin(*args)
7
+ File.join(args.select{ | o | o })
8
+ end
9
+ end
10
+
11
+ $LOAD_PATH.unshift('../../lib/')
12
+
13
+ require 'xamplr-generator'
14
+
15
+ include XamplGenerator
16
+ include Xampl
17
+
18
+ Xampl.transaction("setup", :in_memory) do
19
+ directory = File.sjoin(".", "xampl_generated_code")
20
+
21
+ options = Xampl.make(Options) do |options|
22
+ options.new_index_attribute("pid").persisted = true
23
+ options.new_index_attribute("id")
24
+
25
+ options.resolve("http://example.com/employees", "Employees", "emp")
26
+ end
27
+
28
+ filenames = Dir.glob("./xml/**/*.xml")
29
+
30
+ generator = Generator.new
31
+ generator.go(:options => options,
32
+ :filenames => filenames,
33
+ :directory => directory)
34
+
35
+ puts generator.print_elements("./generated-elements.xml")
36
+ exit!
37
+ end
38
+ end
@@ -0,0 +1,90 @@
1
+ <!--
2
+ [RetirementPlan] ^[DefinedContribution],
3
+ [RetirementPlan] ^[DefinedBenefit],
4
+ [Payroll]^[HourlyPayroll],
5
+ [Payroll]^[SalariedPayroll],
6
+ [EmployeeType]->*[RetirementPlan],
7
+ [EmployeeType]->*[Payroll],
8
+ [Employee]*->[EmployeeType],
9
+ [Department]-*[Employee]
10
+ -->
11
+ <company pid=''
12
+ xmlns="http://example.com/employees">
13
+
14
+ <hourly-payroll pid='singleton'>
15
+ <__payroll__/>
16
+ </hourly-payroll>
17
+ <salaried-payroll pid='singleton'>
18
+ <__payroll__/>
19
+ </salaried-payroll>
20
+
21
+ <defined-contribution pid="singleton">
22
+ <retirement-plan/>
23
+ </defined-contribution>
24
+ <defined-benefit pid="singleton">
25
+ <retirement-plan/>
26
+ </defined-benefit>
27
+
28
+ <employee-type pid="">
29
+ <__payroll__ />
30
+ </employee-type>
31
+
32
+ <employee-type pid=''
33
+ title='janitor'>
34
+ <hourly-payroll pid='singleton'/>
35
+ <defined-contribution pid="singleton"/>
36
+ </employee-type>
37
+ <employee-type pid=''
38
+ title='receptionist'>
39
+ <hourly-payroll pid='singleton'/>
40
+ <defined-contribution pid="singleton"/>
41
+ </employee-type>
42
+ <employee-type pid=''
43
+ title='office-admin'>
44
+ <hourly-payroll pid='singleton'/>
45
+ <defined-benefit pid="singleton"/>
46
+ </employee-type>
47
+ <employee-type pid=''
48
+ title='engineer'>
49
+ <salaried-payroll pid='singleton'/>
50
+ <defined-benefit pid="singleton"/>
51
+ </employee-type>
52
+ <employee-type pid=''
53
+ title='manager'>
54
+ <salaried-payroll pid='singleton'/>
55
+ <defined-benefit pid="singleton"/>
56
+ </employee-type>
57
+
58
+
59
+ <department pid=''
60
+ name='widget design'>
61
+ <employee pid=''
62
+ name='tom'>
63
+ <employee-type pid=''
64
+ title='janitor'/>
65
+ </employee>
66
+ <employee pid=''
67
+ name='mary'
68
+ title='receptionist'>
69
+ <employee-type pid=''
70
+ title='receptionist'/>
71
+ </employee>
72
+ <employee pid=''
73
+ name='bob'
74
+ title='office-admin'>
75
+ <employee-type pid=''
76
+ title='office-admin'/>
77
+ </employee>
78
+
79
+ <employee pid=''
80
+ name='jack'>
81
+ <employee-type pid=''
82
+ title='engineer'/>
83
+ </employee>
84
+ <employee pid=''
85
+ name='jill'>
86
+ <employee-type pid=''
87
+ title='manager'/>
88
+ </employee>
89
+ </department>
90
+ </company>
@@ -0,0 +1,2 @@
1
+ <company pid='' xmlns="http://xampl.com/employees-twisted">
2
+ </company>
@@ -0,0 +1,8 @@
1
+ [RetirementPlan]^[DefinedContribution],
2
+ [RetirementPlan]^[DefinedBenefit],
3
+ [Payroll]^[HourlyPayroll],
4
+ [Payroll]^[SalariedPayroll],
5
+ [EmployeeType]->*[RetirementPlan],
6
+ [EmployeeType]->*[Payroll],
7
+ [Employee]*->[EmployeeType],
8
+ [Department]-*[Employee]
@@ -0,0 +1,7 @@
1
+ [RetirementPlan]^[DefinedContribution],
2
+ [RetirementPlan]^[DefinedBenefit],
3
+ [Employee]^[HourlyEmployee],
4
+ [Employee]^[SalariedEmployee],
5
+ [HourlyEmployee]->[DefinedContribution],
6
+ [SalariedEmployee]->[DefinedBenefit],
7
+ [Department]-*[Employee]
@@ -0,0 +1,12 @@
1
+ [RetirementPlan::Mixin]^[DefinedContribution],
2
+ [RetirementPlan::Mixin]^[DefinedBenefit],
3
+ [Payroll::Mixin]^[HourlyPayroll],
4
+ [Payroll::Mixin]^[SalariedPayroll],
5
+ [EmployeeType]->*[RetirementPlan::Mixin],
6
+ [EmployeeType]->*[Payroll::Mixin],
7
+ [Employee]*->[EmployeeType],
8
+ [Department]<->*[Employee],
9
+ [SalariedPayroll]->[Payroll],
10
+ [HourlyPayroll]->[Payroll],
11
+ [DefinedBenefit]->[RetirementPlan],
12
+ [DefinedContribution]->[RetirementPlan]
@@ -0,0 +1,19 @@
1
+ [Employees::HourlyPayroll{bg:red}],
2
+ [Employees::Payrole{bg:blue}],
3
+ [Employees::SalariedPayroll{bg:red}],
4
+ [Employees::DefinedContribution{bg:red}],
5
+ [Employees::RetirementPlan{bg:blue}],
6
+ [Employees::DefinedBenefit{bg:red}],
7
+ [Employees::EmployeeType{bg:red}],
8
+ [Employees::Department{bg:red}],
9
+ [Employees::Employee{bg:red}],
10
+ [Employees::HourlyPayroll]->[Employees::Payrole],
11
+ [Employees::SalariedPayroll]->[Employees::Payrole],
12
+ [Employees::DefinedContribution]->[Employees::RetirementPlan],
13
+ [Employees::DefinedBenefit]->[Employees::RetirementPlan],
14
+ [Employees::EmployeeType]->[Employees::DefinedContribution],
15
+ [Employees::EmployeeType]->[Employees::HourlyPayroll],
16
+ [Employees::EmployeeType]->[Employees::SalariedPayroll],
17
+ [Employees::EmployeeType]->[Employees::DefinedBenefit],
18
+ [Employees::Department]->[Employees::Employee],
19
+ [Employees::Employee]->[Employees::EmployeeType]
@@ -0,0 +1,53 @@
1
+ ,
2
+ [Employees::Company{bg:red}],
3
+ [Employees::CompanyMixin],
4
+ [Employees::HourlyPayroll{bg:red}],
5
+ [Employees::HourlyPayrollMixin],
6
+ [Employees::Payrole{bg:blue}],
7
+ [Employees::PayroleMixin],
8
+ [Employees::SalariedPayroll{bg:red}],
9
+ [Employees::SalariedPayrollMixin],
10
+ [Employees::DefinedContribution{bg:red}],
11
+ [Employees::DefinedContributionMixin],
12
+ [Employees::RetirementPlan{bg:blue}],
13
+ [Employees::RetirementPlanMixin],
14
+ [Employees::DefinedBenefit{bg:red}],
15
+ [Employees::DefinedBenefitMixin],
16
+ [Employees::EmployeeType{bg:red}],
17
+ [Employees::EmployeeTypeMixin],
18
+ [Employees::Department{bg:red}],
19
+ [Employees::DepartmentMixin],
20
+ [Employees::Employee{bg:red}],
21
+ [Employees::EmployeeMixin],
22
+ [Employees::Company]->[Employees::HourlyPayroll],
23
+ [Employees::HourlyPayrollMixin]^[Employees::Company],
24
+ [Employees::Company]->[Employees::SalariedPayroll],
25
+ [Employees::SalariedPayrollMixin]^[Employees::Company],
26
+ [Employees::Company]->[Employees::DefinedContribution],
27
+ [Employees::DefinedContributionMixin]^[Employees::Company],
28
+ [Employees::Company]->[Employees::DefinedBenefit],
29
+ [Employees::DefinedBenefitMixin]^[Employees::Company],
30
+ [Employees::Company]->[Employees::EmployeeType],
31
+ [Employees::EmployeeTypeMixin]^[Employees::Company],
32
+ [Employees::Company]->[Employees::Department],
33
+ [Employees::DepartmentMixin]^[Employees::Company],
34
+ [Employees::HourlyPayroll]->[Employees::Payrole],
35
+ [Employees::PayroleMixin]^[Employees::HourlyPayroll],
36
+ [Employees::SalariedPayroll]->[Employees::Payrole],
37
+ [Employees::PayroleMixin]^[Employees::SalariedPayroll],
38
+ [Employees::DefinedContribution]->[Employees::RetirementPlan],
39
+ [Employees::RetirementPlanMixin]^[Employees::DefinedContribution],
40
+ [Employees::DefinedBenefit]->[Employees::RetirementPlan],
41
+ [Employees::RetirementPlanMixin]^[Employees::DefinedBenefit],
42
+ [Employees::EmployeeType]->[Employees::DefinedContribution],
43
+ [Employees::DefinedContributionMixin]^[Employees::EmployeeType],
44
+ [Employees::EmployeeType]->[Employees::HourlyPayroll],
45
+ [Employees::HourlyPayrollMixin]^[Employees::EmployeeType],
46
+ [Employees::EmployeeType]->[Employees::SalariedPayroll],
47
+ [Employees::SalariedPayrollMixin]^[Employees::EmployeeType],
48
+ [Employees::EmployeeType]->[Employees::DefinedBenefit],
49
+ [Employees::DefinedBenefitMixin]^[Employees::EmployeeType],
50
+ [Employees::Department]->[Employees::Employee],
51
+ [Employees::EmployeeMixin]^[Employees::Department],
52
+ [Employees::Employee]->[Employees::EmployeeType],
53
+ [Employees::EmployeeTypeMixin]^[Employees::Employee]
@@ -0,0 +1,27 @@
1
+ ,
2
+ [Employees::Company{bg:red}],
3
+ [Employees::HourlyPayroll{bg:red}],
4
+ [Employees::Payrole{bg:blue}],
5
+ [Employees::SalariedPayroll{bg:red}],
6
+ [Employees::DefinedContribution{bg:red}],
7
+ [Employees::RetirementPlan{bg:blue}],
8
+ [Employees::DefinedBenefit{bg:red}],
9
+ [Employees::EmployeeType{bg:red}],
10
+ [Employees::Department{bg:red}],
11
+ [Employees::Employee{bg:red}],
12
+ [Employees::Company]->[Employees::HourlyPayroll],
13
+ [Employees::Company]->[Employees::SalariedPayroll],
14
+ [Employees::Company]->[Employees::DefinedContribution],
15
+ [Employees::Company]->[Employees::DefinedBenefit],
16
+ [Employees::Company]->[Employees::EmployeeType],
17
+ [Employees::Company]->[Employees::Department],
18
+ [Employees::HourlyPayroll]->[Employees::Payrole],
19
+ [Employees::SalariedPayroll]->[Employees::Payrole],
20
+ [Employees::DefinedContribution]->[Employees::RetirementPlan],
21
+ [Employees::DefinedBenefit]->[Employees::RetirementPlan],
22
+ [Employees::EmployeeType]->[Employees::DefinedContribution],
23
+ [Employees::EmployeeType]->[Employees::HourlyPayroll],
24
+ [Employees::EmployeeType]->[Employees::SalariedPayroll],
25
+ [Employees::EmployeeType]->[Employees::DefinedBenefit],
26
+ [Employees::Department]->[Employees::Employee],
27
+ [Employees::Employee]->[Employees::EmployeeType]
@@ -8,6 +8,8 @@ if $0 == __FILE__ then
8
8
  end
9
9
  end
10
10
 
11
+ $LOAD_PATH.unshift('../../lib/')
12
+
11
13
  require 'xamplr-generator'
12
14
 
13
15
  include XamplGenerator
@@ -8,6 +8,8 @@ if $0 == __FILE__ then
8
8
  end
9
9
  end
10
10
 
11
+ $LOAD_PATH.unshift('../../lib/')
12
+
11
13
  require 'xamplr-generator'
12
14
 
13
15
  include XamplGenerator
@@ -8,6 +8,8 @@ if $0 == __FILE__ then
8
8
  end
9
9
  end
10
10
 
11
+ $LOAD_PATH.unshift('../../lib/')
12
+
11
13
  require 'xamplr-generator'
12
14
 
13
15
  include XamplGenerator
@@ -8,6 +8,8 @@ if $0 == __FILE__ then
8
8
  end
9
9
  end
10
10
 
11
+ $LOAD_PATH.unshift('../../lib/')
12
+
11
13
  require 'xamplr-generator'
12
14
 
13
15
  include XamplGenerator
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env ruby
2
1
 
3
2
  module Xampl
4
3
 
@@ -1,7 +1,7 @@
1
- #!/usr/bin/env ruby
2
1
 
3
2
  module Xampl
4
3
 
4
+ require 'rubygems'
5
5
  require "yaml"
6
6
  require "logger"
7
7
 
@@ -83,19 +83,7 @@ module XamplGenerator
83
83
  return false
84
84
  end
85
85
 
86
- # def ignore_package(package)
87
- # puts "#{File.basename(__FILE__)}:#{__LINE__} pkg: [#{ package }], exclude: #{ @excluded_packages.inspect }, include: #{ @included_packages.inspect }"
88
- # r = ignore_package_work(package)
89
- # puts "#{File.basename(__FILE__)}:#{__LINE__} ignore? #{ r }"
90
- # r
91
- # end
92
-
93
- #def write_graph_ml(filename, excluded_packages=[ 'C2', 'NavRelationships', 'App' ], included_packages=nil, include_mixins=false)
94
86
  def write_graph_ml(filename, excluded_packages=[ ], included_packages=nil, include_mixins=true)
95
-
96
- #puts "#{File.basename(__FILE__)}:#{__LINE__} no graphml yet"
97
- #return
98
-
99
87
  filename = devise_filename(filename)
100
88
 
101
89
  @excluded_packages = Set.new(excluded_packages)
@@ -264,7 +264,7 @@ module Xampl
264
264
  next unless result
265
265
 
266
266
  mentioner = result['xampl_from']
267
- class_name = result['class']
267
+ class_name = result['mentioned_class']
268
268
  result_class = class_cache[class_name]
269
269
  unless result_class then
270
270
  class_name.split("::").each do | chunk |
@@ -316,6 +316,10 @@ module Xampl
316
316
  msg = note_errors("TC[[#{ @filename }]]:: trancommit error: %s\n") do
317
317
  @tc_db.tranabort
318
318
  end
319
+ puts "------------------------------------------------------------------------"
320
+ puts "TokyoCabinetPersister Error:: #{ msg }/#{ e }"
321
+ puts e.backtrace.join("\n")
322
+ puts "------------------------------------------------------------------------"
319
323
  raise "TokyoCabinetPersister Error:: #{ msg }/#{ e }"
320
324
  else
321
325
  note_errors("TC[[#{ @filename }]]:: trancommit error: %s\n") do
@@ -327,6 +331,12 @@ module Xampl
327
331
  # end
328
332
  end
329
333
  # puts " num records: #{ @tc_db.rnum() }"
334
+ # puts "#{ __FILE__ }:#{ __LINE__ } keys..."
335
+ # @tc_db.keys.each do | key |
336
+ # meta = @tc_db[key]
337
+ # meta['xampl'] = (meta['xampl'] || "no rep")[0..25]
338
+ # puts " key: [#{ key }] -- #{ meta.inspect }"
339
+ # end
330
340
  end
331
341
 
332
342
  def write(xampl)
@@ -349,7 +359,7 @@ module Xampl
349
359
  pk = @tc_db.genuid
350
360
  mention_hash = {
351
361
  'xampl_from' => place,
352
- 'class' => xampl.class.name,
362
+ 'mentioned_class' => xampl.class.name,
353
363
  'pid' => xampl.get_the_index,
354
364
  'xampl_to' => mention_place
355
365
  }
@@ -7,6 +7,7 @@ module XamplGenerator
7
7
  require "xamplr/xampl-hand-generated"
8
8
  require "xamplr/simpleTemplate/simple-template"
9
9
  require "xamplr/graphml-out.rb"
10
+ require "xamplr/yuml-out.rb"
10
11
 
11
12
  class Attribute
12
13
  attr_accessor :tag_name
@@ -307,6 +308,9 @@ module XamplGenerator
307
308
  graphml_out = GraphMLOut.new(@elements_map)
308
309
  graphml_out.write_graph_ml(filename)
309
310
 
311
+ yuml_out = YUMLOut.new(@elements_map)
312
+ yuml_out.write_yuml(filename)
313
+
310
314
  end
311
315
 
312
316
  def go(args, &eval_context)
@@ -0,0 +1,136 @@
1
+ require 'fileutils'
2
+ require 'set'
3
+
4
+ module XamplGenerator
5
+
6
+ class YUMLOut
7
+
8
+ def initialize(elements_map)
9
+ @elements_map = elements_map
10
+ end
11
+
12
+ def devise_filename(filename)
13
+ bn = File.basename(filename)
14
+ ext = File.extname(bn)
15
+ bn = bn[0..(bn.size - ext.size - 1)]
16
+ fn = "#{bn}.yuml"
17
+ end
18
+
19
+ def generate_class_nodes(element, include_mixins)
20
+ return if ignore_package(element.package)
21
+
22
+ class_name = "#{ element.package }::#{ element.class_name }"
23
+ mixin_name = "#{ element.package }::#{ element.class_name }"
24
+
25
+ @class_by_nstag[element.nstag] = element
26
+ @class_names_by_nstag[element.nstag] = class_name
27
+
28
+ if element.persisted then
29
+ write_entity_node(class_name, element.kind)
30
+ else
31
+ write_internal_node(class_name, element.kind)
32
+ end
33
+
34
+ if include_mixins then
35
+ write_mixin_node(class_name)
36
+ end
37
+ end
38
+
39
+ def generate_edges(element, include_mixins)
40
+ return if ignore_package(element.package)
41
+
42
+ element_name = @class_names_by_nstag[ element.nstag ]
43
+
44
+ element.child_element_child.each do | celement |
45
+ next if ignore_package(celement.package)
46
+
47
+ celement_name = @class_names_by_nstag[ celement.name ]
48
+ referenced_element = @class_by_nstag[ celement.name ]
49
+
50
+ if referenced_element.persisted then
51
+ write_entity_ref_edge(element_name, celement_name)
52
+ else
53
+ write_internal_ref_edge(element_name, celement_name)
54
+ end
55
+ if include_mixins then
56
+ write_mixin_ref_edge(element_name, celement_name)
57
+ end
58
+ end
59
+ end
60
+
61
+ def ignore_package(package)
62
+ return true if @excluded_packages.member?(package)
63
+ return false if @included_packages.nil?
64
+ return true unless @included_packages.member?(package)
65
+ return false
66
+ end
67
+
68
+ def write_yuml(base_filename, excluded_packages=[ ], included_packages=nil, include_mixins=false)
69
+ filename = devise_filename(base_filename)
70
+
71
+ @excluded_packages = Set.new(excluded_packages)
72
+ @included_packages = included_packages ? Set.new(included_packages) : nil
73
+
74
+ @class_names_by_nstag = {} # NOTE -- this is used by yuml!!
75
+ @class_by_nstag = {} # NOTE -- this is used by yuml!!
76
+
77
+ @initialise_output = true
78
+
79
+ File.open(filename, "w") do | out |
80
+ @out = out
81
+
82
+ @elements_map.each_value do |elements|
83
+ elements.element_child.each do |element|
84
+ generate_class_nodes(element, include_mixins)
85
+ end
86
+ end
87
+
88
+ @elements_map.each_value do |elements|
89
+ elements.element_child.each do |element|
90
+ generate_edges(element, include_mixins)
91
+ end
92
+ end
93
+ end
94
+
95
+ return nil
96
+ end
97
+
98
+ def new_statement
99
+ if @initialise_output then
100
+ @initialise_output = false
101
+ else
102
+ @out << ",\n"
103
+ end
104
+ end
105
+
106
+ def write_entity_node(class_name, kind)
107
+ new_statement
108
+ @out << "[#{ class_name }{bg:red}]"
109
+ end
110
+
111
+ def write_internal_node(class_name, kind)
112
+ new_statement
113
+ @out << "[#{ class_name }{bg:blue}]"
114
+ end
115
+
116
+ def write_mixin_node(class_name)
117
+ new_statement
118
+ @out << "[#{ class_name }Mixin]"
119
+ end
120
+
121
+ def write_entity_ref_edge(class_node, external_node)
122
+ new_statement
123
+ @out << "[#{ class_node }]->[#{ external_node }]"
124
+ end
125
+
126
+ def write_internal_ref_edge(class_node, internal_node)
127
+ new_statement
128
+ @out << "[#{ class_node }]->[#{ internal_node }]"
129
+ end
130
+
131
+ def write_mixin_ref_edge(class_node, mixin_node)
132
+ new_statement
133
+ @out << "[#{ mixin_node }Mixin]^[#{ class_node }]"
134
+ end
135
+ end
136
+ end