rtext 0.5.1 → 0.7.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.
- data/CHANGELOG +29 -0
- data/MIT-LICENSE +1 -1
- data/RText_Protocol +102 -51
- data/Rakefile +1 -1
- data/lib/rtext/context_builder.rb +8 -1
- data/lib/rtext/default_completer.rb +163 -0
- data/lib/rtext/default_loader.rb +28 -20
- data/lib/rtext/default_resolver.rb +42 -0
- data/lib/rtext/default_service_provider.rb +49 -21
- data/lib/rtext/frontend/connector.rb +2 -1
- data/lib/rtext/instantiator.rb +38 -16
- data/lib/rtext/json_interface.rb +31 -0
- data/lib/rtext/language.rb +24 -4
- data/lib/rtext/message_helper.rb +35 -25
- data/lib/rtext/parser.rb +27 -45
- data/lib/rtext/serializer.rb +13 -5
- data/lib/rtext/service.rb +27 -18
- data/lib/rtext/tokenizer.rb +18 -2
- data/test/completer_test.rb +35 -18
- data/test/context_builder_test.rb +7 -7
- data/test/instantiator_test.rb +116 -48
- data/test/integration/backend.out +13 -10
- data/test/integration/frontend.log +7664 -0
- data/test/integration/test.rb +6 -0
- data/test/message_helper_test.rb +4 -4
- data/test/serializer_test.rb +101 -3
- data/test/tokenizer_test.rb +33 -1
- metadata +7 -5
- data/lib/rtext/completer.rb +0 -128
data/test/integration/test.rb
CHANGED
@@ -572,6 +572,11 @@ EPackage StatemachineMM {
|
|
572
572
|
|EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
|
573
573
|
END
|
574
574
|
assert_link_targets context, :begin => 3, :end => 8, :targets => []
|
575
|
+
# bad location
|
576
|
+
context = build_context <<-END
|
577
|
+
EPackage S|tatemachineMM {
|
578
|
+
END
|
579
|
+
assert_link_targets context, :begin => 10, :end => 23, :targets => []
|
575
580
|
end
|
576
581
|
|
577
582
|
def test_link_targets_no_text_after_name
|
@@ -652,6 +657,7 @@ def assert_link_targets(context, options)
|
|
652
657
|
lines = RText::Frontend::Context.extract(lines)
|
653
658
|
response = @con.execute_command(
|
654
659
|
{"command" => "link_targets", "context" => lines, "column" => context.col})
|
660
|
+
assert_equal "response", response["type"]
|
655
661
|
assert_equal options[:targets], response["targets"]
|
656
662
|
assert_equal options[:begin], response["begin_column"]
|
657
663
|
assert_equal options[:end], response["end_column"]
|
data/test/message_helper_test.rb
CHANGED
@@ -71,18 +71,18 @@ def test_extract
|
|
71
71
|
# a iso-8859-1 '�'
|
72
72
|
obj = extract_message('19{"key":"umlaut%e4"}'.force_encoding("binary"))
|
73
73
|
assert_equal "ASCII-8BIT", obj["key"].encoding.name
|
74
|
-
assert_equal "umlaut\xe4", obj["key"]
|
74
|
+
assert_equal "umlaut\xe4".force_encoding("ascii-8bit"), obj["key"]
|
75
75
|
obj = extract_message('19{"key":"umlaut%e4"}'.force_encoding("utf-8"))
|
76
76
|
assert_equal "ASCII-8BIT", obj["key"].encoding.name
|
77
|
-
assert_equal "umlaut\xe4", obj["key"]
|
77
|
+
assert_equal "umlaut\xe4".force_encoding("ascii-8bit"), obj["key"]
|
78
78
|
|
79
79
|
# a utf-8 '�'
|
80
80
|
obj = extract_message('22{"key":"umlaut%c3%a4"}'.force_encoding("binary"))
|
81
81
|
assert_equal "ASCII-8BIT", obj["key"].encoding.name
|
82
|
-
assert_equal "umlaut\xc3\xa4", obj["key"]
|
82
|
+
assert_equal "umlaut\xc3\xa4".force_encoding("ascii-8bit"), obj["key"]
|
83
83
|
obj = extract_message('22{"key":"umlaut%c3%a4"}'.force_encoding("utf-8"))
|
84
84
|
assert_equal "ASCII-8BIT", obj["key"].encoding.name
|
85
|
-
assert_equal "umlaut\xc3\xa4", obj["key"]
|
85
|
+
assert_equal "umlaut\xc3\xa4".force_encoding("ascii-8bit"), obj["key"]
|
86
86
|
|
87
87
|
# %
|
88
88
|
obj = extract_message('13{"key":"%25"}')
|
data/test/serializer_test.rb
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
$:.unshift File.join(File.dirname(__FILE__),"..","lib")
|
2
2
|
|
3
3
|
require 'test/unit'
|
4
|
+
require 'bigdecimal'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'stringio'
|
4
7
|
require 'rgen/environment'
|
5
8
|
require 'rgen/metamodel_builder'
|
6
9
|
require 'rtext/serializer'
|
7
10
|
require 'rtext/language'
|
8
11
|
|
9
12
|
class SerializerTest < Test::Unit::TestCase
|
13
|
+
TestOutputFile = ".serializer_test_file"
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
FileUtils.rm_f TestOutputFile
|
17
|
+
end
|
10
18
|
|
11
19
|
class StringWriter < String
|
12
20
|
alias write concat
|
@@ -18,6 +26,7 @@ class SerializerTest < Test::Unit::TestCase
|
|
18
26
|
:name => "SomeEnum", :literals => [:A, :B, :'non-word*chars', :'2you'])
|
19
27
|
class TestNode < RGen::MetamodelBuilder::MMBase
|
20
28
|
has_attr 'text', String
|
29
|
+
has_many_attr 'texts', String
|
21
30
|
has_attr 'integer', Integer
|
22
31
|
has_attr 'float', Float
|
23
32
|
has_attr 'enum', SomeEnum
|
@@ -40,6 +49,17 @@ TestNode text: "some text" {
|
|
40
49
|
), output
|
41
50
|
end
|
42
51
|
|
52
|
+
def test_many_attr
|
53
|
+
testModel = TestMM::TestNode.new(:texts => ["a", "b", "c"])
|
54
|
+
|
55
|
+
output = StringWriter.new
|
56
|
+
serialize(testModel, TestMM, output)
|
57
|
+
|
58
|
+
assert_equal %Q(\
|
59
|
+
TestNode texts: ["a", "b", "c"]
|
60
|
+
), output
|
61
|
+
end
|
62
|
+
|
43
63
|
module TestMMFeatureProvider
|
44
64
|
extend RGen::MetamodelBuilder::ModuleExtension
|
45
65
|
class TestNode < RGen::MetamodelBuilder::MMBase
|
@@ -126,8 +146,9 @@ TestNode unquoted: "//"
|
|
126
146
|
testModel = TestMMComment::TestNode.new(
|
127
147
|
:comment => "this is a comment",
|
128
148
|
:childs => [
|
129
|
-
TestMMComment::TestNode.new(:comment => "
|
130
|
-
TestMMComment::TestNode.new(:comment => "don't show")
|
149
|
+
TestMMComment::TestNode.new(:comment => "\n\ncomment of a child node\n multiline\n\n\nanother\n\n\n"),
|
150
|
+
TestMMComment::TestNode.new(:comment => "don't show"),
|
151
|
+
TestMMComment::TestNode.new(:comment => "")])
|
131
152
|
|
132
153
|
output = StringWriter.new
|
133
154
|
serialize(testModel, TestMMComment, output,
|
@@ -144,10 +165,16 @@ TestNode unquoted: "//"
|
|
144
165
|
assert_equal %Q(\
|
145
166
|
#this is a comment
|
146
167
|
TestNode {
|
168
|
+
#
|
169
|
+
#
|
147
170
|
#comment of a child node
|
148
171
|
# multiline
|
172
|
+
#
|
173
|
+
#
|
174
|
+
#another
|
149
175
|
TestNode
|
150
176
|
TestNode comment: "don't show"
|
177
|
+
TestNode
|
151
178
|
}
|
152
179
|
), output
|
153
180
|
end
|
@@ -370,6 +397,44 @@ TestNode {
|
|
370
397
|
), output
|
371
398
|
end
|
372
399
|
|
400
|
+
module TestMMLabeledContainment
|
401
|
+
extend RGen::MetamodelBuilder::ModuleExtension
|
402
|
+
class TestNode < RGen::MetamodelBuilder::MMBase
|
403
|
+
abstract
|
404
|
+
has_attr 'text', String
|
405
|
+
contains_many 'childs', TestNode, 'parent'
|
406
|
+
end
|
407
|
+
class TestNode1 < TestNode
|
408
|
+
end
|
409
|
+
class TestNode2 < TestNode
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
def test_labeled_containment
|
414
|
+
testModel = TestMMLabeledContainment::TestNode1.new(:text => "some text", :childs => [
|
415
|
+
TestMMLabeledContainment::TestNode2.new(:text => "child", :childs => [
|
416
|
+
TestMMLabeledContainment::TestNode1.new(:text => "nested child")
|
417
|
+
])])
|
418
|
+
|
419
|
+
output = StringWriter.new
|
420
|
+
serialize(testModel, TestMMLabeledContainment, output, :labeled_containments => proc {|c|
|
421
|
+
if c == TestMMLabeledContainment::TestNode2.ecore
|
422
|
+
["childs"]
|
423
|
+
else
|
424
|
+
[]
|
425
|
+
end
|
426
|
+
})
|
427
|
+
|
428
|
+
assert_equal %Q(\
|
429
|
+
TestNode1 text: "some text" {
|
430
|
+
TestNode2 text: "child" {
|
431
|
+
childs:
|
432
|
+
TestNode1 text: "nested child"
|
433
|
+
}
|
434
|
+
}
|
435
|
+
), output
|
436
|
+
end
|
437
|
+
|
373
438
|
def test_escapes
|
374
439
|
testModel = TestMM::TestNode.new(:text => %Q(some " \\ \\" text \r xx \n xx \r\n xx \t xx \b xx \f))
|
375
440
|
output = StringWriter.new
|
@@ -423,6 +488,17 @@ TestNode {
|
|
423
488
|
assert_equal %q(TestNode float: 1.2)+"\n", output
|
424
489
|
end
|
425
490
|
|
491
|
+
def test_float_big_decimal
|
492
|
+
begin
|
493
|
+
testModel = TestMM::TestNode.new(:float => BigDecimal.new("1234567890.123456789"))
|
494
|
+
rescue StandardError
|
495
|
+
return
|
496
|
+
end
|
497
|
+
output = StringWriter.new
|
498
|
+
serialize(testModel, TestMM, output)
|
499
|
+
assert_equal %q(TestNode float: 1234567890.123456789)+"\n", output
|
500
|
+
end
|
501
|
+
|
426
502
|
def test_enum
|
427
503
|
testModel = [
|
428
504
|
TestMM::TestNode.new(:enum => :A),
|
@@ -507,12 +583,34 @@ TestNodeX text: "some text" {
|
|
507
583
|
), output
|
508
584
|
end
|
509
585
|
|
586
|
+
def test_file_output
|
587
|
+
testModel = TestMM::TestNode.new(:text => "some text")
|
588
|
+
|
589
|
+
File.open(TestOutputFile, "w") do |f|
|
590
|
+
serialize(testModel, TestMM, f)
|
591
|
+
end
|
592
|
+
|
593
|
+
assert_equal %Q(\
|
594
|
+
TestNode text: "some text"
|
595
|
+
), File.read(TestOutputFile)
|
596
|
+
end
|
597
|
+
|
598
|
+
def test_stringio_output
|
599
|
+
testModel = TestMM::TestNode.new(:text => "some text")
|
600
|
+
|
601
|
+
output = StringIO.new
|
602
|
+
serialize(testModel, TestMM, output)
|
603
|
+
|
604
|
+
assert_equal %Q(\
|
605
|
+
TestNode text: "some text"
|
606
|
+
), output.string
|
607
|
+
end
|
608
|
+
|
510
609
|
def serialize(model, mm, output, options={})
|
511
610
|
lang = RText::Language.new(mm.ecore, options)
|
512
611
|
ser = RText::Serializer.new(lang)
|
513
612
|
ser.serialize(model, output)
|
514
613
|
end
|
515
614
|
|
516
|
-
|
517
615
|
end
|
518
616
|
|
data/test/tokenizer_test.rb
CHANGED
@@ -105,13 +105,45 @@ end
|
|
105
105
|
|
106
106
|
def test_error
|
107
107
|
assert_tokens [
|
108
|
-
Token.new(:error, "\"
|
108
|
+
Token.new(:error, "\"", 1, 1, 1),
|
109
|
+
Token.new(:identifier, "open", 1, 2, 5),
|
109
110
|
Token.new(:newline, nil, 1, nil, nil)
|
110
111
|
], <<-END
|
111
112
|
"open
|
112
113
|
END
|
113
114
|
end
|
114
115
|
|
116
|
+
def test_with_bom
|
117
|
+
assert_tokens [
|
118
|
+
Token.new(:identifier, "TestNode", 1, 1, 8),
|
119
|
+
Token.new(:integer, 1, 1, 10, 10),
|
120
|
+
Token.new(:newline, nil, 1, nil, nil)
|
121
|
+
], "\xEF\xBB\xBFTestNode 1"
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_excessive_newline
|
125
|
+
assert_tokens [
|
126
|
+
Token.new(:identifier, "TestNode", 3, 1, 8),
|
127
|
+
Token.new(:newline, nil, 3, nil, nil),
|
128
|
+
Token.new(:identifier, "TestNode", 5, 1, 8),
|
129
|
+
Token.new(:newline, nil, 5, nil, nil)
|
130
|
+
], %Q(
|
131
|
+
|
132
|
+
TestNode
|
133
|
+
|
134
|
+
TestNode
|
135
|
+
|
136
|
+
)
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_only_newline
|
140
|
+
assert_tokens [
|
141
|
+
], %Q(
|
142
|
+
|
143
|
+
|
144
|
+
)
|
145
|
+
end
|
146
|
+
|
115
147
|
def do_tokenize(str)
|
116
148
|
tokenize(str, /\A\/[\/\w]+/)
|
117
149
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rtext
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-08-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rgen
|
@@ -39,9 +39,10 @@ extra_rdoc_files:
|
|
39
39
|
- RText_Users_Guide
|
40
40
|
- RText_Protocol
|
41
41
|
files:
|
42
|
-
- lib/rtext/completer.rb
|
43
42
|
- lib/rtext/context_builder.rb
|
43
|
+
- lib/rtext/default_completer.rb
|
44
44
|
- lib/rtext/default_loader.rb
|
45
|
+
- lib/rtext/default_resolver.rb
|
45
46
|
- lib/rtext/default_service_provider.rb
|
46
47
|
- lib/rtext/frontend/config.rb
|
47
48
|
- lib/rtext/frontend/connector.rb
|
@@ -49,6 +50,7 @@ files:
|
|
49
50
|
- lib/rtext/frontend/context.rb
|
50
51
|
- lib/rtext/generic.rb
|
51
52
|
- lib/rtext/instantiator.rb
|
53
|
+
- lib/rtext/json_interface.rb
|
52
54
|
- lib/rtext/language.rb
|
53
55
|
- lib/rtext/link_detector.rb
|
54
56
|
- lib/rtext/message_helper.rb
|
@@ -64,8 +66,8 @@ files:
|
|
64
66
|
- test/integration/ecore_editor.rb
|
65
67
|
- test/integration/frontend.log
|
66
68
|
- test/integration/model/invalid_encoding.invenc
|
67
|
-
- test/integration/model/test.crashing_backend
|
68
69
|
- test/integration/model/test.crash_on_request
|
70
|
+
- test/integration/model/test.crashing_backend
|
69
71
|
- test/integration/model/test.dont_open_socket
|
70
72
|
- test/integration/model/test.invalid_cmd_line
|
71
73
|
- test/integration/model/test.not_in_rtext
|
@@ -110,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
112
|
version: '0'
|
111
113
|
requirements: []
|
112
114
|
rubyforge_project:
|
113
|
-
rubygems_version: 1.8.
|
115
|
+
rubygems_version: 1.8.24
|
114
116
|
signing_key:
|
115
117
|
specification_version: 3
|
116
118
|
summary: Ruby Textual Modelling
|
data/lib/rtext/completer.rb
DELETED
@@ -1,128 +0,0 @@
|
|
1
|
-
require 'rgen/ecore/ecore_ext'
|
2
|
-
|
3
|
-
module RText
|
4
|
-
|
5
|
-
class Completer
|
6
|
-
|
7
|
-
CompletionOption = Struct.new(:text, :extra)
|
8
|
-
|
9
|
-
# Creates a completer for RText::Language +language+.
|
10
|
-
#
|
11
|
-
def initialize(language)
|
12
|
-
@lang = language
|
13
|
-
end
|
14
|
-
|
15
|
-
# Provides completion options
|
16
|
-
#
|
17
|
-
# :ref_completion_option_provider
|
18
|
-
# a proc which receives a EReference and should return
|
19
|
-
# the possible completion options as CompletionOption objects
|
20
|
-
# note, that the context element may be nil if this information is unavailable
|
21
|
-
#
|
22
|
-
def complete(context, ref_completion_option_provider=nil)
|
23
|
-
clazz = context && context.element && context.element.class.ecore
|
24
|
-
if clazz
|
25
|
-
if context.in_block
|
26
|
-
# command and lable completion within block
|
27
|
-
types = []
|
28
|
-
labled_refs = []
|
29
|
-
if context.feature
|
30
|
-
if context.feature.is_a?(RGen::ECore::EReference) && context.feature.containment
|
31
|
-
types = @lang.concrete_types(context.feature.eType)
|
32
|
-
else
|
33
|
-
# invalid, ignore
|
34
|
-
end
|
35
|
-
else
|
36
|
-
# all target types which don't need a label
|
37
|
-
# and all lables which are needed by a potential target type
|
38
|
-
@lang.containments(clazz).each do |r|
|
39
|
-
([r.eType] + r.eType.eAllSubTypes).select{|t| !t.abstract}.each do |t|
|
40
|
-
if @lang.containments_by_target_type(clazz, t).size > 1
|
41
|
-
labled_refs << r
|
42
|
-
else
|
43
|
-
types << t
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
types.uniq.
|
49
|
-
sort{|a,b| a.name <=> b.name}.collect do |c|
|
50
|
-
class_completion_option(c)
|
51
|
-
end +
|
52
|
-
labled_refs.uniq.collect do |r|
|
53
|
-
CompletionOption.new("#{r.name}:", "<#{r.eType.name}>")
|
54
|
-
end
|
55
|
-
elsif !context.problem
|
56
|
-
result = []
|
57
|
-
if context.feature
|
58
|
-
if context.after_label
|
59
|
-
description = "<#{context.feature.eType.name}>"
|
60
|
-
else
|
61
|
-
description = "[#{context.feature.name}] <#{context.feature.eType.name}>"
|
62
|
-
end
|
63
|
-
# value completion
|
64
|
-
if context.feature.is_a?(RGen::ECore::EAttribute) || !context.feature.containment
|
65
|
-
if context.feature.is_a?(RGen::ECore::EReference)
|
66
|
-
if ref_completion_option_provider
|
67
|
-
result += ref_completion_option_provider.call(context.feature)
|
68
|
-
else
|
69
|
-
# no options
|
70
|
-
end
|
71
|
-
elsif context.feature.eType.is_a?(RGen::ECore::EEnum)
|
72
|
-
result += context.feature.eType.eLiterals.collect do |l|
|
73
|
-
CompletionOption.new("#{l.name}", "<#{context.feature.eType.name}>")
|
74
|
-
end
|
75
|
-
elsif context.feature.eType.instanceClass == String
|
76
|
-
if @lang.unquoted?(context.feature)
|
77
|
-
result += [ CompletionOption.new("#{context.feature.name.gsub(/\W/,"")}", description) ]
|
78
|
-
else
|
79
|
-
result += [ CompletionOption.new("\"\"", description) ]
|
80
|
-
end
|
81
|
-
elsif context.feature.eType.instanceClass == Integer
|
82
|
-
result += (0..0).collect{|i| CompletionOption.new("#{i}", description) }
|
83
|
-
elsif context.feature.eType.instanceClass == Float
|
84
|
-
result += (0..0).collect{|i| CompletionOption.new("#{i}.0", description) }
|
85
|
-
elsif context.feature.eType.instanceClass == RGen::MetamodelBuilder::DataTypes::Boolean
|
86
|
-
result += [true, false].collect{|b| CompletionOption.new("#{b}", description) }
|
87
|
-
else
|
88
|
-
# no options
|
89
|
-
end
|
90
|
-
else
|
91
|
-
# containment reference, ignore
|
92
|
-
end
|
93
|
-
end
|
94
|
-
if !context.after_label
|
95
|
-
# label completion
|
96
|
-
result += @lang.labled_arguments(clazz).
|
97
|
-
select{|f|
|
98
|
-
!context.element.eIsSet(f.name)}.collect do |f|
|
99
|
-
CompletionOption.new("#{f.name}:", "<#{f.eType.name}>")
|
100
|
-
end
|
101
|
-
end
|
102
|
-
result
|
103
|
-
else
|
104
|
-
# missing comma, after curly brace, etc.
|
105
|
-
[]
|
106
|
-
end
|
107
|
-
elsif context
|
108
|
-
# root classes
|
109
|
-
@lang.root_classes.
|
110
|
-
sort{|a,b| a.name <=> b.name}.collect do |c|
|
111
|
-
class_completion_option(c)
|
112
|
-
end
|
113
|
-
else
|
114
|
-
[]
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
private
|
119
|
-
|
120
|
-
def class_completion_option(eclass)
|
121
|
-
uargs = @lang.unlabled_arguments(eclass).collect{|a| "<#{a.name}>"}.join(", ")
|
122
|
-
CompletionOption.new(@lang.command_by_class(eclass.instanceClass), uargs)
|
123
|
-
end
|
124
|
-
|
125
|
-
end
|
126
|
-
|
127
|
-
end
|
128
|
-
|