codemodels 0.2.2-java → 0.2.3-java

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.
@@ -2,6 +2,14 @@ require 'codemodels/monkey_patching'
2
2
 
3
3
  module CodeModels
4
4
 
5
+ class Parser
6
+
7
+ def parse_file(path)
8
+ parse_code(IO.read(path))
9
+ end
10
+
11
+ end
12
+
5
13
  class ParsingError < Exception
6
14
  attr_reader :node
7
15
  attr_reader :line
@@ -26,159 +34,4 @@ class UnknownNodeType < ParsingError
26
34
 
27
35
  end
28
36
 
29
- module ParserWrapper
30
-
31
- @@verbose = false
32
-
33
- JavaCollection = ::Java::JavaClass.for_name("java.util.Collection")
34
-
35
- def adapter(model_class,ref)
36
- if adapter_specific_class(model_class,ref)
37
- adapter_specific_class(model_class,ref)
38
- else
39
- if model_class.superclass!=Object
40
- adapter(model_class.superclass,ref)
41
- else
42
- nil
43
- end
44
- end
45
- end
46
-
47
- def reference_to_method(model_class,ref)
48
- s = ref.name
49
- #s = 'value' if s=='body'
50
- adapted = adapter(model_class,ref)
51
- s = adapted if adapted
52
- s.to_sym
53
- end
54
-
55
- def attribute_to_method(model_class,att)
56
- s = att.name
57
- adapted = adapter(model_class,att)
58
- s = adapted if adapted
59
- s.to_sym
60
- end
61
-
62
- def assign_ref_to_model(model,ref,value)
63
- return unless value==nil # we do not need to assign a nil...
64
- if ref.many
65
- adder_method = :"add#{ref.name.capitalize}"
66
- value.each {|el| model.send(adder_method,node_to_model(el))}
67
- else
68
- setter_method = :"#{ref.name}="
69
- raise "Trying to assign an array to a single property. Class #{model.class}, property #{ref.name}" if value.is_a?(::Array)
70
- model.send(setter_method,node_to_model(value))
71
- end
72
- rescue Object => e
73
- puts "Problem while assigning ref #{ref.name} (many? #{ref.many}) to #{model.class}. Value: #{value.class}"
74
- puts "\t<<#{e}>>"
75
- raise e
76
- end
77
-
78
- def assign_att_to_model(model,att,value)
79
- if att.many
80
- adder_method = :"add#{att.name.capitalize}"
81
- value.each {|el| model.send(adder_method,el)}
82
- else
83
- setter_method = :"#{att.name}="
84
- raise "Trying to assign an array to a single property. Class #{model.class}, property #{att.name}" if value.is_a?(::Array)
85
- model.send(setter_method,value)
86
- end
87
- end
88
-
89
- def populate_attr(node,att,model)
90
- value = get_feature_value(node,att)
91
- model.send(:"#{att.name}=",value) if value!=nil
92
- rescue Object => e
93
- puts "Problem while populating attribute #{att.name} of #{model} from #{node}. Value: #{value}"
94
- raise e
95
- end
96
-
97
- def populate_ref(node,ref,model)
98
- log("populate ref #{ref.name}, node: #{node.class}, model: #{model.class}")
99
- value = get_feature_value(node,ref)
100
- log("\tvalue=#{value.class}")
101
- if value!=nil
102
- if value==node
103
- puts "avoiding loop... #{ref.name}, class #{node.class}"
104
- return
105
- end
106
- if JavaCollection.assignable_from?(value.java_class)
107
- log("\tvalue is a collection")
108
- capitalized_name = ref.name.proper_capitalize
109
- value.each do |el|
110
- unless el.respond_to?(:parent)
111
- class << el
112
- attr_accessor :parent
113
- end
114
- end
115
- el.parent = node
116
- model.send(:"add#{capitalized_name}",node_to_model(el))
117
- end
118
- else
119
- log("\tvalue is not a collection")
120
- unless value.respond_to?(:parent)
121
- value.class.__persistent__ = true
122
- class << value
123
- attr_accessor :parent
124
- end
125
- end
126
- value.parent = node
127
- model.send(:"#{ref.name}=",node_to_model(value))
128
- end
129
- end
130
- end
131
-
132
- def log(msg)
133
- puts msg if @@verbose
134
- end
135
-
136
- def node_to_model(node)
137
- log("node_to_model #{node.class}")
138
- metaclass = get_corresponding_metaclass(node)
139
- instance = metaclass.new
140
- metaclass.ecore.eAllAttributes.each do |attr|
141
- populate_attr(node,attr,instance)
142
- end
143
- metaclass.ecore.eAllReferences.each do |ref|
144
- populate_ref(node,ref,instance)
145
- end
146
- instance
147
- end
148
-
149
- def transform_enum_values(value)
150
- if value.respond_to?(:java_class) && value.java_class.enum?
151
- value.name
152
- else
153
- value
154
- end
155
- end
156
-
157
- def get_feature_value_through_getter(node,feat_name)
158
- capitalized_name = feat_name.proper_capitalize
159
- methods = [:"get#{capitalized_name}",:"is#{capitalized_name}"]
160
-
161
- methods.each do |m|
162
- if node.respond_to?(m)
163
- begin
164
- return transform_enum_values(node.send(m))
165
- rescue Object => e
166
- raise "Problem invoking #{m} on #{node.class}: #{e}"
167
- end
168
- end
169
- end
170
- raise "how should I get this... #{feat_name} on #{node.class}. It does not respond to #{methods}"
171
- end
172
-
173
- def get_feature_value(node,feat)
174
- adapter = adapter(node.class,feat)
175
- if adapter
176
- adapter[:adapter].call(node)
177
- else
178
- get_feature_value_through_getter(node,feat.name)
179
- end
180
- end
181
-
182
- end
183
-
184
37
  end
@@ -12,17 +12,12 @@ class RGen::MetamodelBuilder::MMBase
12
12
  values.each do |k,v|
13
13
  attribute = self.ecore.eAllAttributes.find {|x| x.name==k.to_s}
14
14
  reference = self.ecore.eAllReferences.find {|x| x.name==k.to_s}
15
- raise EMF::UnexistingFeature.new(k.to_s) unless (attribute or reference)
15
+ raise "UnexistingFeature #{k}" unless (attribute or reference)
16
16
  setter = (k.to_s+'=').to_sym
17
17
  instance.send setter, v
18
18
  end
19
19
  else
20
- has_dynamic = false
21
- self.ecore.eAllAttributes.each {|a| has_dynamic|=a.name=='dynamic'}
22
- d = 0
23
- d = 1 if has_dynamic
24
-
25
- raise EMF::SingleAttributeRequired.new(self.ecore.name,self.ecore.eAllAttributes) if self.ecore.eAllAttributes.count!=1+d
20
+ raise "SingleAttributeRequired" if self.ecore.eAllAttributes.count!=1
26
21
  attribute = self.ecore.eAllAttributes[0]
27
22
  set_attr(instance,attribute,values)
28
23
  end
@@ -45,12 +40,9 @@ class RGen::MetamodelBuilder::MMBase
45
40
  return false unless self.class==other.class
46
41
  self.class.ecore.eAllAttributes.each do |attrib|
47
42
  raise "Attrib <nil> for class #{self.class.ecore.name}" unless attrib
48
- if attrib.name != 'dynamic' # I have to understand this...
49
- self_value = self.get(attrib)
50
- other_value = other.get(attrib)
51
- #puts "returning false on #{attrib.name}" unless self_value.eql?(other_value)
52
- return false unless self_value == other_value
53
- end
43
+ self_value = self.get(attrib)
44
+ other_value = other.get(attrib)
45
+ return false unless self_value == other_value
54
46
  end
55
47
  true
56
48
  end
@@ -95,92 +87,47 @@ class RGen::MetamodelBuilder::MMBase
95
87
  send getter
96
88
  end
97
89
 
98
- def all_children
99
- arr = []
90
+ def features_by_name(name)
91
+ features = []
100
92
  ecore = self.class.ecore
101
- ecore.eAllReferences.select {|r| r.containment}.each do |ref|
102
- res = self.send(ref.name.to_sym)
103
- if ref.many
104
- d = arr.count
105
- res.each do |el|
106
- arr << el unless res==nil
107
- end
108
- elsif res!=nil
109
- d = arr.count
110
- arr << res
111
- end
112
- end
113
- arr
114
- end
115
-
116
- def all_children_deep
117
- arr = []
118
- all_children.each do |c|
119
- arr << c
120
- c.all_children_deep.each do |cc|
121
- arr << cc
122
- end
93
+ ecore.eAllAttributes.select {|a| a.name==name}.each do |a|
94
+ features << a
123
95
  end
124
- arr
125
- end
126
-
127
- def traverse(&op)
128
- op.call(self)
129
- all_children_deep.each do |c|
130
- op.call(c)
96
+ ecore.eAllReferences.select {|r| r.name==name}.each do |r|
97
+ features << r
131
98
  end
99
+ features
132
100
  end
133
101
 
134
- def collect_values_with_count
135
- values = Hash.new {|h,k| h[k]=0}
136
- self.class.ecore.eAllAttributes.each do |a|
137
- v = self.send(:"#{a.name}")
138
- if v!=nil
139
- if a.many
140
- v.each {|el| values[el]+=1}
141
- else
142
- values[v]+=1
143
- end
144
- end
145
- end
146
- values
147
- end
148
-
149
- def collect_values_with_count_subtree
150
- values = collect_values_with_count
151
- all_children_deep.each do |c|
152
- c.collect_values_with_count.each do |k,v|
153
- values[k]+=v
154
- end
155
- end
156
- values
157
- end
102
+ end
158
103
 
159
- def all_children_of_type(type)
160
- all_children.select {|c| c and c.is_a?(type)}
104
+ module FixingCollidingFeatureAddOn
105
+ def has_attr(role, target_class=nil, raw_props={}, &block)
106
+ raise "Role already used #{role}" if self.ecore.eAllAttributes.find {|a| a.name==role.to_s}
107
+ raise "Role already used #{role}" if self.ecore.eAllReferences.find {|r| r.name==role.to_s}
108
+ super(role,target_class,raw_props,block)
161
109
  end
162
-
163
- def all_children_deep_of_type(type)
164
- all_children_deep.select {|c| c and c.is_a?(type)}
110
+ def has_many_attr(role, target_class=nil, raw_props={}, &block)
111
+ raise "Role already used #{role}" if self.ecore.eAllAttributes.find {|a| a.name==role.to_s}
112
+ raise "Role already used #{role}" if self.ecore.eAllReferences.find {|r| r.name==role.to_s}
113
+ super(role,target_class,raw_props,block)
165
114
  end
166
-
167
- def only_child_of_type(type)
168
- selected = all_children_of_type(type)
169
- raise "Exactly one child of type #{type} expected, #{selected.count} found on #{self}" unless selected.count==1
170
- selected[0]
115
+ def contains_many_uni(role, target_class=nil, raw_props={}, &block)
116
+ raise "Role already used #{role}" if self.ecore.eAllAttributes.find {|a| a.name==role.to_s}
117
+ raise "Role already used #{role}" if self.ecore.eAllReferences.find {|r| r.name==role.to_s}
118
+ super(role,target_class,raw_props,block)
171
119
  end
172
-
173
- def only_child_deep_of_type(type)
174
- selected = all_children_deep_of_type(type)
175
- raise "Exactly one child of type #{type} expected, #{selected.count} found on #{self}" unless selected.count==1
176
- selected[0]
120
+ def contains_one_uni(role, target_class=nil, raw_props={}, &block)
121
+ raise "Role already used #{role}" if self.ecore.eAllAttributes.find {|a| a.name==role.to_s}
122
+ raise "Role already used #{role}" if self.ecore.eAllReferences.find {|r| r.name==role.to_s}
123
+ super(role,target_class,raw_props,block)
177
124
  end
178
-
179
125
  end
180
126
 
181
127
  class << self
182
128
  include ClassAddOn
183
129
  end
184
130
 
131
+ include FixingCollidingFeatureAddOn
185
132
  include SingletonAddOn
186
133
  end
@@ -10,38 +10,16 @@ module Serialization
10
10
 
11
11
  module SerializationFunctionalities
12
12
 
13
- # It could be a simple hash with a block passed to the
14
- # constructor...
15
- class SerializationMemory
16
-
17
- def initialize
18
- @next_id = 1
19
- @id_map = {}
20
- end
21
-
22
- def id(rgen_object)
23
- unless @id_map[rgen_object]
24
- @id_map[rgen_object] = @next_id
25
- @next_id += 1
26
- end
27
- @id_map[rgen_object]
28
- end
29
-
30
- end
13
+ def to_json(params={})
14
+ serialization_memory = params.fetch(:memory,SerializationMemory.new)
15
+ adapters = params.fetch(:adapters,{})
16
+ with_source_info = params.fetch(:source_info,true)
31
17
 
32
- def to_json(serialization_memory=SerializationMemory.new,adapters={},with_source_info=true)
33
18
  e_object = self
34
- map = { 'type' => qname, 'id' => serialization_memory.id(e_object) }
19
+ map = { 'type' => type, 'id' => serialization_memory.id(e_object) }
35
20
  if with_source_info
36
- if self.respond_to?(:source) && self.source
37
- source_map = {}
38
- if self.source.begin_pos
39
- source_map['begin_pos'] = {'line'=> self.source.begin_pos.line, 'column'=>self.source.begin_pos.column}
40
- end
41
- if self.source.end_pos
42
- source_map['end_pos'] = {'line'=> self.source.end_pos.line, 'column'=>self.source.end_pos.column}
43
- end
44
- map['source'] = source_map
21
+ if self.respond_to?(:source) && self.source
22
+ map['source'] = source_info_to_json(self.source)
45
23
  end
46
24
  end
47
25
  e_class = e_object.class.ecore
@@ -51,21 +29,32 @@ module SerializationFunctionalities
51
29
  e_class.eAllReferences.each do |r|
52
30
  id = jsonize_ref_value(map,r,adapters,serialization_memory)
53
31
  end
54
- if adapters.has_key? qname
55
- adapters[qname].adapt(self,map)
32
+ if adapters.has_key? type
33
+ adapters[type].adapt(self,map)
56
34
  end
57
35
  map
58
36
  end
59
37
 
60
38
  private
61
39
 
62
- def qname
40
+ def source_info_to_json(source_info)
41
+ source_map = {}
42
+ if self.source.begin_pos
43
+ source_map['begin_pos'] = {'line'=> self.source.begin_pos.line, 'column'=>self.source.begin_pos.column}
44
+ end
45
+ if self.source.end_pos
46
+ source_map['end_pos'] = {'line'=> self.source.end_pos.line, 'column'=>self.source.end_pos.column}
47
+ end
48
+ source_map
49
+ end
50
+
51
+ def type
63
52
  self.class.to_s
64
53
  end
65
54
 
66
55
  def jsonize_attr_value(map,e_attr)
67
56
  value = self.send(e_attr.name.to_sym)
68
- if e_attr.upperBound==1
57
+ unless e_attr.many
69
58
  map["attr_#{e_attr.name}"] = value
70
59
  else
71
60
  l = []
@@ -82,7 +71,7 @@ module SerializationFunctionalities
82
71
  propname = "relcont_#{e_ref.name}" if e_ref.containment
83
72
  propname = "relnoncont_#{e_ref.name}" if not e_ref.containment
84
73
 
85
- if e_ref.upperBound==1
74
+ unless e_ref.many
86
75
  map[propname] = jsonize_ref_single_el(value,e_ref.containment,adapters,serialization_memory)
87
76
  else
88
77
  l = []
@@ -95,23 +84,38 @@ module SerializationFunctionalities
95
84
 
96
85
  def jsonize_ref_single_el(single_value,containment,adapters,serialization_memory)
97
86
  if containment
98
- single_value.to_json(serialization_memory,adapters)
87
+ single_value.to_json(memory:serialization_memory,adapters:adapters)
99
88
  else
100
89
  serialization_memory.id(single_value)
101
90
  end
102
91
  end
103
92
 
104
- end
93
+ # It could be a simple hash with a block passed to the
94
+ # constructor...
95
+ class SerializationMemory
96
+
97
+ def initialize
98
+ @next_id = 1
99
+ @id_map = {}
100
+ end
101
+
102
+ def id(rgen_object)
103
+ unless @id_map[rgen_object]
104
+ @id_map[rgen_object] = @next_id
105
+ @next_id += 1
106
+ end
107
+ @id_map[rgen_object]
108
+ end
109
+
110
+ end
105
111
 
106
- class ::RGen::MetamodelBuilder::MMBase
107
- include SerializationFunctionalities
108
112
  end
109
113
 
110
114
  def self.load_file(path,max_nesting=500)
111
115
  JSON.parse(File.read(path),{max_nesting: max_nesting})
112
116
  end
113
117
 
114
- def self.save_model(model,model_path, max_nesting=500)
118
+ def self.save_model(model,model_path,max_nesting=500)
115
119
  dir = File.dirname(model_path)
116
120
  FileUtils.mkdir_p(dir)
117
121
 
@@ -125,10 +129,10 @@ def self.rgenobject_to_model(root,adapters={})
125
129
  external_elements = []
126
130
 
127
131
  sm = SerializationFunctionalities::SerializationMemory.new
128
- model['root'] = root.to_json(sm,adapters)
132
+ model['root'] = root.to_json(memory:sm,adapters:adapters)
129
133
  model['external_elements'] = []
130
134
  external_elements.each do |ee|
131
- model['external_elements'] << ee.to_json(sm,adapters)
135
+ model['external_elements'] << ee.to_json(memory:sm,adapters:adapters)
132
136
  end
133
137
  model
134
138
  end
@@ -139,4 +143,5 @@ def self.save_as_model(root,model_path)
139
143
  end
140
144
 
141
145
  end # module
146
+
142
147
  end # module
@@ -0,0 +1,192 @@
1
+ require 'rgen/metamodel_builder'
2
+ require 'codemodels/language'
3
+
4
+ module CodeModels
5
+
6
+ class AbstractArtifact
7
+
8
+ def point_to_absolute(point)
9
+ offset = absolute_start
10
+ p = SourcePoint.new
11
+ p.line = point.line + offset.line - 1
12
+ p.column = point.column
13
+ p.column += offset.column-1 if point.line==1
14
+ p
15
+ end
16
+
17
+ def position_to_absolute(position)
18
+ pos = SourcePosition.new
19
+ pos.begin_point = point_to_absolute(position.begin_point)
20
+ pos.end_point = point_to_absolute(position.end_point)
21
+ pos
22
+ end
23
+
24
+ end
25
+
26
+ class EmbeddedArtifact < AbstractArtifact
27
+ attr_accessor :host_artifact
28
+ attr_accessor :position_in_host
29
+
30
+ def absolute_start
31
+ p = host_artifact.absolute_start
32
+ p.line += position_in_host.begin_point.line-1
33
+ if position_in_host.begin_point.line==1
34
+ # if I am on the first line of my "host", its column
35
+ # matters because there are not newlines to reset the column
36
+ # counter
37
+ p.column += position_in_host.begin_point.column-1
38
+ else
39
+ p.column = position_in_host.begin_point.column
40
+ end
41
+ p
42
+ end
43
+
44
+ end
45
+
46
+ class FileArtifact < AbstractArtifact
47
+ attr_accessor :filename
48
+
49
+ def absolute_start
50
+ sp = SourcePoint.new
51
+ sp.line = 1
52
+ sp.column = 1
53
+ sp
54
+ end
55
+ end
56
+
57
+ class SourcePoint
58
+ attr_accessor :line, :column
59
+
60
+ def initialize(line=nil,column=nil)
61
+ @line = line
62
+ @column = column
63
+ end
64
+
65
+ def eql?(other)
66
+ other.line==line && other.column==column
67
+ end
68
+
69
+ def ==(other)
70
+ self.eql?(other)
71
+ end
72
+ end
73
+
74
+ class SourcePosition
75
+ attr_accessor :begin_point, :end_point
76
+
77
+ def initialize(begin_point=nil,end_point=nil)
78
+ @begin_point = begin_point
79
+ @end_point = end_point
80
+ end
81
+
82
+ def begin_line=(line)
83
+ @begin_point=SourcePoint.new unless @begin_point
84
+ @begin_point.line = line
85
+ end
86
+
87
+ def begin_column=(column)
88
+ @begin_point=SourcePoint.new unless @begin_point
89
+ @begin_point.column = column
90
+ end
91
+
92
+ def eql?(other)
93
+ other.begin_point==begin_point && other.end_point==end_point
94
+ end
95
+
96
+ def ==(other)
97
+ self.eql?(other)
98
+ end
99
+ end
100
+
101
+ class SourceInfo
102
+ attr_accessor :artifact
103
+ attr_accessor :position
104
+
105
+ def to_code
106
+ raise "Unimplemented"
107
+ end
108
+
109
+ def begin_point=(data)
110
+ point = data_to_point(data)
111
+ @position = SourcePosition.new unless @position
112
+ @position.begin_point = point
113
+ end
114
+
115
+ def end_point=(data)
116
+ point = data_to_point(data)
117
+ @position = SourcePosition.new unless @position
118
+ @position.end_point = point
119
+ end
120
+
121
+ def begin_line
122
+ position.begin_point.line
123
+ end
124
+
125
+ def end_line
126
+ position.end_point.line
127
+ end
128
+
129
+ private
130
+
131
+ def data_to_point(data)
132
+ if data.is_a? Hash
133
+ point = SourcePoint.new
134
+ point.line = data[:line]
135
+ point.column = data[:column]
136
+ elsif data.is_a? SourcePoint
137
+ point = data
138
+ else
139
+ raise "Expected Hash or SourcePoint"
140
+ end
141
+ point
142
+ end
143
+
144
+ end
145
+
146
+ # This extension give all the information about the source
147
+ # from which the node was derived
148
+ module SourceInfoExtensions
149
+ attr_accessor :language
150
+ attr_accessor :source
151
+
152
+ def set_start_point(data)
153
+ @source = SourceInfo.new unless @source
154
+ @source.set_start_point(data)
155
+ end
156
+
157
+ def set_end_point(data)
158
+ @source = SourceInfo.new unless @source
159
+ @source.set_end_point(data)
160
+ end
161
+ end
162
+
163
+ # Inside an host language snippet of other languages can be hosted
164
+ # For example Java code could contain in a string literal a sql statement
165
+ # or an Html file can contain CSS or Javascript code.
166
+ # In those cases an AST is inserted inside the AST of the host language.
167
+ module ForeignAstExtensions
168
+
169
+ attr_accessor :foreign_container
170
+
171
+ def addForeign_asts(foreign_ast)
172
+ foreign_asts << foreign_ast
173
+ foreign_ast.foreign_container = self
174
+ end
175
+
176
+ def foreign_asts
177
+ @foreign_asts=[] unless @foreign_asts
178
+ @foreign_asts
179
+ end
180
+ end
181
+
182
+ module HostPositionExtensions
183
+
184
+ def absolute_position
185
+ artifact = source.artifact
186
+ artifact.absolute_position(source.position)
187
+ end
188
+
189
+ end
190
+
191
+
192
+ end
@@ -1,3 +1,3 @@
1
1
  module CodeModels
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.3"
3
3
  end
data/lib/codemodels.rb CHANGED
@@ -1,5 +1,3 @@
1
1
  curr_dir = File.dirname(__FILE__)
2
2
 
3
- Dir[curr_dir+"/codemodels/*.rb"].each do |rb|
4
- require rb
5
- end
3
+ Dir["#{curr_dir}/codemodels/*.rb"].each { |rb| require rb }