rtext 0.5.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|