codemodels 0.2.2-java → 0.2.3-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 }