rtext 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 51b8fbadb70e46e456b58b2910f56862f5021d5fc1e0d22671aafb31236bfb85
4
- data.tar.gz: f6df8e5a17c1dbc839f0ca751b4ae99671e4f9b21242389ba7c3e8190ae391ee
2
+ SHA1:
3
+ metadata.gz: 747355cc5b17bf91ec5a902b0be20b9b13639baf
4
+ data.tar.gz: 808497bcef84bfcb8e5a5f5d50b4b6cda109337a
5
5
  SHA512:
6
- metadata.gz: 93e358c961fedc1b3497229699f14cb5ecca26c9b4f6eb4c73609321dc2383fc6089b2b4db1f4781889a3be6701d439e9a37ca0f4d887ff75eb9eb37cd4ccd31
7
- data.tar.gz: 36e6b72e7d2b7d78051a872cfcd173180b2831e570b3f7dc42a25b4966589edbf859f00809b9470518d5f3d85fadb0c48af5193238dbcba57f8b999afd370922
6
+ metadata.gz: 987cf234234bb2284fe9d7c030be5c7837667cf051701985c2634f0cbee14d77c0abe4cad9eb962dd66312c9d35b1020f0578931cccc8c9f0de4a2fa3ea08295
7
+ data.tar.gz: 5425d8b7189dd74db31d97df3123cee9d27fb59716d73913b2f3d993f79f354f561d26d1f1a6a175f8ab7cc4a813977428a602898ba5748a71d71d58700da630
data/CHANGELOG CHANGED
@@ -99,4 +99,10 @@
99
99
 
100
100
  =0.9.1
101
101
 
102
- * Fixed backward compatibility issues
102
+ * Fixed backward compatibility issues
103
+
104
+ =0.9.2
105
+
106
+ * Fixed frontend connector
107
+ * Fixed frontend tests
108
+ * Automatic conversion of integer and float values to string
data/RText_Protocol CHANGED
@@ -501,7 +501,7 @@ the parent commands wrapped around it. Any sibling commands can be omitted as we
501
501
  any lines containing closing braces and brackets. The order of lines is the same as in the
502
502
  RText file.
503
503
 
504
- Here is an example. Consider the following RText file with the cursor in the line of "Command3"
504
+ Here is an example. Consider the following RText file with the cursor in the line of "Command5"
505
505
  at the time when the auto completion command is issued.
506
506
 
507
507
  Command1 {
data/Rakefile CHANGED
@@ -1,36 +1,22 @@
1
1
  require 'rubygems/package_task'
2
+
3
+ require 'rake'
2
4
  require 'rdoc/task'
3
5
 
4
- DocFiles = [
5
- "README.rdoc", "CHANGELOG", "MIT-LICENSE",
6
- "RText_Users_Guide",
7
- "RText_Protocol"]
8
-
9
- RTextGemSpec = Gem::Specification.new do |s|
10
- s.name = %q{rtext}
11
- s.version = "0.9.1"
12
- s.date = Time.now.strftime("%Y-%m-%d")
13
- s.summary = %q{Ruby Textual Modelling}
14
- s.email = %q{martin dot thiede at gmx de}
15
- s.homepage = %q{http://ruby-gen.org}
16
- s.description = %q{RText can be used to derive textual languages from an RGen metamodel with very little effort.}
17
- s.authors = ["Martin Thiede"]
18
- s.add_dependency('rgen', '>= 0.8.2')
19
- gemfiles = Rake::FileList.new
20
- gemfiles.include("{lib,test}/**/*")
21
- gemfiles.include(DocFiles)
22
- gemfiles.include("Rakefile")
23
- gemfiles.exclude(/\b\.bak\b/)
24
- s.files = gemfiles
25
- s.rdoc_options = ["--main", "README.rdoc", "-x", "test"]
26
- s.extra_rdoc_files = DocFiles
27
- end
6
+ RTextGemSpec = eval(File.read('rtext.gemspec'))
7
+
8
+ gemfiles = Rake::FileList.new
9
+ gemfiles.include('{lib,test}/**/*')
10
+ gemfiles.include(DocFiles)
11
+ gemfiles.include('Rakefile')
12
+ gemfiles.exclude(/\b\.bak\b/)
13
+ RTextGemSpec.files = gemfiles
28
14
 
29
15
  RDoc::Task.new do |rd|
30
- rd.main = "README.rdoc"
31
- rd.rdoc_files.include(DocFiles)
32
- rd.rdoc_files.include("lib/**/*.rb")
33
- rd.rdoc_dir = "doc"
16
+ rd.main = 'README.rdoc'
17
+ rd.rdoc_files.include(RTextGemSpec.extra_rdoc_files)
18
+ rd.rdoc_files.include('lib/**/*.rb')
19
+ rd.rdoc_dir = 'doc'
34
20
  end
35
21
 
36
22
  RTextPackageTask = Gem::PackageTask.new(RTextGemSpec) do |p|
@@ -38,9 +24,16 @@ RTextPackageTask = Gem::PackageTask.new(RTextGemSpec) do |p|
38
24
  end
39
25
 
40
26
  task :prepare_package_rdoc => :rdoc do
41
- RTextPackageTask.package_files.include("doc/**/*")
27
+ RTextPackageTask.package_files.include('doc/**/*')
42
28
  end
43
29
 
44
30
  task :release => [:prepare_package_rdoc, :package]
45
31
 
46
32
  task :clobber => [:clobber_rdoc, :clobber_package]
33
+
34
+ require 'rake/testtask'
35
+
36
+ ::Rake::TestTask.new(:test) do |t|
37
+ t.test_files = ['test/rtext_test.rb']
38
+ t.warning = false
39
+ end
@@ -21,15 +21,21 @@ def initialize(config, options={})
21
21
  @outfile_provider = options[:outfile_provider]
22
22
  @keep_outfile = options[:keep_outfile]
23
23
  @connection_timeout = options[:connection_timeout] || 10
24
+ @process_id = nil
24
25
  end
25
26
 
26
27
  def execute_command(obj, options={})
27
- timeout = options[:timeout] || 5
28
+ timeout = options[:timeout] || 10
28
29
  @busy = false if @busy_start_time && (Time.now > @busy_start_time + timeout)
29
30
  if @busy
30
31
  do_work
31
- :backend_busy
32
- elsif connected?
32
+ return :backend_busy
33
+ end
34
+ unless connected?
35
+ connect unless connecting?
36
+ do_work
37
+ end
38
+ if connected?
33
39
  obj["invocation_id"] = @invocation_id
34
40
  obj["type"] = "request"
35
41
  @socket.send(serialize_message(obj), 0)
@@ -66,9 +72,7 @@ def execute_command(obj, options={})
66
72
  result
67
73
  end
68
74
  else
69
- connect unless connecting?
70
- do_work
71
- :connecting
75
+ :connecting
72
76
  end
73
77
  end
74
78
 
@@ -87,23 +91,68 @@ def stop
87
91
  sleep(0.1)
88
92
  end
89
93
  end
94
+ ensure_process_cleanup(@process_id, @keep_outfile ? nil : @out_file, 10)
95
+ @process_id = nil
90
96
  end
91
97
 
92
98
  private
93
99
 
100
+ def wait_for_process_to_exit(process_id, timeout)
101
+ with_timeout timeout do
102
+ begin
103
+ waitpid(process_id, Process::WNOHANG)
104
+ process_id = nil
105
+ true
106
+ rescue Errno::ECHILD => _
107
+ false
108
+ end
109
+ end
110
+ end
111
+
112
+ def ensure_process_cleanup(process_id, out_file, timeout)
113
+ Thread.new do
114
+ begin
115
+ unless process_id.nil?
116
+ process_id = nil if wait_for_process_to_exit(process_id, timeout)
117
+ end
118
+ ensure
119
+ unless process_id.nil?
120
+ begin
121
+ Process.kill('QUIT', process_id)
122
+ rescue Errno::ESRCH => _
123
+ end
124
+ end
125
+ File.unlink(out_file) if !out_file.nil? && File.exist?(out_file)
126
+ end
127
+ end
128
+ end
129
+
130
+ def with_timeout(timeout, sleep_time = 0.1, &block)
131
+ started = Time.now
132
+ while true do
133
+ return true if block.call
134
+ if Time.now > started + timeout
135
+ return false
136
+ end
137
+ sleep(sleep_time)
138
+ end
139
+ end
140
+
141
+
94
142
  def connected?
95
- @state == :connected && backend_running?
143
+ !@process_id.nil? && @state == :read_from_socket && backend_running?
96
144
  end
97
145
 
98
146
  def connecting?
99
- @state == :connecting
147
+ !@process_id.nil? && (@state == :wait_for_file || @state == :wait_for_port)
100
148
  end
101
149
 
102
150
  def backend_running?
103
151
  if @process_id
104
152
  begin
105
- return true unless waitpid(@process_id, Process::WNOHANG)
106
- rescue Errno::ECHILD
153
+ waitpid(@process_id, Process::WNOHANG)
154
+ return true
155
+ rescue Errno::ECHILD => _
107
156
  end
108
157
  end
109
158
  false
@@ -121,7 +170,7 @@ def tempfile_name
121
170
  end
122
171
 
123
172
  def connect
124
- @state = :connecting
173
+ return if connected?
125
174
  @connect_start_time = Time.now
126
175
 
127
176
  @logger.info @config.command if @logger
@@ -131,56 +180,75 @@ def connect
131
180
  else
132
181
  @out_file = tempfile_name
133
182
  end
134
- File.unlink(@out_file) if File.exist?(@out_file)
135
183
 
136
- Dir.chdir(File.dirname(@config.file)) do
137
- @process_id = spawn(@config.command.strip + " > #{@out_file} 2>&1")
184
+ if @process_id.nil?
185
+ File.unlink(@out_file) if File.exist?(@out_file)
186
+ Dir.chdir(File.dirname(@config.file)) do
187
+ @process_id = spawn(@config.command.strip + " > #{@out_file} 2>&1")
188
+ @state = :wait_for_file
189
+ end
138
190
  end
139
- @work_state = :wait_for_file
140
191
  end
141
192
 
142
193
  def do_work
143
- case @work_state
144
- when :wait_for_file
145
- if File.exist?(@out_file)
146
- @work_state = :wait_for_port
147
- end
148
- if Time.now > @connect_start_time + @connection_timeout
149
- cleanup
150
- @connection_listener.call(:timeout) if @connection_listener
151
- @work_state = :done
152
- @state = :off
153
- @logger.warn "process didn't startup (connection timeout)" if @logger
194
+ if @process_id.nil?
195
+ @state = :off
196
+ return false
197
+ end
198
+ if @state == :wait_for_port && !File.exist?(@out_file)
199
+ @state = :wait_for_file
200
+ end
201
+ if @state == :wait_for_file && File.exist?(@out_file)
202
+ @state = :wait_for_port
203
+ end
204
+ if @state == :wait_for_file
205
+ while true
206
+ if Time.now > @connect_start_time + @connection_timeout
207
+ cleanup
208
+ @connection_listener.call(:timeout) if @connection_listener
209
+ @state = :off
210
+ @logger.warn "process didn't startup (connection timeout)" if @logger
211
+ return false
212
+ end
213
+ sleep(0.1)
214
+ if File.exist?(@out_file)
215
+ @state = :wait_for_port
216
+ break
217
+ end
154
218
  end
155
- true
156
- when :wait_for_port
157
- output = File.read(@out_file)
158
- if output =~ /^RText service, listening on port (\d+)/
159
- port = $1.to_i
160
- @logger.info "connecting to #{port}" if @logger
161
- begin
162
- @socket = TCPSocket.new("127.0.0.1", port)
163
- @socket.setsockopt(:SOCKET, :RCVBUF, 1000000)
164
- rescue Errno::ECONNREFUSED
219
+ end
220
+ if @state == :wait_for_port
221
+ while true
222
+ break unless File.exist?(@out_file)
223
+ output = File.read(@out_file)
224
+ if output =~ /^RText service, listening on port (\d+)/
225
+ port = $1.to_i
226
+ @logger.info "connecting to #{port}" if @logger
227
+ begin
228
+ @socket = TCPSocket.new("127.0.0.1", port)
229
+ @socket.setsockopt(:SOCKET, :RCVBUF, 1000000)
230
+ rescue Errno::ECONNREFUSED
231
+ cleanup
232
+ @connection_listener.call(:timeout) if @connection_listener
233
+ @state = :off
234
+ @logger.warn "could not connect socket (connection timeout)" if @logger
235
+ return false
236
+ end
237
+ @state = :read_from_socket
238
+ @connection_listener.call(:connected) if @connection_listener
239
+ break
240
+ end
241
+ if Time.now > @connect_start_time + @connection_timeout
165
242
  cleanup
166
243
  @connection_listener.call(:timeout) if @connection_listener
167
- @work_state = :done
168
244
  @state = :off
169
245
  @logger.warn "could not connect socket (connection timeout)" if @logger
246
+ return false
170
247
  end
171
- @state = :connected
172
- @work_state = :read_from_socket
173
- @connection_listener.call(:connected) if @connection_listener
174
- end
175
- if Time.now > @connect_start_time + @connection_timeout
176
- cleanup
177
- @connection_listener.call(:timeout) if @connection_listener
178
- @work_state = :done
179
- @state = :off
180
- @logger.warn "could not connect socket (connection timeout)" if @logger
248
+ sleep(0.1)
181
249
  end
182
- true
183
- when :read_from_socket
250
+ end
251
+ if @state == :read_from_socket
184
252
  repeat = true
185
253
  socket_closed = false
186
254
  response_data = ""
@@ -208,13 +276,12 @@ def do_work
208
276
  end
209
277
  elsif !backend_running? || socket_closed
210
278
  cleanup
211
- @work_state = :done
279
+ @state = :off
212
280
  return false
213
281
  end
214
282
  end
215
- true
216
283
  end
217
-
284
+ true
218
285
  end
219
286
 
220
287
  def cleanup
@@ -224,7 +291,7 @@ def cleanup
224
291
  break unless backend_running?
225
292
  sleep(0.1)
226
293
  end
227
- File.unlink(@out_file) unless @keep_outfile
294
+ ensure_process_cleanup(@process_id, @keep_outfile ? @out_file : nil, 10)
228
295
  end
229
296
 
230
297
  end
@@ -247,7 +247,15 @@ class Instantiator
247
247
  element.setOrAddGeneric(feature.name, proxy)
248
248
  else
249
249
  begin
250
- element.setOrAddGeneric(feature.name, v.value)
250
+ v_value = v.value
251
+ feature_instance_class = feature.eType.instanceClass
252
+ if feature_instance_class == String && (v_value.is_a?(Float) || v_value.is_a?(Fixnum))
253
+ element.setOrAddGeneric(feature.name, v_value.to_s)
254
+ elsif feature_instance_class == Float && v_value.is_a?(Fixnum)
255
+ element.setOrAddGeneric(feature.name, v_value.to_f)
256
+ else
257
+ element.setOrAddGeneric(feature.name, v_value)
258
+ end
251
259
  rescue StandardError
252
260
  # backward compatibility for RGen versions not supporting BigDecimal
253
261
  if v.value.is_a?(BigDecimal)
@@ -302,9 +310,9 @@ class Instantiator
302
310
  elsif feature.eType.is_a?(RGen::ECore::EEnum)
303
311
  [:identifier, :string]
304
312
  else
305
- expected = { String => [:string, :identifier],
313
+ expected = { String => [:string, :identifier, :integer, :float],
306
314
  Integer => [:integer],
307
- Float => [:float],
315
+ Float => [:float, :integer],
308
316
  RGen::MetamodelBuilder::DataTypes::Boolean => [:boolean],
309
317
  Object => [:string, :identifier, :integer, :float, :boolean]
310
318
  }[feature.eType.instanceClass]
@@ -914,7 +914,11 @@ def assert_context(c, options)
914
914
  assert_equal(options[:in_array], c.position.in_array)
915
915
  assert_equal(options[:in_block], c.position.in_block)
916
916
  assert_equal((options[:after_label] || false), c.position.after_label)
917
- assert_equal(options[:problem], c.problem)
917
+ if options[:problem]
918
+ assert_equal(options[:problem], c.problem)
919
+ else
920
+ assert_nil(c.problem)
921
+ end
918
922
  if options[:feature]
919
923
  assert_equal(options[:feature], c.feature.name)
920
924
  else
@@ -106,6 +106,50 @@ class InstantiatorTest < MiniTest::Test
106
106
  end
107
107
  end
108
108
 
109
+ def test_int_float_string
110
+ root_elements = []
111
+ _, problems = instantiate(%Q(
112
+ TestNode text: 10
113
+ TestNode text: -14.55
114
+ ), TestMM, :root_elements => root_elements)
115
+ assert_no_problems(problems)
116
+ assert(root_elements.first.text.is_a?(String))
117
+ assert_equal('10', root_elements.first.text)
118
+ assert(root_elements[1].text.is_a?(String))
119
+ assert_equal('-14.55', root_elements[1].text)
120
+ end
121
+
122
+ def test_int_float
123
+ env, problems = instantiate(%Q(
124
+ TestNode float: "abc"
125
+ ), TestMM)
126
+ assert_equal(1, problems.length)
127
+
128
+ root_elements = []
129
+ env, problems = instantiate(%Q(
130
+ TestNode text: "some text", float: -25 {
131
+ TestNode text: "child"
132
+ TestNode text: "child2"
133
+ }
134
+ ), TestMM, :root_elements => root_elements)
135
+ assert_no_problems(problems)
136
+ assert_model_simple(env)
137
+ assert(root_elements.first.float.is_a?(Float))
138
+ assert_equal(-25.0, root_elements.first.float)
139
+
140
+ root_elements = []
141
+ env, problems = instantiate(%Q(
142
+ TestNode text: "some text", float: -72.001 {
143
+ TestNode text: "child"
144
+ TestNode text: "child2"
145
+ }
146
+ ), TestMM, :root_elements => root_elements)
147
+ assert_no_problems(problems)
148
+ assert_model_simple(env)
149
+ assert(root_elements.first.float.is_a?(Float))
150
+ assert_equal(-72.001, root_elements.first.float)
151
+ end
152
+
109
153
  def test_simple
110
154
  env, problems = instantiate(%Q(
111
155
  TestNode text: "some text", nums: [1,2] {
@@ -729,7 +773,6 @@ class InstantiatorTest < MiniTest::Test
729
773
  TestNode related: 1
730
774
  ), TestMM)
731
775
  assert_problems([
732
- [/argument 'text' can not take a integer, expected string/i, 2],
733
776
  [/argument 'integer' can not take a string, expected integer/i, 3],
734
777
  [/argument 'integer' can not take a boolean, expected integer/i, 4],
735
778
  [/argument 'integer' can not take a float, expected integer/i, 5],
@@ -1728,5 +1771,3 @@ class InstantiatorTest < MiniTest::Test
1728
1771
  end
1729
1772
 
1730
1773
  end
1731
-
1732
-
@@ -21,7 +21,7 @@ CrashOnRequestFile = File.dirname(__FILE__)+"/model/test.crash_on_request"
21
21
 
22
22
  def setup_connector(file)
23
23
  @infile = file
24
- outfile = File.dirname(__FILE__)+"/backend.out"
24
+ outfile = File.dirname(__FILE__)+"/backend.out" + Random.new.rand(100000000).to_s
25
25
  logfile = File.dirname(__FILE__)+"/frontend.log"
26
26
  logger = Logger.new(logfile)
27
27
  File.unlink(outfile) if File.exist?(outfile)
@@ -29,7 +29,7 @@ def setup_connector(file)
29
29
  man = RText::Frontend::ConnectorManager.new(
30
30
  :logger => logger,
31
31
  :keep_outfile => true,
32
- :connection_timeout => 2,
32
+ :connection_timeout => 10,
33
33
  :outfile_provider => lambda { File.expand_path(outfile) },
34
34
  :connect_callback => lambda do |connector, state|
35
35
  @connection_timeout = true if state == :timeout
@@ -936,8 +936,16 @@ def assert_link_targets(context, options)
936
936
  {"command" => "link_targets", "context" => lines, "column" => col})
937
937
  assert_equal "response", response["type"]
938
938
  assert_equal options[:targets], response["targets"]
939
- assert_equal options[:begin], response["begin_column"]
940
- assert_equal options[:end], response["end_column"]
939
+ if options[:begin]
940
+ assert_equal options[:begin], response["begin_column"]
941
+ else
942
+ assert_nil response["begin_column"]
943
+ end
944
+ if options[:end]
945
+ assert_equal options[:end], response["end_column"]
946
+ else
947
+ assert_nil response["end_column"]
948
+ end
941
949
  end
942
950
 
943
951
  def assert_completions(context, expected)
@@ -952,11 +960,10 @@ end
952
960
  def load_model
953
961
  done = false
954
962
  response = nil
955
- while !done
963
+ while !done
956
964
  response = @con.execute_command({"command" => "load_model"})
957
965
  if response == :connecting && !@connection_timeout
958
966
  sleep(0.1)
959
- @con.resume
960
967
  else
961
968
  done = true
962
969
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rtext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Thiede
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-11 00:00:00.000000000 Z
11
+ date: 2017-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rgen
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.8.2
19
+ version: 0.8.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.8.2
26
+ version: 0.8.0
27
27
  description: RText can be used to derive textual languages from an RGen metamodel
28
28
  with very little effort.
29
29
  email: martin dot thiede at gmx de
@@ -67,7 +67,6 @@ files:
67
67
  - test/instantiator_test.rb
68
68
  - test/integration/crash_on_request_editor.rb
69
69
  - test/integration/ecore_editor.rb
70
- - test/integration/frontend.log
71
70
  - test/integration/model/invalid_encoding.invenc
72
71
  - test/integration/model/test.crash_on_request
73
72
  - test/integration/model/test.crashing_backend
@@ -108,7 +107,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
107
  - !ruby/object:Gem::Version
109
108
  version: '0'
110
109
  requirements: []
111
- rubygems_version: 3.0.8
110
+ rubyforge_project:
111
+ rubygems_version: 2.5.2
112
112
  signing_key:
113
113
  specification_version: 4
114
114
  summary: Ruby Textual Modelling