rtext 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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,125 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
2
+
3
+ require 'test/unit'
4
+ require 'rtext/tokenizer'
5
+ require 'rtext/generic'
6
+
7
+ class TokenizerTest < Test::Unit::TestCase
8
+ include RText::Tokenizer
9
+
10
+ def test_simple
11
+ assert_tokens [
12
+ Token.new(:identifier, "TestNode", 1, 1, 8),
13
+ Token.new(:integer, 1, 1, 10, 10),
14
+ Token.new(",", nil, 1, 11, 11),
15
+ Token.new(:identifier, "bla", 1, 13, 15),
16
+ Token.new(",", nil, 1, 16, 16),
17
+ Token.new(:float, 0.4, 1, 18, 20),
18
+ Token.new(",", nil, 1, 21, 21),
19
+ Token.new(:label, "label", 1, 23, 28),
20
+ Token.new(:integer, 4, 1, 30, 30),
21
+ Token.new(",", nil, 1, 31, 31),
22
+ Token.new(:string, "string", 1, 33, 40),
23
+ Token.new(:newline, nil, 1, nil, nil)
24
+ ], "TestNode 1, bla, 0.4, label: 4, \"string\""
25
+ end
26
+
27
+ def test_more
28
+ assert_tokens [
29
+ Token.new(:identifier, "TestNode", 1, 1, 8),
30
+ Token.new(:boolean, true, 1, 10, 13),
31
+ Token.new(",", nil, 1, 14, 14),
32
+ Token.new(:integer, 0xfaa, 1, 16, 20),
33
+ Token.new(:integer, -3, 1, 22, 23),
34
+ Token.new(:reference, "/a/b", 1, 25, 28),
35
+ Token.new(:newline, nil, 1, nil, nil)
36
+ ], <<-END
37
+ TestNode true, 0xfaa -3 /a/b
38
+ END
39
+ end
40
+
41
+ def test_comments_and_annotation
42
+ assert_tokens [
43
+ Token.new(:comment, " comment", 1, 1, 9),
44
+ Token.new(:newline, nil, 1, nil, nil),
45
+ Token.new(:annotation, " annotation", 2, 1, 12),
46
+ Token.new(:newline, nil, 2, nil, nil),
47
+ Token.new(:identifier, "TestNode", 3, 1, 8),
48
+ Token.new(:comment, "comment2", 3, 10, 18),
49
+ Token.new(:newline, nil, 3, nil, nil)
50
+ ], <<-END
51
+ # comment
52
+ @ annotation
53
+ TestNode #comment2
54
+ END
55
+ end
56
+
57
+ def test_generic
58
+ tokens = do_tokenize("<name>")
59
+ assert_equal :generic, tokens.first.kind
60
+ assert_equal "name", tokens.first.value.string
61
+ assert_equal 1, tokens.first.line
62
+ assert_equal 1, tokens.first.scol
63
+ assert_equal 6, tokens.first.ecol
64
+ end
65
+
66
+ def test_generic_bad
67
+ tokens = do_tokenize("<a>b>")
68
+ assert_equal :generic, tokens.first.kind
69
+ assert_equal "a", tokens.first.value.string
70
+ assert_equal 1, tokens.first.line
71
+ assert_equal 1, tokens.first.scol
72
+ assert_equal 3, tokens.first.ecol
73
+ assert_equal :identifier, tokens[1].kind
74
+ assert_equal :error, tokens[2].kind
75
+ end
76
+
77
+ def test_generic_percent
78
+ tokens = do_tokenize("<%name%>")
79
+ assert_equal :generic, tokens.first.kind
80
+ assert_equal "name", tokens.first.value.string
81
+ assert_equal 1, tokens.first.line
82
+ assert_equal 1, tokens.first.scol
83
+ assert_equal 8, tokens.first.ecol
84
+ end
85
+
86
+ def test_generic_percent_angle_close
87
+ tokens = do_tokenize("<% a > b < c %>")
88
+ assert_equal :generic, tokens.first.kind
89
+ assert_equal " a > b < c ", tokens.first.value.string
90
+ assert_equal 1, tokens.first.line
91
+ assert_equal 1, tokens.first.scol
92
+ assert_equal 15, tokens.first.ecol
93
+ end
94
+
95
+ def test_generic_percent_bad
96
+ tokens = do_tokenize("<%= a %> b %>")
97
+ assert_equal :generic, tokens.first.kind
98
+ assert_equal "= a ", tokens.first.value.string
99
+ assert_equal 1, tokens.first.line
100
+ assert_equal 1, tokens.first.scol
101
+ assert_equal 8, tokens.first.ecol
102
+ assert_equal :identifier, tokens[1].kind
103
+ assert_equal :error, tokens[2].kind
104
+ end
105
+
106
+ def test_error
107
+ assert_tokens [
108
+ Token.new(:error, "\"open", 1, 1, 5),
109
+ Token.new(:newline, nil, 1, nil, nil)
110
+ ], <<-END
111
+ "open
112
+ END
113
+ end
114
+
115
+ def do_tokenize(str)
116
+ tokenize(str, /\A\/[\/\w]+/)
117
+ end
118
+
119
+ def assert_tokens(expected, str)
120
+ tokens = tokenize(str, /\A\/[\/\w]+/)
121
+ assert_equal(expected, tokens)
122
+ end
123
+
124
+ end
125
+
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.0
4
+ version: 0.5.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: 2012-10-09 00:00:00.000000000 Z
12
+ date: 2012-12-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rgen
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 0.6.0
21
+ version: 0.6.1
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,46 +26,72 @@ dependencies:
26
26
  requirements:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
- version: 0.6.0
29
+ version: 0.6.1
30
30
  description: RText can be used to derive textual languages from an RGen metamodel
31
31
  with very little effort.
32
32
  email: martin dot thiede at gmx de
33
33
  executables: []
34
34
  extensions: []
35
35
  extra_rdoc_files:
36
- - README
36
+ - README.rdoc
37
37
  - CHANGELOG
38
38
  - MIT-LICENSE
39
39
  - RText_Users_Guide
40
- - RText_Plugin_Implementation_Guide
40
+ - RText_Protocol
41
41
  files:
42
42
  - lib/rtext/completer.rb
43
43
  - lib/rtext/context_builder.rb
44
44
  - lib/rtext/default_loader.rb
45
45
  - lib/rtext/default_service_provider.rb
46
+ - lib/rtext/frontend/config.rb
47
+ - lib/rtext/frontend/connector.rb
48
+ - lib/rtext/frontend/connector_manager.rb
49
+ - lib/rtext/frontend/context.rb
50
+ - lib/rtext/generic.rb
46
51
  - lib/rtext/instantiator.rb
47
52
  - lib/rtext/language.rb
53
+ - lib/rtext/link_detector.rb
54
+ - lib/rtext/message_helper.rb
48
55
  - lib/rtext/parser.rb
49
56
  - lib/rtext/serializer.rb
50
57
  - lib/rtext/service.rb
51
- - lib/rtext_plugin/connection_manager.rb
58
+ - lib/rtext/tokenizer.rb
52
59
  - test/completer_test.rb
53
60
  - test/context_builder_test.rb
54
61
  - test/instantiator_test.rb
62
+ - test/integration/backend.out
63
+ - test/integration/crash_on_request_editor.rb
64
+ - test/integration/ecore_editor.rb
65
+ - test/integration/frontend.log
66
+ - test/integration/model/invalid_encoding.invenc
67
+ - test/integration/model/test.crashing_backend
68
+ - test/integration/model/test.crash_on_request
69
+ - test/integration/model/test.dont_open_socket
70
+ - test/integration/model/test.invalid_cmd_line
71
+ - test/integration/model/test.not_in_rtext
72
+ - test/integration/model/test_large_with_errors.ect3
73
+ - test/integration/model/test_metamodel.ect
74
+ - test/integration/model/test_metamodel2.ect
75
+ - test/integration/model/test_metamodel_error.ect2
76
+ - test/integration/model/test_metamodel_ok.ect2
77
+ - test/integration/test.rb
78
+ - test/link_detector_test.rb
79
+ - test/message_helper_test.rb
55
80
  - test/rtext_test.rb
56
81
  - test/serializer_test.rb
57
- - README
82
+ - test/tokenizer_test.rb
83
+ - README.rdoc
58
84
  - CHANGELOG
59
85
  - MIT-LICENSE
60
86
  - RText_Users_Guide
61
- - RText_Plugin_Implementation_Guide
87
+ - RText_Protocol
62
88
  - Rakefile
63
89
  homepage: http://ruby-gen.org
64
90
  licenses: []
65
91
  post_install_message:
66
92
  rdoc_options:
67
93
  - --main
68
- - README
94
+ - README.rdoc
69
95
  - -x
70
96
  - test
71
97
  require_paths:
@@ -1,268 +0,0 @@
1
- =RText Plugin Implementation Guide
2
-
3
- RText editors consist of a frontend and a backend. Most of the logic is implemented
4
- within the backend while the frontend is kept as thin as possible. This should simplify
5
- the task of writing a frontend and promote development of RText frontends for different
6
- editing environments.
7
-
8
- This guide explains how to build a RText frontend which will typically be a plugin for an
9
- existing editor.
10
-
11
-
12
- ==Plugin Responsibilies
13
-
14
- Here is a rough overview of what a RText plugin has to do:
15
-
16
- * find the .rtext config file for a given RText model file
17
- * start the corresponding backend process if not started already
18
- * provide a way to reload the model and issue the refresh command to the backend
19
- * implement syntax highlighting for the generic RText syntax
20
- * forward auto completion requests to the backend, let the user choose from the returned options
21
- and insert the option chosen
22
- * forward element search requests to the backend, let the user choose from the matched elements
23
- and jump to the element chosen
24
- * forward reference target requests to the backend, let the user choose from the targets found
25
- and jump to the target chosen
26
- * query the backend for model problems and display them to the user
27
- * stop the backend process when it's no longer needed
28
-
29
-
30
- ==Plugin Implementation Hints
31
-
32
- The plugin implementation could include the following entities.
33
-
34
- ===Command
35
-
36
- A command issued by the plugin and sent to the backend service. See the section about the
37
- Frontend/Backend Communication Protocol below for details about available commands.
38
-
39
-
40
- ===Connector
41
-
42
- A connector represents the connection to a running backend process.
43
- Each connector/process is associated with a specific .rtext file and a specific service specification
44
- within this file. See the RText Users Guide for details about the .rtext config file.
45
-
46
- When the backend service is started, it outputs the UDP port it is listening on. The connector
47
- should use this port to send commands to the backend.
48
-
49
- The connector should send commands to the backend. It should assign invocation ids and keep the
50
- invocation until a response is received or a timeout has occured.
51
-
52
- When the backend responds, the connector should associate the response packages with the previous
53
- request using the invocation id. It should also join fragmented response packages and send an
54
- internal notification when a response has been fully received.
55
-
56
-
57
- ===Connector Manager
58
-
59
- The connector manager should be able to return a connector for a given RText model file.
60
-
61
- It needs to identify the backend process to which to connect by means of the .rtext config file and
62
- a contained service specification (one .rtext files may contain service specifications for starting
63
- different backend services depending on the model file name).
64
-
65
- For this, it needs to find the first .rtext config file containing a service specification matching
66
- the given RText model file name. See the RText Users guide for details about the .rtext config file
67
- and the way how they are found in the filesystem.
68
-
69
- Once the .rtext file/service specification is found it can be used as a key for a lookup for
70
- already established connections. The plugin should avoid starting the same process twice. All
71
- RText model files with the same file extension and belonging to the same .rtext file should
72
- use the same process.
73
-
74
- The process should be kept running as long as editing is in progress. This will greatly
75
- reduce response times as the model can be kept in memory and only the changed parts need
76
- to be reloaded.
77
-
78
- When the plugin lifecycle ends, the connector manager should send the "stop" command to the
79
- backend processes.
80
-
81
-
82
- ==Frontend/Backend Communication Protocol
83
-
84
- Communication takes place via plain text transmitted via UDP. There are requests by
85
- the frontend and responses by the backend. In both cases the text is interpreted as
86
- a set of lines (separated by \n or \r\n).
87
-
88
-
89
- ===Request
90
-
91
- The request consists of a command id, an invocation id and the command parameters.
92
- The invocation id is repeated within the response to allow proper association with the
93
- request. Command parameters are command specific (see below).
94
-
95
- Requests can not span more than one UDP package and thus are limited to the UDP payload size.
96
-
97
- line 1: <command id>
98
- line 2: <invocation id>
99
- line 3..n: <command parameters>
100
-
101
-
102
- ===Response
103
-
104
- Each response contains the invocation id of the request in the first line.
105
- Since it could be splitted over several UDP packages it contains an indication
106
- in the second line if more packages are following ("more") or this is the last package
107
- ("last"). The rest of the response is a fragment of the command result data. All fragments
108
- of a set of response packages with the same invocation id need to be joined.
109
-
110
- Note that there are no mechanisms to protect agains package loss or reordering since
111
- this protocol is intended to be used on local socket connections only.
112
-
113
- line 1: <invocation id>
114
- line 2: "more" | "last"
115
- line 3..n: <command result data>
116
-
117
-
118
- ===Command: Refresh
119
-
120
- The refresh command tells the backend to reload the model from the file system. Frontends
121
- could issue this command after a model file has been changed in the file system or on
122
- an explicit user request.
123
-
124
- Request Format:
125
- command id: "refresh"
126
- no parameters
127
-
128
- Response Format:
129
- no result data
130
-
131
-
132
- ===Command: Complete
133
-
134
- This command is a request by the frontend to show auto completion options at a given
135
- location within a file. The location is expressed using a set of context lines and the cursor
136
- column position in the current line.
137
-
138
- Context lines are lines from an RText file which contain a (context) command and all
139
- the parent commands wrapped around it. Any sibling commands can be omitted as well as
140
- any lines containing closing braces and brackets. The order of lines is the same as in the RText file.
141
-
142
- Here is an example. Consider the following RText file with the cursor in the line of "Command3" at
143
- the time when the auto completion command is issued.
144
-
145
- Command1 {
146
- Command2 {
147
- role1: [
148
- Command3 <== cursor in this line
149
- Command4
150
- ]
151
- }
152
- Command5
153
- }
154
-
155
- The context lines in this case would be the following.
156
-
157
- Command1 {
158
- Command2 {
159
- role1: [
160
- Command3
161
-
162
- The current line is always the last of the context lines.
163
-
164
- Note that all siblings of the command and parent commands have been stripped off, as well as
165
- any closing braces or brackets.
166
-
167
- The purpose of this special context line format is to keep the task of extracting the
168
- context in the frontend simple and the amount of data transmitted to the backend low.
169
- It's also a way to keep the parsing time of the context low in the backend and thus to minimize
170
- the user noticable delay.
171
-
172
- Request Format:
173
- command id: "complete"
174
- param line 1: cursor column position in the current line
175
- param line 2..n: context lines
176
-
177
- Response Format:
178
- result line 1..n: <completion string>;<extra info string>
179
-
180
-
181
- ===Command: Show Problems
182
-
183
- This command is a request by the frontend to determine and return all problems present in the current model.
184
- The command implicitly reloads the model from the filesystem before checking for problems.
185
-
186
- Request Format:
187
- command id: "show_problems"
188
- no parameters
189
-
190
- Response Format:
191
- result line 1: <file name>
192
- result line 2..n <line number>;<message>
193
-
194
- Note that the file name is repeated only once for all problems within a file to reduce the amout of
195
- result data which needs to be transmitted.
196
-
197
-
198
- ===Command: Show Problems 2
199
-
200
- Since protocol version 1
201
-
202
- Like the first version but provides progress information while the model is loaded and problem severity.
203
-
204
- Request Format:
205
- command id: "show_problems2"
206
- no parameters
207
-
208
- Response Format:
209
- result line 1..n: progress:<[0..100]>
210
- result line n+1: <file name>
211
- result line n+2..m <[diwef]>;<line number>;<message>
212
-
213
- Progress is expressed by a value between 0 and 100. The backend may choose to return any number
214
- of progress lines. It should start with 0 and end with 100 and progress should not go backwards.
215
-
216
- Problem severity is expressed with one of the following flags: d (debug), i (info), w (warn), e (error), f (fatal)
217
-
218
-
219
- ===Command: Reference Targets
220
-
221
- This command is used to retrieve the targets of a given reference. The reference location is expressed
222
- by means of a set of context lines and the cursor column position in the current line. The cursor
223
- column position must be within the string representing the reference. The format of the context lines
224
- is the same as the one described with the "Complete" command (see above).
225
-
226
- Note that the service provider is free to define how a reference is represented. In particular it
227
- can interpret the command identifier as a reference and use this mechanism to show incoming references
228
- (reverse references).
229
-
230
- As references can be ambiguous, the result is a list of possible targets. Each target consists of the
231
- filename and line number of the target element as well as the text to be displayed to the user in case
232
- there are more than one targets to choose from.
233
-
234
- Request Format:
235
- command id: "get_reference_targets"
236
- param line 1: cursor column position in the current line
237
- param line 2..n: context lines
238
-
239
- Response Format:
240
- result line 1..n: <file name>;<line number>;<display name>
241
-
242
-
243
- ===Command: Find Elements
244
-
245
- This command returns a set of model elements matching a search pattern. The format of the
246
- pattern depends on the service provider. In a simple case, for example, the pattern could be the
247
- beginning of the element names.
248
-
249
- Request Format:
250
- command id: "get_elements"
251
- param line 1: <seach pattern>
252
-
253
- Response Format:
254
- result line 1..n: <display name>;<file name>;<line number>
255
-
256
-
257
- ===Command: Stop
258
-
259
- This command is normally invoked when the frontend terminates or otherwise needs to terminate
260
- the backend service. When receiving this command, the backend will terminate.
261
-
262
- Request Format:
263
- command id: "stop"
264
- no parameters
265
-
266
- Response Format:
267
- no result data
268
-