metaruby 1.0.0 → 2.0.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.
- checksums.yaml +4 -4
- data/.travis.yml +6 -3
- data/Gemfile +6 -0
- data/Rakefile +12 -2
- data/lib/metaruby.rb +2 -0
- data/lib/metaruby/attributes.rb +52 -60
- data/lib/metaruby/backward/singleton_class_p.rb +14 -0
- data/lib/metaruby/dsls.rb +31 -1
- data/lib/metaruby/dsls/doc.rb +33 -25
- data/lib/metaruby/dsls/find_through_method_missing.rb +78 -16
- data/lib/metaruby/gui.rb +1 -0
- data/lib/metaruby/gui/html/exception_view.css +4 -4
- data/lib/metaruby/gui/html/page_body.rhtml +0 -3
- data/lib/metaruby/gui/model_browser.rb +35 -20
- data/lib/metaruby/gui/model_hierarchy.rb +267 -0
- data/lib/metaruby/gui/model_selector.rb +63 -40
- data/lib/metaruby/model_as_class.rb +9 -13
- data/lib/metaruby/model_as_module.rb +2 -5
- data/lib/metaruby/registration.rb +25 -19
- data/lib/metaruby/test.rb +3 -0
- data/lib/metaruby/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4a39a36eff3dfcc3885b69729b7fc1f20d08803
|
4
|
+
data.tar.gz: 2d6a47cba4d1e6658aabd7a54f682d62e9cfc7c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ef497f6483f83756ede50becd59106c9bd5c87700172fb1de2090bfe9e0ee56317c50a0e4c6e7d9ee71a8a74e3d497a23bcb76bd8c15572c5ab1a1f27947e66
|
7
|
+
data.tar.gz: 32ed5a1675c2598bdba4690ab9214bfe39b5c4125e04b0a825f2513cedaceb5a4297bab53a1393e5a0fe910143ea53efebc5cc11e9792830e66525f58be2dff5
|
data/.travis.yml
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
-
- 2.0.0
|
5
4
|
- 2.1.6
|
6
5
|
- 2.2.2
|
7
|
-
- 2.3.
|
8
|
-
-
|
6
|
+
- 2.3.3
|
7
|
+
- 2.4.1
|
8
|
+
- jruby-9.1.13.0
|
9
9
|
script:
|
10
10
|
- bundle exec rake
|
11
11
|
- bundle exec rake test
|
12
|
+
allow_failures:
|
13
|
+
- rvm: jruby-9.1.13.0
|
14
|
+
bundler_args: --without gui
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -3,11 +3,21 @@ require "rake/testtask"
|
|
3
3
|
|
4
4
|
task :default
|
5
5
|
|
6
|
+
has_gui = begin
|
7
|
+
require 'Qt'
|
8
|
+
true
|
9
|
+
rescue LoadError
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
6
13
|
Rake::TestTask.new(:test) do |t|
|
7
14
|
t.libs << "lib"
|
8
15
|
t.libs << "."
|
9
|
-
|
10
|
-
|
16
|
+
|
17
|
+
file_list = FileList['test/**/test_*.rb']
|
18
|
+
if !has_gui
|
19
|
+
file_list.exclude('test/gui/**/test_*.rb')
|
20
|
+
end
|
11
21
|
end
|
12
22
|
|
13
23
|
task :gem => :build
|
data/lib/metaruby.rb
CHANGED
data/lib/metaruby/attributes.rb
CHANGED
@@ -23,8 +23,6 @@ module MetaRuby
|
|
23
23
|
# @example promotion to update back references
|
24
24
|
# class Port; attr_accessor :component_model end
|
25
25
|
# class Component
|
26
|
-
# inherited_attribute(:ports, :port, map: true) { Hash.new }
|
27
|
-
#
|
28
26
|
# # Update #component_model to make it point to the receiver instead
|
29
27
|
# # of the original model. Note that metaruby does not memoize the
|
30
28
|
# # result, so it has to be done in the promote method if it is
|
@@ -34,6 +32,8 @@ module MetaRuby
|
|
34
32
|
# port.component_model = self
|
35
33
|
# port
|
36
34
|
# end
|
35
|
+
#
|
36
|
+
# inherited_attribute(:ports, :port, map: true) { Hash.new }
|
37
37
|
# end
|
38
38
|
module Attributes
|
39
39
|
def included(mod)
|
@@ -72,6 +72,21 @@ module MetaRuby
|
|
72
72
|
nil
|
73
73
|
end
|
74
74
|
|
75
|
+
ANCESTORS_ACCESS =
|
76
|
+
if RUBY_VERSION < "2.1.0"
|
77
|
+
<<-EOCODE
|
78
|
+
ancestors = self.ancestors
|
79
|
+
if ancestors.first != self
|
80
|
+
ancestors.unshift self
|
81
|
+
end
|
82
|
+
EOCODE
|
83
|
+
else
|
84
|
+
<<-EOCODE
|
85
|
+
ancestors = self.ancestors
|
86
|
+
EOCODE
|
87
|
+
end
|
88
|
+
|
89
|
+
|
75
90
|
# @api private
|
76
91
|
#
|
77
92
|
# Helper method for {#inherited_single_value_attribute} in case there
|
@@ -79,10 +94,7 @@ module MetaRuby
|
|
79
94
|
def define_single_value_without_promotion(method_name, ivar)
|
80
95
|
class_eval <<-EOF, __FILE__, __LINE__+1
|
81
96
|
def #{method_name}
|
82
|
-
|
83
|
-
if ancestors.first != self
|
84
|
-
ancestors.unshift self
|
85
|
-
end
|
97
|
+
#{ANCESTORS_ACCESS}
|
86
98
|
|
87
99
|
has_value = false
|
88
100
|
for klass in ancestors
|
@@ -118,10 +130,7 @@ module MetaRuby
|
|
118
130
|
def define_single_value_with_promotion(method_name, promotion_method_name, ivar)
|
119
131
|
class_eval <<-EOF, __FILE__, __LINE__+1
|
120
132
|
def #{method_name}
|
121
|
-
|
122
|
-
if ancestors.first != self
|
123
|
-
ancestors.unshift self
|
124
|
-
end
|
133
|
+
#{ANCESTORS_ACCESS}
|
125
134
|
|
126
135
|
promotions = []
|
127
136
|
for klass in ancestors
|
@@ -130,7 +139,7 @@ module MetaRuby
|
|
130
139
|
value = klass.instance_variable_get(:#{ivar})
|
131
140
|
break
|
132
141
|
end
|
133
|
-
promotions.unshift(klass) if klass.respond_to?(
|
142
|
+
promotions.unshift(klass) if klass.respond_to?(:#{promotion_method_name})
|
134
143
|
end
|
135
144
|
if !has_value && respond_to?(:#{method_name}_default)
|
136
145
|
# Look for default
|
@@ -281,13 +290,10 @@ module MetaRuby
|
|
281
290
|
nil
|
282
291
|
end
|
283
292
|
def has_#{name}?(key)
|
284
|
-
|
285
|
-
if ancestors.first != self
|
286
|
-
ancestors.unshift self
|
287
|
-
end
|
293
|
+
#{ANCESTORS_ACCESS}
|
288
294
|
for klass in ancestors
|
289
|
-
if klass.
|
290
|
-
return true if
|
295
|
+
if attr = klass.instance_variable_get(:@#{attribute_name})
|
296
|
+
return true if attr.has_key?(key)
|
291
297
|
end
|
292
298
|
end
|
293
299
|
false
|
@@ -305,8 +311,8 @@ module MetaRuby
|
|
305
311
|
def clear_#{attribute_name}
|
306
312
|
#{attribute_name}.clear
|
307
313
|
for klass in ancestors
|
308
|
-
if klass.
|
309
|
-
|
314
|
+
if attr = klass.instance_variable_get(:@#{attribute_name})
|
315
|
+
attr.clear
|
310
316
|
end
|
311
317
|
end
|
312
318
|
end
|
@@ -338,23 +344,20 @@ module MetaRuby
|
|
338
344
|
return enum_for(:each_#{name}, key, uniq)
|
339
345
|
end
|
340
346
|
|
341
|
-
|
342
|
-
if ancestors.first != self
|
343
|
-
ancestors.unshift self
|
344
|
-
end
|
347
|
+
#{ANCESTORS_ACCESS}
|
345
348
|
if key
|
346
349
|
for klass in ancestors
|
347
|
-
if klass.
|
348
|
-
if
|
349
|
-
yield(
|
350
|
+
if attr = klass.instance_variable_get(:@#{attribute_name})
|
351
|
+
if attr.has_key?(key)
|
352
|
+
yield(attr[key])
|
350
353
|
return self if uniq
|
351
354
|
end
|
352
355
|
end
|
353
356
|
end
|
354
357
|
elsif !uniq
|
355
358
|
for klass in ancestors
|
356
|
-
if klass.
|
357
|
-
|
359
|
+
if attr = klass.instance_variable_get(:@#{attribute_name})
|
360
|
+
attr.#{enum_with} do |el|
|
358
361
|
yield(el)
|
359
362
|
end
|
360
363
|
end
|
@@ -362,8 +365,8 @@ module MetaRuby
|
|
362
365
|
else
|
363
366
|
seen = Set.new
|
364
367
|
for klass in ancestors
|
365
|
-
if klass.
|
366
|
-
|
368
|
+
if attr = klass.instance_variable_get(:@#{attribute_name})
|
369
|
+
attr.#{enum_with} do |el_key, el|
|
367
370
|
if !seen.include?(el_key)
|
368
371
|
seen << el_key
|
369
372
|
#{if yield_key then 'yield(el_key, el)' else 'yield(el)' end}
|
@@ -386,17 +389,12 @@ module MetaRuby
|
|
386
389
|
def self.nomap_without_promotion(name, attribute_name, enum_with: :each)
|
387
390
|
code, file, line =<<-EOF, __FILE__, __LINE__+1
|
388
391
|
def each_#{name}
|
389
|
-
if !block_given?
|
390
|
-
return enum_for(:each_#{name})
|
391
|
-
end
|
392
|
+
return enum_for(__method__) if !block_given?
|
392
393
|
|
393
|
-
|
394
|
-
if ancestors.first != self
|
395
|
-
ancestors.unshift self
|
396
|
-
end
|
394
|
+
#{ANCESTORS_ACCESS}
|
397
395
|
for klass in ancestors
|
398
|
-
if klass.
|
399
|
-
|
396
|
+
if attr = klass.instance_variable_get(:@#{attribute_name})
|
397
|
+
attr.#{enum_with} { |el| yield(el) }
|
400
398
|
end
|
401
399
|
end
|
402
400
|
self
|
@@ -416,16 +414,13 @@ module MetaRuby
|
|
416
414
|
return enum_for(:each_#{name}, key, uniq)
|
417
415
|
end
|
418
416
|
|
419
|
-
|
420
|
-
if ancestors.first != self
|
421
|
-
ancestors.unshift self
|
422
|
-
end
|
417
|
+
#{ANCESTORS_ACCESS}
|
423
418
|
if key
|
424
419
|
promotions = []
|
425
420
|
for klass in ancestors
|
426
|
-
if klass.
|
427
|
-
if
|
428
|
-
value =
|
421
|
+
if attr = klass.instance_variable_get(:@#{attribute_name})
|
422
|
+
if attr.has_key?(key)
|
423
|
+
value = attr[key]
|
429
424
|
for p in promotions
|
430
425
|
value = p.promote_#{name}(key, value)
|
431
426
|
end
|
@@ -433,27 +428,27 @@ module MetaRuby
|
|
433
428
|
return self if uniq
|
434
429
|
end
|
435
430
|
end
|
436
|
-
promotions.unshift(klass) if klass.respond_to?(
|
431
|
+
promotions.unshift(klass) if klass.respond_to?(:promote_#{name})
|
437
432
|
end
|
438
433
|
elsif !uniq
|
439
434
|
promotions = []
|
440
435
|
for klass in ancestors
|
441
|
-
if klass.
|
442
|
-
|
436
|
+
if attr = klass.instance_variable_get(:@#{attribute_name})
|
437
|
+
attr.#{enum_with} do |k, v|
|
443
438
|
for p in promotions
|
444
439
|
v = p.promote_#{name}(k, v)
|
445
440
|
end
|
446
441
|
#{if yield_key then 'yield(k, v)' else 'yield(v)' end}
|
447
442
|
end
|
448
443
|
end
|
449
|
-
promotions.unshift(klass) if klass.respond_to?(
|
444
|
+
promotions.unshift(klass) if klass.respond_to?(:promote_#{name})
|
450
445
|
end
|
451
446
|
else
|
452
447
|
seen = Set.new
|
453
448
|
promotions = []
|
454
449
|
for klass in ancestors
|
455
|
-
if klass.
|
456
|
-
|
450
|
+
if attr = klass.instance_variable_get(:@#{attribute_name})
|
451
|
+
attr.#{enum_with} do |k, v|
|
457
452
|
unless seen.include?(k)
|
458
453
|
for p in promotions
|
459
454
|
v = p.promote_#{name}(k, v)
|
@@ -463,7 +458,7 @@ module MetaRuby
|
|
463
458
|
end
|
464
459
|
end
|
465
460
|
end
|
466
|
-
promotions.unshift(klass) if klass.respond_to?(
|
461
|
+
promotions.unshift(klass) if klass.respond_to?(:promote_#{name})
|
467
462
|
end
|
468
463
|
end
|
469
464
|
self
|
@@ -483,21 +478,18 @@ module MetaRuby
|
|
483
478
|
return enum_for(:each_#{name})
|
484
479
|
end
|
485
480
|
|
486
|
-
|
487
|
-
if ancestors.first != self
|
488
|
-
ancestors.unshift self
|
489
|
-
end
|
481
|
+
#{ANCESTORS_ACCESS}
|
490
482
|
promotions = []
|
491
483
|
for klass in ancestors
|
492
|
-
if klass.
|
493
|
-
|
484
|
+
if attr = klass.instance_variable_get(:@#{attribute_name})
|
485
|
+
attr.#{enum_with} do |value|
|
494
486
|
for p in promotions
|
495
487
|
value = p.promote_#{name}(value)
|
496
488
|
end
|
497
489
|
yield(value)
|
498
490
|
end
|
499
491
|
end
|
500
|
-
promotions.unshift(klass) if klass.respond_to?(
|
492
|
+
promotions.unshift(klass) if klass.respond_to?(:promote_#{name})
|
501
493
|
end
|
502
494
|
self
|
503
495
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Module
|
2
|
+
if !method_defined?(:singleton_class?)
|
3
|
+
# It so happens that this method to determine whether a class is a
|
4
|
+
# singleton class is valid for ruby 2.0 and breaks on 2.1 ... However
|
5
|
+
# (!) on 2.1 singleton_class? is defined
|
6
|
+
def singleton_class?
|
7
|
+
if instance_variable_defined?(:@__singleton_class)
|
8
|
+
@__singleton_class
|
9
|
+
else
|
10
|
+
@__singleton_class = (ancestors.first != self)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/metaruby/dsls.rb
CHANGED
@@ -2,7 +2,37 @@ require 'metaruby/dsls/doc'
|
|
2
2
|
require 'metaruby/dsls/find_through_method_missing'
|
3
3
|
|
4
4
|
module MetaRuby
|
5
|
-
#
|
5
|
+
# DSLs-related tools
|
6
|
+
#
|
7
|
+
# == Find through method missing
|
8
|
+
#
|
9
|
+
# The find through method missing functionality is meant to allow classes to
|
10
|
+
# turn objects that can be found (with a method that finds an object by its
|
11
|
+
# name) into an attribute call as e.g.
|
12
|
+
#
|
13
|
+
# task.test_event # => task.find_event("test")
|
14
|
+
#
|
15
|
+
# See {DSLs::FindThroughMethodMissing} for a complete description
|
16
|
+
#
|
17
|
+
# == Documentation parsing
|
18
|
+
#
|
19
|
+
# This provides the logic to find a documentation block above a DSL-like
|
20
|
+
# object creation. For instance, given a class that looks like
|
21
|
+
#
|
22
|
+
# class Task
|
23
|
+
# def event(name) # creates an event object with the given name
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# Used in a DSL context like so:
|
28
|
+
#
|
29
|
+
# # The test event allows us
|
30
|
+
# #
|
31
|
+
# # To provide an example
|
32
|
+
# event 'test'
|
33
|
+
#
|
34
|
+
# The parse_documentation method allows to extract the comment block above
|
35
|
+
# the 'event' call. See {DSLs.parse_documentation} for more information
|
6
36
|
module DSLs
|
7
37
|
end
|
8
38
|
end
|
data/lib/metaruby/dsls/doc.rb
CHANGED
@@ -10,21 +10,34 @@ module MetaRuby
|
|
10
10
|
# the element whose documentation we are looking for.
|
11
11
|
# @return [String,nil] the parsed documentation, or nil if there is no
|
12
12
|
# documentation
|
13
|
+
#
|
14
|
+
# @example find the documentation block of an event creation
|
15
|
+
# # assuming the following toplevel DSL code in a file called test.orogen
|
16
|
+
# task "Task" do
|
17
|
+
# # Just an example event
|
18
|
+
# event "test"
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# # One would use the following code to extract the documentation
|
22
|
+
# # above the test event declaration. The call must be made within the
|
23
|
+
# # event creation code
|
24
|
+
# MetaRuby::DSLs.parse_documentation_block(/test\.orogen$/, "event")
|
25
|
+
#
|
13
26
|
def self.parse_documentation_block(file_match, trigger_method = /.*/)
|
14
27
|
last_method_matched = false
|
15
|
-
|
28
|
+
caller_locations(1).each do |call|
|
16
29
|
this_method_matched =
|
17
|
-
if trigger_method === call
|
30
|
+
if trigger_method === call.label
|
18
31
|
true
|
19
|
-
elsif call
|
32
|
+
elsif call.label == 'method_missing'
|
20
33
|
last_method_matched
|
21
34
|
else
|
22
35
|
false
|
23
36
|
end
|
24
37
|
|
25
|
-
if !this_method_matched && last_method_matched && (file_match === call
|
26
|
-
if File.file?(call
|
27
|
-
return parse_documentation_block_at(call
|
38
|
+
if !this_method_matched && last_method_matched && (file_match === call.absolute_path)
|
39
|
+
if File.file?(call.absolute_path)
|
40
|
+
return parse_documentation_block_at(call.absolute_path, call.lineno)
|
28
41
|
else return
|
29
42
|
end
|
30
43
|
end
|
@@ -47,31 +60,26 @@ module MetaRuby
|
|
47
60
|
# Lines are given 1-based (as all editors work that way), and we
|
48
61
|
# want the line before the definition. Remove two
|
49
62
|
line = line - 2
|
63
|
+
|
64
|
+
space_count = nil
|
50
65
|
while true
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
66
|
+
l = lines[line]
|
67
|
+
comment_match = /^\s*#/.match(l)
|
68
|
+
if comment_match
|
69
|
+
comment_line = comment_match.post_match.rstrip
|
70
|
+
stripped_line = comment_line.lstrip
|
71
|
+
leading_spaces = comment_line.size - stripped_line.size
|
72
|
+
if !stripped_line.empty? && (!space_count || space_count > leading_spaces)
|
73
|
+
space_count = leading_spaces
|
74
|
+
end
|
75
|
+
block.unshift(comment_line)
|
56
76
|
else break
|
57
77
|
end
|
58
78
|
line = line - 1
|
59
79
|
end
|
60
|
-
block = block.map do |l|
|
61
|
-
l.strip.gsub(/^\s*#/, '')
|
62
|
-
end
|
63
|
-
# Now remove the same amount of spaces in front of each lines
|
64
|
-
space_count = block.map do |l|
|
65
|
-
l =~ /^(\s*)/
|
66
|
-
if $1.size != l.size
|
67
|
-
$1.size
|
68
|
-
end
|
69
|
-
end.compact.min
|
70
|
-
block = block.map do |l|
|
71
|
-
l[space_count..-1]
|
72
|
-
end
|
73
80
|
if !block.empty?
|
74
|
-
|
81
|
+
space_count ||= 0
|
82
|
+
block.map { |l| l[space_count..-1] }.join("\n")
|
75
83
|
end
|
76
84
|
end
|
77
85
|
end
|