rtext 0.4.0 → 0.5.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 (48) hide show
  1. data/CHANGELOG +20 -0
  2. data/{README → README.rdoc} +5 -1
  3. data/RText_Protocol +444 -0
  4. data/Rakefile +10 -10
  5. data/lib/rtext/completer.rb +32 -26
  6. data/lib/rtext/context_builder.rb +113 -59
  7. data/lib/rtext/default_loader.rb +73 -8
  8. data/lib/rtext/default_service_provider.rb +30 -14
  9. data/lib/rtext/frontend/config.rb +58 -0
  10. data/lib/rtext/frontend/connector.rb +233 -0
  11. data/lib/rtext/frontend/connector_manager.rb +81 -0
  12. data/lib/rtext/frontend/context.rb +56 -0
  13. data/lib/rtext/generic.rb +13 -0
  14. data/lib/rtext/instantiator.rb +30 -7
  15. data/lib/rtext/language.rb +54 -27
  16. data/lib/rtext/link_detector.rb +57 -0
  17. data/lib/rtext/message_helper.rb +77 -0
  18. data/lib/rtext/parser.rb +19 -68
  19. data/lib/rtext/serializer.rb +18 -3
  20. data/lib/rtext/service.rb +182 -118
  21. data/lib/rtext/tokenizer.rb +102 -0
  22. data/test/completer_test.rb +327 -70
  23. data/test/context_builder_test.rb +671 -91
  24. data/test/instantiator_test.rb +153 -0
  25. data/test/integration/backend.out +10 -0
  26. data/test/integration/crash_on_request_editor.rb +12 -0
  27. data/test/integration/ecore_editor.rb +50 -0
  28. data/test/integration/frontend.log +25138 -0
  29. data/test/integration/model/invalid_encoding.invenc +2 -0
  30. data/test/integration/model/test.crash_on_request +18 -0
  31. data/test/integration/model/test.crashing_backend +18 -0
  32. data/test/integration/model/test.dont_open_socket +0 -0
  33. data/test/integration/model/test.invalid_cmd_line +0 -0
  34. data/test/integration/model/test.not_in_rtext +0 -0
  35. data/test/integration/model/test_large_with_errors.ect3 +43523 -0
  36. data/test/integration/model/test_metamodel.ect +18 -0
  37. data/test/integration/model/test_metamodel2.ect +5 -0
  38. data/test/integration/model/test_metamodel_error.ect2 +3 -0
  39. data/test/integration/model/test_metamodel_ok.ect2 +18 -0
  40. data/test/integration/test.rb +684 -0
  41. data/test/link_detector_test.rb +276 -0
  42. data/test/message_helper_test.rb +118 -0
  43. data/test/rtext_test.rb +4 -1
  44. data/test/serializer_test.rb +96 -1
  45. data/test/tokenizer_test.rb +125 -0
  46. metadata +36 -10
  47. data/RText_Plugin_Implementation_Guide +0 -268
  48. data/lib/rtext_plugin/connection_manager.rb +0 -59
@@ -0,0 +1,18 @@
1
+ EPackage StatemachineMM {
2
+ EClass State, abstract: true {
3
+ EAttribute name, eType: /StatemachineMM/StringType
4
+ EReference parent, eType: /StatemachineMM/CompositeState, eOpposite: /StatemachineMM/CompositeState/substates
5
+ }
6
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
7
+ EClass CompositeState, eSuperTypes: [/StatemachineMM/State] {
8
+ EReference substates, upperBound: -1, containment: true, eType: /StatemachineMM/State, eOpposite: /StatemachineMM/State/parent
9
+ }
10
+ EClass Transition {
11
+ EReference target, upperBound: 1, eType: /StatemachineMM/State
12
+ EReference source, upperBound: 1, eType: /StatemachineMM/State
13
+ }
14
+ EDataType StringType
15
+ EAnnotation source: "test" {
16
+ EStringToStringMapEntry key: "kind", value: "package"
17
+ }
18
+ }
@@ -0,0 +1,5 @@
1
+ EPackage StatemachineMM2 {
2
+ EClass State
3
+ EClass SimpleState, eSuperTypes: [/StatemachineMM2/State]
4
+ }
5
+
@@ -0,0 +1,3 @@
1
+ EPackage StatemachineMM {
2
+ problem
3
+ }
@@ -0,0 +1,18 @@
1
+ EPackage StatemachineMM {
2
+ EClass State, abstract: true {
3
+ EAttribute name, eType: /StatemachineMM/StringType
4
+ EReference parent, eType: /StatemachineMM/CompositeState, eOpposite: /StatemachineMM/CompositeState/substates
5
+ }
6
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
7
+ EClass CompositeState, eSuperTypes: [/StatemachineMM/State] {
8
+ EReference substates, upperBound: -1, containment: true, eType: /StatemachineMM/State, eOpposite: /StatemachineMM/State/parent
9
+ }
10
+ EClass Transition {
11
+ EReference target, upperBound: 1, eType: /StatemachineMM/State
12
+ EReference source, upperBound: 1, eType: /StatemachineMM/State
13
+ }
14
+ EDataType StringType
15
+ EAnnotation source: "test" {
16
+ EStringToStringMapEntry key: "kind", value: "package"
17
+ }
18
+ }
@@ -0,0 +1,684 @@
1
+ # encoding: binary
2
+ $:.unshift(File.dirname(__FILE__)+"/../../lib")
3
+ require 'test/unit'
4
+ require 'rtext/frontend/connector_manager'
5
+ require 'rtext/frontend/context'
6
+ require 'logger'
7
+
8
+ class IntegrationTest < Test::Unit::TestCase
9
+
10
+ ModelFile = File.dirname(__FILE__)+"/model/test_metamodel.ect"
11
+ ModelFile2 = File.dirname(__FILE__)+"/model/test_metamodel2.ect"
12
+ LargeWithErrorsFile = File.dirname(__FILE__)+"/model/test_large_with_errors.ect3"
13
+ InvalidEncodingFile = File.dirname(__FILE__)+"/model/invalid_encoding.invenc"
14
+ NotInRTextFile = File.dirname(__FILE__)+"/model/test.not_in_rtext"
15
+ InvalidCmdLineFile = File.dirname(__FILE__)+"/model/test.invalid_cmd_line"
16
+ CrashingBackendFile = File.dirname(__FILE__)+"/model/test.crashing_backend"
17
+ DontOpenSocketFile = File.dirname(__FILE__)+"/model/test.dont_open_socket"
18
+ CrashOnRequestFile = File.dirname(__FILE__)+"/model/test.crash_on_request"
19
+
20
+ def setup_connector(file)
21
+ @infile = file
22
+ outfile = File.dirname(__FILE__)+"/backend.out"
23
+ logfile = File.dirname(__FILE__)+"/frontend.log"
24
+ logger = Logger.new(logfile)
25
+ File.unlink(outfile) if File.exist?(outfile)
26
+ @connection_timeout = false
27
+ man = RText::Frontend::ConnectorManager.new(
28
+ :logger => logger,
29
+ :keep_outfile => true,
30
+ :connection_timeout => 1,
31
+ :outfile_provider => lambda { File.expand_path(outfile) },
32
+ :connect_callback => lambda do |connector, state|
33
+ @connection_timeout = true if state == :timeout
34
+ end)
35
+ @con = man.connector_for_file(@infile)
36
+ end
37
+
38
+ def teardown
39
+ @con.stop if @con
40
+ end
41
+
42
+ def test_non_existing_file
43
+ setup_connector("this is not a file")
44
+ assert_nil @con
45
+ end
46
+
47
+ def test_not_in_rtext_file
48
+ setup_connector(NotInRTextFile)
49
+ assert_nil @con
50
+ end
51
+
52
+ def test_invalid_command_line
53
+ setup_connector(InvalidCmdLineFile)
54
+ assert @con
55
+ response = load_model
56
+ assert @connection_timeout
57
+ end
58
+
59
+ def test_crashing_backend
60
+ setup_connector(CrashingBackendFile)
61
+ assert @con
62
+ response = load_model
63
+ assert @connection_timeout
64
+ end
65
+
66
+ def test_backend_doesnt_open_socket
67
+ setup_connector(DontOpenSocketFile)
68
+ assert @con
69
+ response = load_model
70
+ assert @connection_timeout
71
+ end
72
+
73
+ def test_backend_crash_on_request
74
+ setup_connector(CrashOnRequestFile)
75
+ assert @con
76
+ response = load_model
77
+ assert_equal [], response["problems"]
78
+ response = @con.execute_command({"command" => "link_targets", "context" => [], "column" => 1})
79
+ assert_equal :timeout, response
80
+ end
81
+
82
+ # simulate external encoding utf-8 (-E in .rext) containing a iso-8859-1 character
83
+ def test_invalid_encoding
84
+ setup_connector(InvalidEncodingFile)
85
+ response = load_model
86
+ assert_equal "response", response["type"]
87
+ assert_equal [], response["problems"]
88
+ text = %Q(EPackage "iso-8859-1 umlaut: \xe4",| nsPrefix: "")
89
+ context = build_context(text)
90
+ assert_completions context, [
91
+ "nsPrefix:",
92
+ "nsURI:"
93
+ ]
94
+ end
95
+
96
+ def test_loadmodel
97
+ setup_connector(ModelFile)
98
+ response = load_model
99
+ assert_equal "response", response["type"]
100
+ assert_equal [], response["problems"]
101
+ end
102
+
103
+ def test_loadmodel_large_with_errors
104
+ setup_connector(LargeWithErrorsFile)
105
+ response = load_model
106
+ assert_equal "response", response["type"]
107
+ assert_equal 43523, response["problems"].first["problems"].size
108
+ end
109
+
110
+ def test_unknown_command
111
+ setup_connector(ModelFile)
112
+ response = load_model
113
+ response = @con.execute_command({"command" => "unknown"})
114
+ assert_equal "unknown_command_error", response["type"]
115
+ end
116
+
117
+ #TODO: connector restart when .rtext file changes
118
+
119
+ def test_complete_first_line
120
+ setup_connector(ModelFile)
121
+ load_model
122
+ context = build_context <<-END
123
+ |EPackage StatemachineMM {
124
+ END
125
+ assert_completions context, [
126
+ "EPackage"
127
+ ]
128
+ context = build_context <<-END
129
+ EPackage| StatemachineMM {
130
+ END
131
+ assert_completions context, [
132
+ "EPackage"
133
+ ]
134
+ context = build_context <<-END
135
+ EPackage |StatemachineMM {
136
+ END
137
+ assert_completions context, [
138
+ "name",
139
+ "nsPrefix:",
140
+ "nsURI:"
141
+ ]
142
+ context = build_context <<-END
143
+ EPackage S|tatemachineMM {
144
+ END
145
+ assert_completions context, [
146
+ "name",
147
+ "nsPrefix:",
148
+ "nsURI:"
149
+ ]
150
+ context = build_context <<-END
151
+ EPackage StatemachineMM| {
152
+ END
153
+ assert_completions context, [
154
+ "name",
155
+ "nsPrefix:",
156
+ "nsURI:"
157
+ ]
158
+ context = build_context <<-END
159
+ EPackage StatemachineMM |{
160
+ END
161
+ assert_completions context, [
162
+ ]
163
+ context = build_context <<-END
164
+ EPackage StatemachineMM {|
165
+ END
166
+ # these columns don't exist
167
+ assert_completions context, []
168
+ context = build_context({:col => 27}, "EPackage StatemachineMM {")
169
+ assert_completions context, []
170
+ context = build_context({:col => 28}, "EPackage StatemachineMM {")
171
+ assert_completions context, []
172
+ context = build_context({:col => 100}, "EPackage StatemachineMM {")
173
+ assert_completions context, []
174
+ # before first column is like first column
175
+ context = build_context({:col => 0}, "EPackage StatemachineMM {")
176
+ assert_completions context, [
177
+ "EPackage"
178
+ ]
179
+ context = build_context({:col => -1}, "EPackage StatemachineMM {")
180
+ assert_completions context, [
181
+ "EPackage"
182
+ ]
183
+ context = build_context({:col => -100}, "EPackage StatemachineMM {")
184
+ assert_completions context, [
185
+ "EPackage"
186
+ ]
187
+ end
188
+
189
+ def test_nested_command
190
+ setup_connector(ModelFile)
191
+ load_model
192
+ context = build_context <<-END
193
+ EPackage StatemachineMM {
194
+ | EClass State, abstract: true {
195
+ END
196
+ assert_completions context, [
197
+ "EAnnotation",
198
+ "EClass",
199
+ "EClassifier",
200
+ "EDataType",
201
+ "EEnum",
202
+ "EGenericType",
203
+ "EPackage"
204
+ ]
205
+ context = build_context <<-END
206
+ EPackage StatemachineMM {
207
+ |EClass State, abstract: true {
208
+ END
209
+ assert_completions context, [
210
+ "EAnnotation",
211
+ "EClass",
212
+ "EClassifier",
213
+ "EDataType",
214
+ "EEnum",
215
+ "EGenericType",
216
+ "EPackage"
217
+ ]
218
+ context = build_context <<-END
219
+ EPackage StatemachineMM {
220
+ EC|lass State, abstract: true {
221
+ END
222
+ assert_completions context, [
223
+ "EAnnotation",
224
+ "EClass",
225
+ "EClassifier",
226
+ "EDataType",
227
+ "EEnum",
228
+ "EGenericType",
229
+ "EPackage"
230
+ ]
231
+ context = build_context <<-END
232
+ EPackage StatemachineMM {
233
+ EClass| State, abstract: true {
234
+ END
235
+ assert_completions context, [
236
+ "EAnnotation",
237
+ "EClass",
238
+ "EClassifier",
239
+ "EDataType",
240
+ "EEnum",
241
+ "EGenericType",
242
+ "EPackage"
243
+ ]
244
+ context = build_context <<-END
245
+ EPackage StatemachineMM {
246
+ EClass |State, abstract: true {
247
+ END
248
+ assert_completions context, [
249
+ "name",
250
+ "abstract:",
251
+ "interface:",
252
+ "eSuperTypes:",
253
+ "instanceClassName:"
254
+ ]
255
+ context = build_context <<-END
256
+ EPackage StatemachineMM {
257
+ EClass S|tate, abstract: true {
258
+ END
259
+ assert_completions context, [
260
+ "name",
261
+ "abstract:",
262
+ "interface:",
263
+ "eSuperTypes:",
264
+ "instanceClassName:"
265
+ ]
266
+ context = build_context <<-END
267
+ EPackage StatemachineMM {
268
+ EClass State|, abstract: true {
269
+ END
270
+ assert_completions context, [
271
+ "name",
272
+ "abstract:",
273
+ "interface:",
274
+ "eSuperTypes:",
275
+ "instanceClassName:"
276
+ ]
277
+ context = build_context <<-END
278
+ EPackage StatemachineMM {
279
+ EClass State,| abstract: true {
280
+ END
281
+ assert_completions context, [
282
+ "abstract:",
283
+ "interface:",
284
+ "eSuperTypes:",
285
+ "instanceClassName:"
286
+ ]
287
+ context = build_context <<-END
288
+ EPackage StatemachineMM {
289
+ EClass State, |abstract: true {
290
+ END
291
+ assert_completions context, [
292
+ "abstract:",
293
+ "interface:",
294
+ "eSuperTypes:",
295
+ "instanceClassName:"
296
+ ]
297
+ context = build_context <<-END
298
+ EPackage StatemachineMM {
299
+ EClass State, a|bstract: true {
300
+ END
301
+ assert_completions context, [
302
+ "abstract:",
303
+ "interface:",
304
+ "eSuperTypes:",
305
+ "instanceClassName:"
306
+ ]
307
+ context = build_context <<-END
308
+ EPackage StatemachineMM {
309
+ EClass State, abstract:| true {
310
+ END
311
+ assert_completions context, [
312
+ "true",
313
+ "false"
314
+ ]
315
+ context = build_context <<-END
316
+ EPackage StatemachineMM {
317
+ EClass State, abstract: |true {
318
+ END
319
+ assert_completions context, [
320
+ "true",
321
+ "false"
322
+ ]
323
+ context = build_context <<-END
324
+ EPackage StatemachineMM {
325
+ EClass State, abstract: t|rue {
326
+ END
327
+ assert_completions context, [
328
+ "true",
329
+ "false"
330
+ ]
331
+ context = build_context <<-END
332
+ EPackage StatemachineMM {
333
+ EClass State, abstract: true| {
334
+ END
335
+ assert_completions context, [
336
+ "true",
337
+ "false"
338
+ ]
339
+ context = build_context <<-END
340
+ EPackage StatemachineMM {
341
+ EClass State, abstract: true |{
342
+ END
343
+ assert_completions context, [
344
+ ]
345
+ context = build_context <<-END
346
+ EPackage StatemachineMM {
347
+ EClass State, abstract: true {|
348
+ END
349
+ assert_completions context, [
350
+ ]
351
+ end
352
+
353
+ def test_reference_completion
354
+ setup_connector(ModelFile)
355
+ load_model
356
+ context = build_context <<-END
357
+ EPackage StatemachineMM {
358
+ EClass State, abstract: true {
359
+ EAttribute name, eType: |/StatemachineMM/StringType
360
+ END
361
+ assert_completions context, [
362
+ "/StatemachineMM/CompositeState",
363
+ "/StatemachineMM/SimpleState",
364
+ "/StatemachineMM/State",
365
+ "/StatemachineMM/StringType",
366
+ "/StatemachineMM/Transition",
367
+ "/StatemachineMM2/SimpleState",
368
+ "/StatemachineMM2/State",
369
+ ]
370
+ context = build_context <<-END
371
+ EPackage StatemachineMM {
372
+ EClass State, abstract: true {
373
+ EAttribute name, eType: /StatemachineMM/|StringType
374
+ END
375
+ assert_completions context, [
376
+ "/StatemachineMM/CompositeState",
377
+ "/StatemachineMM/SimpleState",
378
+ "/StatemachineMM/State",
379
+ "/StatemachineMM/StringType",
380
+ "/StatemachineMM/Transition",
381
+ "/StatemachineMM2/SimpleState",
382
+ "/StatemachineMM2/State",
383
+ ]
384
+ context = build_context <<-END
385
+ EPackage StatemachineMM {
386
+ EClass State, abstract: true {
387
+ EAttribute name, eType: /StatemachineMM/St|ringType
388
+ END
389
+ assert_completions context, [
390
+ "/StatemachineMM/CompositeState",
391
+ "/StatemachineMM/SimpleState",
392
+ "/StatemachineMM/State",
393
+ "/StatemachineMM/StringType",
394
+ "/StatemachineMM/Transition",
395
+ "/StatemachineMM2/SimpleState",
396
+ "/StatemachineMM2/State",
397
+ ]
398
+ context = build_context <<-END
399
+ EPackage StatemachineMM {
400
+ EClass State, abstract: true {
401
+ EAttribute name, eType: /StatemachineMM/StringType|
402
+ END
403
+ assert_completions context, [
404
+ "/StatemachineMM/CompositeState",
405
+ "/StatemachineMM/SimpleState",
406
+ "/StatemachineMM/State",
407
+ "/StatemachineMM/StringType",
408
+ "/StatemachineMM/Transition",
409
+ "/StatemachineMM2/SimpleState",
410
+ "/StatemachineMM2/State",
411
+ ]
412
+ end
413
+
414
+ def test_reference_completion_in_array
415
+ setup_connector(ModelFile)
416
+ load_model
417
+ context = build_context <<-END
418
+ EPackage StatemachineMM {
419
+ EClass State, abstract: true {
420
+ EAttribute name, eType: /StatemachineMM/StringType
421
+ EReference parent, eType: /StatemachineMM/CompositeState, eOpposite: /StatemachineMM/CompositeState/substates
422
+ }
423
+ EClass SimpleState, eSuperTypes: [|/StatemachineMM/State]
424
+ END
425
+ assert_completions context, [
426
+ "/StatemachineMM/CompositeState",
427
+ "/StatemachineMM/SimpleState",
428
+ "/StatemachineMM/State",
429
+ "/StatemachineMM/Transition",
430
+ "/StatemachineMM2/SimpleState",
431
+ "/StatemachineMM2/State",
432
+ ]
433
+ context = build_context <<-END
434
+ EPackage StatemachineMM {
435
+ EClass State, abstract: true {
436
+ EAttribute name, eType: /StatemachineMM/StringType
437
+ EReference parent, eType: /StatemachineMM/CompositeState, eOpposite: /StatemachineMM/CompositeState/substates
438
+ }
439
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/S|tate]
440
+ END
441
+ assert_completions context, [
442
+ "/StatemachineMM/CompositeState",
443
+ "/StatemachineMM/SimpleState",
444
+ "/StatemachineMM/State",
445
+ "/StatemachineMM/Transition",
446
+ "/StatemachineMM2/SimpleState",
447
+ "/StatemachineMM2/State",
448
+ ]
449
+ context = build_context <<-END
450
+ EPackage StatemachineMM {
451
+ EClass State, abstract: true {
452
+ EAttribute name, eType: /StatemachineMM/StringType
453
+ EReference parent, eType: /StatemachineMM/CompositeState, eOpposite: /StatemachineMM/CompositeState/substates
454
+ }
455
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State|]
456
+ END
457
+ assert_completions context, [
458
+ "/StatemachineMM/CompositeState",
459
+ "/StatemachineMM/SimpleState",
460
+ "/StatemachineMM/State",
461
+ "/StatemachineMM/Transition",
462
+ "/StatemachineMM2/SimpleState",
463
+ "/StatemachineMM2/State",
464
+ ]
465
+ context = build_context <<-END
466
+ EPackage StatemachineMM {
467
+ EClass State, abstract: true {
468
+ EAttribute name, eType: /StatemachineMM/StringType
469
+ EReference parent, eType: /StatemachineMM/CompositeState, eOpposite: /StatemachineMM/CompositeState/substates
470
+ }
471
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State]|
472
+ END
473
+ assert_completions context, [
474
+ ]
475
+ end
476
+
477
+ def test_integer_completion
478
+ setup_connector(ModelFile)
479
+ load_model
480
+ context = build_context <<-END
481
+ EPackage StatemachineMM {
482
+ EClass State, abstract: true {
483
+ EAttribute name, eType: /StatemachineMM/StringType
484
+ EReference parent, eType: /StatemachineMM/CompositeState, eOpposite: /StatemachineMM/CompositeState/substates
485
+ }
486
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
487
+ EClass CompositeState, eSuperTypes: [/StatemachineMM/State] {
488
+ EReference substates, upperBound: |-1, containment: true, eType: /StatemachineMM/State, eOpposite: /StatemachineMM/State/parent
489
+ END
490
+ assert_completions context, [
491
+ "0",
492
+ ]
493
+ context = build_context <<-END
494
+ EPackage StatemachineMM {
495
+ EClass State, abstract: true {
496
+ EAttribute name, eType: /StatemachineMM/StringType
497
+ EReference parent, eType: /StatemachineMM/CompositeState, eOpposite: /StatemachineMM/CompositeState/substates
498
+ }
499
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
500
+ EClass CompositeState, eSuperTypes: [/StatemachineMM/State] {
501
+ EReference substates, upperBound: -1|, containment: true, eType: /StatemachineMM/State, eOpposite: /StatemachineMM/State/parent
502
+ END
503
+ assert_completions context, [
504
+ "0",
505
+ ]
506
+ end
507
+
508
+ def test_link_targets
509
+ setup_connector(ModelFile)
510
+ load_model
511
+ context = build_context <<-END
512
+ EPackage StatemachineMM {
513
+ EClass State, abstract: true {
514
+ EAttribute name, eType: /St|atemachineMM/StringType
515
+ END
516
+ assert_link_targets context, :begin => 29, :end => 54, :targets => [
517
+ {"file"=> File.expand_path(@infile),
518
+ "line"=>14,
519
+ "display"=>"/StatemachineMM/StringType [EDataType]"}
520
+ ]
521
+ context = build_context <<-END
522
+ EPackage StatemachineMM {
523
+ EClass State, abstract: true {
524
+ EAttribute name, eType: |/StatemachineMM/StringType
525
+ END
526
+ assert_link_targets context, :begin => 29, :end => 54, :targets => [
527
+ {"file"=> File.expand_path(@infile),
528
+ "line"=>14,
529
+ "display"=>"/StatemachineMM/StringType [EDataType]"}
530
+ ]
531
+ context = build_context <<-END
532
+ EPackage StatemachineMM {
533
+ EClass State, abstract: true {
534
+ EAttribute name, eType: /StatemachineMM/StringTyp|e
535
+ END
536
+ assert_link_targets context, :begin => 29, :end => 54, :targets => [
537
+ {"file"=> File.expand_path(@infile),
538
+ "line"=>14,
539
+ "display"=>"/StatemachineMM/StringType [EDataType]"}
540
+ ]
541
+ context = build_context <<-END
542
+ EPackage StatemachineMM {
543
+ EClass State, abstract: true {
544
+ EAttribute name, eType: /StatemachineMM/StringType|
545
+ END
546
+ assert_link_targets context, :begin => nil, :end => nil, :targets => []
547
+ context = build_context <<-END
548
+ EPackage StatemachineMM {
549
+ EClass State, abstract: true {
550
+ EAttribute name, eType:| /StatemachineMM/StringType
551
+ END
552
+ assert_link_targets context, :begin => nil, :end => nil, :targets => []
553
+ # backward ref
554
+ context = build_context <<-END
555
+ EPackage StatemachineMM {
556
+ E|Class State, abstract: true {
557
+ END
558
+ assert_link_targets context, :begin => 3, :end => 8, :targets => [
559
+ {"file"=> File.expand_path(@infile),
560
+ "line"=>6,
561
+ "display"=>"/StatemachineMM/SimpleState [EClass]"},
562
+ {"file"=> File.expand_path(@infile),
563
+ "line"=>7,
564
+ "display"=>"/StatemachineMM/CompositeState [EClass]"}
565
+ ]
566
+ context = build_context <<-END
567
+ EPackage StatemachineMM {
568
+ EClass State, abstract: true {
569
+ EAttribute name, eType: /StatemachineMM/StringType
570
+ EReference parent, eType: /StatemachineMM/CompositeState, eOpposite: /StatemachineMM/CompositeState/substates
571
+ }
572
+ |EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
573
+ END
574
+ assert_link_targets context, :begin => 3, :end => 8, :targets => []
575
+ end
576
+
577
+ def test_link_targets_no_text_after_name
578
+ setup_connector(ModelFile)
579
+ load_model
580
+ context = build_context({:infile => ModelFile2}, <<-END
581
+ EPackage StatemachineMM2 {
582
+ ECl|ass State
583
+ END
584
+ )
585
+ assert_link_targets context, :file => ModelFile2, :begin => 3, :end => 8, :targets => [
586
+ {"file"=> File.expand_path(ModelFile2),
587
+ "line"=>3,
588
+ "display"=>"/StatemachineMM2/SimpleState [EClass]"}
589
+ ]
590
+ end
591
+
592
+ def test_find_elements
593
+ setup_connector(ModelFile)
594
+ load_model
595
+ response = @con.execute_command(
596
+ {"command" => "find_elements", "search_pattern" => "Sta"})
597
+ assert_equal \
598
+ [{"display"=>"State [EClass] - /StatemachineMM",
599
+ "file"=> File.expand_path(@infile),
600
+ "line"=>2},
601
+ {"display"=>"State [EClass] - /StatemachineMM2",
602
+ "file"=> File.expand_path(ModelFile2),
603
+ "line"=>2},
604
+ {"display"=>"StatemachineMM [EPackage] - /StatemachineMM",
605
+ "file"=> File.expand_path(@infile),
606
+ "line"=>1},
607
+ {"display"=>"StatemachineMM2 [EPackage] - /StatemachineMM2",
608
+ "file"=> File.expand_path(ModelFile2),
609
+ "line"=>1}], response["elements"]
610
+ response = @con.execute_command(
611
+ {"command" => "find_elements", "search_pattern" => "target"})
612
+ assert_equal \
613
+ [{"display"=>"target [EReference] - /StatemachineMM/Transition",
614
+ "file"=> File.expand_path(@infile),
615
+ "line"=>11}], response["elements"]
616
+ response = @con.execute_command(
617
+ {"command" => "find_elements", "search_pattern" => ""})
618
+ assert_equal [], response["elements"]
619
+ response = @con.execute_command(
620
+ {"command" => "find_elements", "search_pattern" => "xxx"})
621
+ assert_equal [], response["elements"]
622
+ end
623
+
624
+ TestContext = Struct.new(:line, :col)
625
+
626
+ def build_context(text, text2=nil)
627
+ if text.is_a?(Hash)
628
+ context_lines = text2.split("\n")
629
+ pos_in_line = text[:col] || context_lines.last.index("|") + 1
630
+ infile = text[:infile] || @infile
631
+ else
632
+ context_lines = text.split("\n")
633
+ pos_in_line = context_lines.last.index("|") + 1
634
+ infile = @infile
635
+ end
636
+ context_lines.last.sub!("|", "")
637
+
638
+ # check that the context data actally matches the real file in the filesystem
639
+ content = File.open(infile, "rb"){|f| f.read}
640
+ ref_lines = content.split(/\r?\n/)[0..context_lines.size-1]
641
+ raise "inconsistent test data, expected\n:#{ref_lines.join("\n")}\ngot:\n#{context_lines.join("\n")}\n" \
642
+ unless ref_lines == context_lines
643
+
644
+ # column numbers start at 1
645
+ TestContext.new(context_lines.size, pos_in_line)
646
+ end
647
+
648
+ def assert_link_targets(context, options)
649
+ infile = options[:file] || @infile
650
+ content = File.open(infile, "rb") {|f| f.read}
651
+ lines = content.split(/\r?\n/)[0..context.line-1]
652
+ lines = RText::Frontend::Context.extract(lines)
653
+ response = @con.execute_command(
654
+ {"command" => "link_targets", "context" => lines, "column" => context.col})
655
+ assert_equal options[:targets], response["targets"]
656
+ assert_equal options[:begin], response["begin_column"]
657
+ assert_equal options[:end], response["end_column"]
658
+ end
659
+
660
+ def assert_completions(context, expected)
661
+ content = File.open(@infile, "rb"){|f| f.read}
662
+ lines = content.split(/\r?\n/)[0..context.line-1]
663
+ lines = RText::Frontend::Context.extract(lines)
664
+ response = @con.execute_command(
665
+ {"command" => "content_complete", "context" => lines, "column" => context.col})
666
+ assert_equal expected, response["options"].collect{|o| o["insert"]}
667
+ end
668
+
669
+ def load_model
670
+ done = false
671
+ response = nil
672
+ while !done
673
+ response = @con.execute_command({"command" => "load_model"})
674
+ if response == :connecting && !@connection_timeout
675
+ sleep(0.1)
676
+ @con.resume
677
+ else
678
+ done = true
679
+ end
680
+ end
681
+ response
682
+ end
683
+
684
+ end