xumlidot 0.1.0 → 0.2.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/bin/xumlidot +2 -31
- data/lib/xumlidot/diagram/dot/klass.rb +25 -10
- data/lib/xumlidot/diagram/dot.rb +8 -8
- data/lib/xumlidot/diagram/shared/naming.rb +5 -4
- data/lib/xumlidot/diagram/xmi/argument.rb +7 -4
- data/lib/xumlidot/diagram/xmi/attribute.rb +5 -5
- data/lib/xumlidot/diagram/xmi/id.rb +45 -1
- data/lib/xumlidot/diagram/xmi/klass.rb +18 -19
- data/lib/xumlidot/diagram/xmi/method.rb +5 -2
- data/lib/xumlidot/diagram/xmi.rb +25 -26
- data/lib/xumlidot/diagram.rb +6 -4
- data/lib/xumlidot/directory_tree.rb +3 -1
- data/lib/xumlidot/loader.rb +49 -0
- data/lib/xumlidot/options.rb +63 -28
- data/lib/xumlidot/parsers/args.rb +17 -21
- data/lib/xumlidot/parsers/call.rb +32 -9
- data/lib/xumlidot/parsers/file.rb +0 -1
- data/lib/xumlidot/parsers/generic.rb +24 -31
- data/lib/xumlidot/parsers/klass_definition.rb +10 -7
- data/lib/xumlidot/parsers/method_signature.rb +27 -23
- data/lib/xumlidot/parsers/module_definition.rb +8 -8
- data/lib/xumlidot/parsers/scope.rb +6 -7
- data/lib/xumlidot/parsers/stack.rb +17 -9
- data/lib/xumlidot/parsers.rb +2 -1
- data/lib/xumlidot/types/argument.rb +1 -1
- data/lib/xumlidot/types/attribute.rb +1 -2
- data/lib/xumlidot/types/constant.rb +4 -4
- data/lib/xumlidot/types/constants.rb +3 -2
- data/lib/xumlidot/types/klass.rb +5 -5
- data/lib/xumlidot/types/method_signature.rb +8 -16
- data/lib/xumlidot/types/superklass.rb +4 -4
- data/lib/xumlidot/types.rb +2 -1
- data/lib/xumlidot.rb +2 -0
- data/spec/spec_helper.rb +21 -2
- metadata +38 -5
data/lib/xumlidot/options.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'optparse'
|
2
4
|
require 'optparse/time'
|
3
5
|
require 'ostruct'
|
@@ -6,16 +8,41 @@ module Xumlidot
|
|
6
8
|
OptionsError = Class.new(StandardError)
|
7
9
|
|
8
10
|
class Options
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
@options = nil
|
12
|
+
|
13
|
+
attr_accessor(*%i[
|
14
|
+
composition
|
15
|
+
debug
|
16
|
+
diagram_type
|
17
|
+
exclude
|
18
|
+
inheritance
|
19
|
+
model_name
|
20
|
+
rails
|
21
|
+
respond_to
|
22
|
+
send
|
23
|
+
sequence
|
24
|
+
split
|
25
|
+
title
|
26
|
+
usage
|
27
|
+
use_debug_ids
|
28
|
+
])
|
29
|
+
|
30
|
+
class << self
|
31
|
+
attr_accessor :options
|
32
|
+
|
33
|
+
def method_missing(method_name, *_args, &_block)
|
34
|
+
return options.public_send(method_name) if options.respond_to?(method_name)
|
35
|
+
|
36
|
+
raise OptionsError.new, "Unknown Option #{method_name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def respond_to_missing?(method_name, include_private = false)
|
40
|
+
options.respond_to?(method_name) || super
|
14
41
|
end
|
15
42
|
end
|
16
43
|
|
17
|
-
def self.parse(args)
|
18
|
-
@options =
|
44
|
+
def self.parse(args) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
45
|
+
@options = new
|
19
46
|
|
20
47
|
@options.title = 'Class Diagram'
|
21
48
|
@options.model_name = 'My Model'
|
@@ -28,77 +55,85 @@ module Xumlidot
|
|
28
55
|
@options.split = 1
|
29
56
|
@options.sequence = ''
|
30
57
|
@options.exclude = ''
|
58
|
+
@options.use_debug_ids = false
|
31
59
|
|
32
|
-
ENV.delete(
|
60
|
+
ENV.delete('XUMLIDOT_DEBUG')
|
33
61
|
|
34
62
|
opt_parser = OptionParser.new do |opts|
|
35
|
-
opts.banner =
|
63
|
+
opts.banner = 'Usage: xumlidot.rb [options]'
|
36
64
|
|
37
|
-
opts.separator
|
38
|
-
opts.separator
|
65
|
+
opts.separator ''
|
66
|
+
opts.separator 'Specific options:'
|
39
67
|
|
40
|
-
opts.on(
|
68
|
+
opts.on('-t', '--title [TEXT]', 'Title for the diagram') do |v|
|
41
69
|
@options.title = v
|
42
70
|
end
|
43
71
|
|
44
|
-
opts.on(
|
72
|
+
opts.on('-m', '--model [TEXT]', 'Model Name for the diagram') do |v|
|
45
73
|
@options.model_name = v
|
46
74
|
end
|
47
75
|
|
48
|
-
opts.on(
|
76
|
+
opts.on('-d', '--dot', 'Output diagram using dot (default)') do
|
49
77
|
@options.diagram_type = :dot
|
50
78
|
end
|
51
79
|
|
52
|
-
opts.on(
|
80
|
+
opts.on('-x', '--xmi', 'Output diagram using xmi') do
|
53
81
|
@options.diagram_type = :xmi
|
54
82
|
end
|
55
83
|
|
56
|
-
opts.on(
|
84
|
+
opts.on('-d', '--debug', 'Output debug information') do
|
57
85
|
@options.debug = true
|
58
|
-
ENV[
|
86
|
+
ENV['XUMLIDOT_DEBUG'] = '1'
|
59
87
|
end
|
60
88
|
|
61
|
-
opts.on(
|
89
|
+
opts.on('-i', '--no-inheritance', 'Output inheritance links on the diagram') do
|
62
90
|
@options.inheritance = false
|
63
91
|
end
|
64
92
|
|
65
|
-
opts.on(
|
93
|
+
opts.on('-c', '--no-composition', 'Output composition links on the diagram') do
|
66
94
|
@options.composition = false
|
67
95
|
end
|
68
96
|
|
69
|
-
opts.on(
|
97
|
+
opts.on('-r', '--rails', 'Expect a Rails application') do |v|
|
70
98
|
@options.rails = v
|
71
99
|
end
|
72
100
|
|
73
|
-
|
74
|
-
opts.on("-e", "--exclude [TEXT[", "Output usage links on the diagram") do |v|
|
101
|
+
opts.on('-e', '--exclude [TEXT]', 'Exclude directories or files by pattern') do |v|
|
75
102
|
@options.exclude = v
|
76
103
|
end
|
77
104
|
|
78
|
-
opts.on(
|
105
|
+
opts.on('-u', '--[no-]usage', 'Output usage links on the diagram') do |v|
|
79
106
|
@options.usage = v
|
80
107
|
end
|
81
|
-
opts.separator ""
|
82
108
|
|
83
|
-
opts.
|
109
|
+
opts.on('-b', '--debug-ids', 'Output from a static list of ids') do |v|
|
110
|
+
@options.use_debug_ids = v
|
111
|
+
end
|
112
|
+
|
113
|
+
opts.separator ''
|
114
|
+
opts.separator 'Common options:'
|
84
115
|
|
85
116
|
# No argument, shows at tail. This will print an options summary.
|
86
117
|
# Try it and see!
|
87
|
-
opts.on_tail(
|
118
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
88
119
|
puts opts
|
89
120
|
exit
|
90
121
|
end
|
91
122
|
|
92
123
|
# Another typical switch to print the version.
|
93
|
-
opts.on_tail(
|
124
|
+
opts.on_tail('--version', 'Show version') do
|
94
125
|
puts ::Version.join('.')
|
95
126
|
exit
|
96
127
|
end
|
97
128
|
end
|
98
129
|
|
99
130
|
opt_parser.parse!(args)
|
131
|
+
|
132
|
+
# Rather than pass the options around everywhere, lets set it as a class instance var
|
133
|
+
# TODO: Remove code passing it around everywhere
|
134
|
+
::Xumlidot::Options.options = @options
|
135
|
+
|
100
136
|
@options
|
101
137
|
end
|
102
|
-
|
103
138
|
end
|
104
139
|
end
|
@@ -9,17 +9,15 @@ module Xumlidot
|
|
9
9
|
#
|
10
10
|
# e.g. formats def method(a, b = nil)
|
11
11
|
# to a string 'a, b = nil'
|
12
|
-
#
|
13
12
|
class Args < MethodBasedSexpProcessor
|
14
|
-
|
15
13
|
def initialize(exp)
|
16
14
|
super()
|
17
15
|
|
18
16
|
@arguments = ::Xumlidot::Types::Arguments.new
|
19
17
|
|
20
|
-
process(exp)
|
21
|
-
rescue =>
|
22
|
-
|
18
|
+
process(Sexp.new.concat(exp))
|
19
|
+
rescue StandardError => _e
|
20
|
+
warn " ** bug: unable to process args #{exp} "
|
23
21
|
end
|
24
22
|
|
25
23
|
def to_s
|
@@ -34,7 +32,7 @@ module Xumlidot
|
|
34
32
|
# means we shouldn't display it and so we use the :nil
|
35
33
|
# symbol to represent an *actual assignment of nil* to
|
36
34
|
# a variable.
|
37
|
-
def process_nil(
|
35
|
+
def process_nil(_exp)
|
38
36
|
@argument.default = :nil
|
39
37
|
s()
|
40
38
|
end
|
@@ -44,7 +42,7 @@ module Xumlidot
|
|
44
42
|
s()
|
45
43
|
end
|
46
44
|
|
47
|
-
def process_hash(
|
45
|
+
def process_hash(_exp)
|
48
46
|
@argument.default = {}
|
49
47
|
s()
|
50
48
|
end
|
@@ -73,7 +71,7 @@ module Xumlidot
|
|
73
71
|
# but this is complex since it needs to be inserted into the right
|
74
72
|
# place and for that I need the namespace...which suggests this ISNT
|
75
73
|
# the place to do that. I possibly need a fake class ...
|
76
|
-
@argument.default = leader + name.map do |v|
|
74
|
+
@argument.default = leader + name.map do |v| # rubocop:disable Style/SymbolProc
|
77
75
|
v.to_s
|
78
76
|
end.to_a.join('::')
|
79
77
|
|
@@ -113,16 +111,14 @@ module Xumlidot
|
|
113
111
|
@argument.default << exp.value
|
114
112
|
when nil
|
115
113
|
@argument.default = exp.value
|
116
|
-
when Symbol
|
117
|
-
@argument.default = exp.value.to_s
|
118
|
-
when String
|
114
|
+
when Symbol, String
|
119
115
|
@argument.default = exp.value.to_s
|
120
|
-
|
121
|
-
#
|
122
|
-
|
123
|
-
#
|
124
|
-
|
125
|
-
#
|
116
|
+
# when Sexp
|
117
|
+
# binding.pry
|
118
|
+
# when Hash
|
119
|
+
# binding.pry
|
120
|
+
# else
|
121
|
+
# binding.pry
|
126
122
|
end
|
127
123
|
exp.shift
|
128
124
|
s()
|
@@ -133,8 +129,8 @@ module Xumlidot
|
|
133
129
|
@argument.name = "#{exp[0]}:"
|
134
130
|
process(exp)
|
135
131
|
s()
|
136
|
-
rescue
|
137
|
-
|
132
|
+
rescue StandardError
|
133
|
+
warn " ** bug: unable to process kwarg #{exp}; failure to parse default value?"
|
138
134
|
s()
|
139
135
|
end
|
140
136
|
|
@@ -151,8 +147,8 @@ module Xumlidot
|
|
151
147
|
|
152
148
|
@arguments << @argument
|
153
149
|
end
|
154
|
-
rescue
|
155
|
-
|
150
|
+
rescue StandardError
|
151
|
+
warn " ** bug: unable to process args #{exp}; failure to parse default value?"
|
156
152
|
end
|
157
153
|
end
|
158
154
|
end
|
@@ -17,16 +17,23 @@ module Xumlidot
|
|
17
17
|
process(exp)
|
18
18
|
|
19
19
|
return if klass.definition.nil?
|
20
|
+
|
20
21
|
klass.definition.inherited_modules << @modules
|
21
22
|
end
|
22
23
|
|
24
|
+
# rubocop:disable Metrics/AbcSize
|
25
|
+
# rubocop:disable Metrics/MethodLength
|
23
26
|
def process_call(exp)
|
24
|
-
exp.shift # remove the :call
|
27
|
+
_call = exp.shift # remove the :call
|
25
28
|
|
26
29
|
begin
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
+
shifted = exp.shift
|
31
|
+
_recv = process(shifted)
|
32
|
+
rescue StandardError => _e
|
33
|
+
# Reaching here when the shifted value is an array, hash, or iter
|
34
|
+
# one example:
|
35
|
+
# BaseMailer.view_paths = [File.join(FIXTURE_LOAD_PATH, "another.path")] + old.dup
|
36
|
+
warn " ** bug: unable to calculate reciever for #{exp}"
|
30
37
|
end
|
31
38
|
|
32
39
|
name = exp.shift
|
@@ -44,22 +51,39 @@ module Xumlidot
|
|
44
51
|
when :prepend
|
45
52
|
@modules.type = :prepend
|
46
53
|
process(args)
|
47
|
-
when :module_function
|
48
|
-
|
54
|
+
# when :module_function
|
55
|
+
# TODO: expose as an instance method on the module
|
56
|
+
# when :public_constant
|
57
|
+
# TODO:
|
49
58
|
when :attr_reader
|
50
59
|
add_attributes(args, exp, read: true)
|
51
60
|
when :attr_writer
|
52
61
|
add_attributes(args, exp, write: true)
|
53
62
|
when :attr_accessor
|
54
63
|
add_attributes(args, exp, read: true, write: true)
|
55
|
-
|
56
|
-
#
|
64
|
+
# else
|
65
|
+
# warn "CALL RECV:#{recv unless recv.nil? || recv.empty?} " \
|
66
|
+
# "NAME:#{name} ARGS:#{args unless args.nil? || args.empty?}"
|
67
|
+
end
|
68
|
+
s()
|
69
|
+
end
|
70
|
+
# rubocop:enable Metrics/AbcSize
|
71
|
+
# rubocop:enable Metrics/MethodLength
|
72
|
+
|
73
|
+
# If we have e.g a constant in the class definition which is assigned an
|
74
|
+
# array this prevents us having those constants defined as a parent
|
75
|
+
# class. See issue #30
|
76
|
+
def process_array(exp)
|
77
|
+
exp.shift # remove :array
|
78
|
+
exp.each do |element|
|
79
|
+
process_until_empty(element)
|
57
80
|
end
|
58
81
|
s()
|
59
82
|
end
|
60
83
|
|
61
84
|
def add_attributes(name, exp, read: false, write: false)
|
62
85
|
@klass.attributes << ::Xumlidot::Types::Attribute.new(name.value, read, write)
|
86
|
+
|
63
87
|
exp.each do |attribute|
|
64
88
|
@klass.attributes << ::Xumlidot::Types::Attribute.new(attribute.value, read, write)
|
65
89
|
end
|
@@ -86,7 +110,6 @@ module Xumlidot
|
|
86
110
|
process_until_empty(exp)
|
87
111
|
s()
|
88
112
|
end
|
89
|
-
|
90
113
|
end
|
91
114
|
end
|
92
115
|
end
|
@@ -5,7 +5,6 @@ require_relative '../types'
|
|
5
5
|
|
6
6
|
module Xumlidot
|
7
7
|
module Parsers
|
8
|
-
|
9
8
|
# We need a level of indirection between the actual parser
|
10
9
|
# and MethodBasedSexpProcessor since we will probably end up inheriting
|
11
10
|
# from SexpProcessor directly eventually
|
@@ -15,7 +14,7 @@ module Xumlidot
|
|
15
14
|
class Generic < MethodBasedSexpProcessor
|
16
15
|
attr_reader :constants
|
17
16
|
|
18
|
-
def initialize(string, constants = Stack::Constants.new
|
17
|
+
def initialize(string, constants = Stack::Constants.new)
|
19
18
|
@parsed = RubyParser.new.parse(string)
|
20
19
|
@constants = constants
|
21
20
|
super()
|
@@ -33,11 +32,8 @@ module Xumlidot
|
|
33
32
|
super(exp) do
|
34
33
|
Scope.public { process_until_empty(exp) } # Process the superclass with public visibility
|
35
34
|
end
|
36
|
-
rescue
|
37
|
-
|
38
|
-
STDERR.puts e.backtrace.reverse
|
39
|
-
STDERR.puts "ERROR (#process_sclass) #{e.message}"
|
40
|
-
end
|
35
|
+
rescue StandardError => e
|
36
|
+
sdebug('#process_sclass', e)
|
41
37
|
exp
|
42
38
|
end
|
43
39
|
|
@@ -52,55 +48,52 @@ module Xumlidot
|
|
52
48
|
type: Xumlidot::Types::Klass)
|
53
49
|
|
54
50
|
Scope.set_visibility
|
55
|
-
definition = definition_parser.new(exp
|
51
|
+
definition = definition_parser.new(Sexp.new.concat(exp[0..2]), @class_stack).definition
|
56
52
|
|
57
|
-
|
53
|
+
warn definition.to_s if ::Xumlidot::Options.debug == true
|
58
54
|
super(exp) do
|
59
55
|
Scope.public do
|
60
56
|
klass_or_module = type.new(definition)
|
61
57
|
@constants.add(klass_or_module)
|
62
58
|
process_until_empty(exp)
|
59
|
+
@constants.pop_last_added
|
63
60
|
end
|
64
61
|
end
|
65
|
-
rescue
|
66
|
-
|
67
|
-
STDERR.puts e.backtrace.reverse
|
68
|
-
STDERR.puts "ERROR (#process_class) #{e.message}"
|
69
|
-
end
|
62
|
+
rescue StandardError => e
|
63
|
+
sdebug('#process_class', e)
|
70
64
|
exp
|
71
65
|
end
|
72
66
|
|
73
67
|
# METHODS & METHOD SIGNATURES
|
74
|
-
def process_defn(exp, superclass_method
|
75
|
-
method = ::Xumlidot::Parsers::MethodSignature.new(exp, superclass_method || @sclass.last)
|
68
|
+
def process_defn(exp, superclass_method: false)
|
69
|
+
method = ::Xumlidot::Parsers::MethodSignature.new(exp, superclass_method: superclass_method || @sclass.last)
|
76
70
|
@constants.last_added.add_method(method)
|
77
|
-
|
78
|
-
#super(exp) { process_until_empty(exp) } # DISABLING since parsing the method is crashing
|
79
|
-
s()
|
80
|
-
rescue Exception => e
|
81
|
-
if ENV["XUMLIDOT_DEBUG"]
|
82
|
-
STDERR.puts e.backtrace.reverse
|
83
|
-
STDERR.puts "ERROR (#process_def#{superclass_method ? 's' : 'n'}) #{e.message}"
|
84
|
-
end
|
71
|
+
warn method.to_s if ::Xumlidot::Options.debug == true
|
72
|
+
# super(exp) { process_until_empty(exp) } # DISABLING since parsing the method is crashing
|
85
73
|
s()
|
74
|
+
rescue StandardError => e
|
75
|
+
sdebug("#process_def#{superclass_method ? 's' : 'n'}", e)
|
86
76
|
end
|
87
77
|
|
88
78
|
def process_defs(exp)
|
89
|
-
process_defn(exp, true)
|
79
|
+
process_defn(exp, superclass_method: true)
|
90
80
|
end
|
91
81
|
|
92
82
|
# CALLS
|
93
83
|
def process_call(exp)
|
94
84
|
::Xumlidot::Parsers::Call.new(exp, @constants.last_added)
|
95
85
|
s()
|
96
|
-
rescue
|
97
|
-
|
98
|
-
STDERR.puts e.backtrace.reverse
|
99
|
-
STDERR.puts "ERROR (#process_call) #{e.message}"
|
100
|
-
end
|
101
|
-
s()
|
86
|
+
rescue StandardError => e
|
87
|
+
sdebug('#process_call', e)
|
102
88
|
end
|
103
89
|
|
90
|
+
def sdebug(name, error)
|
91
|
+
return s() unless ENV['XUMLIDOT_DEBUG']
|
92
|
+
|
93
|
+
warn error.backtrace.reverse
|
94
|
+
warn "ERROR (#{name}) #{error.message}"
|
95
|
+
s()
|
96
|
+
end
|
104
97
|
end
|
105
98
|
end
|
106
99
|
end
|
@@ -7,7 +7,6 @@ module Xumlidot
|
|
7
7
|
module Parsers
|
8
8
|
# Parser for the KLASS DEFINITION ONLY
|
9
9
|
class KlassDefinition < MethodBasedSexpProcessor
|
10
|
-
|
11
10
|
attr_reader :definition
|
12
11
|
|
13
12
|
def initialize(exp, namespace = nil)
|
@@ -19,28 +18,30 @@ module Xumlidot
|
|
19
18
|
process(exp)
|
20
19
|
end
|
21
20
|
|
21
|
+
# rubocop:disable Metrics/AbcSize
|
22
|
+
# rubocop:disable Metrics/MethodLength
|
22
23
|
def process_class(exp)
|
23
24
|
exp.shift # remove :class
|
24
25
|
definition = exp.shift
|
25
26
|
|
26
27
|
# Processes the name of the class
|
27
|
-
if Sexp === definition
|
28
|
+
if Sexp === definition # rubocop:disable Style/CaseEquality
|
28
29
|
case definition.sexp_type
|
29
|
-
when :colon2
|
30
|
+
when :colon2 # Reached in the event that a name is a compound
|
30
31
|
name = definition.flatten
|
31
32
|
name.delete :const
|
32
33
|
name.delete :colon2
|
33
34
|
name.each do |v|
|
34
35
|
@definition.name << ::Xumlidot::Types::Constant.new(v, @namespace)
|
35
36
|
end
|
36
|
-
when :colon3
|
37
|
+
when :colon3 # Reached in the event that a name begins with ::
|
37
38
|
@definition.name << ::Xumlidot::Types::Constant.new(definition.last, '::')
|
38
39
|
else
|
39
40
|
raise "unknown type #{exp.inspect}"
|
40
41
|
end
|
41
|
-
|
42
|
-
|
43
|
-
# e.g. class Foo; end
|
42
|
+
# TODO: looks like a bug - fix when we get specs
|
43
|
+
else # Symbol === definition
|
44
|
+
# if we have a symbol we have the actual class name e.g. class Foo; end
|
44
45
|
@definition.name << ::Xumlidot::Types::Constant.new(definition, @namespace)
|
45
46
|
end
|
46
47
|
|
@@ -49,6 +50,8 @@ module Xumlidot
|
|
49
50
|
|
50
51
|
s()
|
51
52
|
end
|
53
|
+
# rubocop:enable Metrics/AbcSize
|
54
|
+
# rubocop:enable Metrics/MethodLength
|
52
55
|
|
53
56
|
def process_const(exp)
|
54
57
|
# TODO: may have removed a shift by mistake
|
@@ -11,14 +11,12 @@ module Xumlidot
|
|
11
11
|
# to a string 'a, b = nil'
|
12
12
|
#
|
13
13
|
class MethodSignature < MethodBasedSexpProcessor
|
14
|
-
|
15
|
-
#
|
16
|
-
#class Assignments < Hash
|
17
|
-
#end
|
14
|
+
# class Assignments < Hash
|
15
|
+
# end
|
18
16
|
|
19
17
|
attr_reader :definition
|
20
18
|
|
21
|
-
def initialize(exp, superclass_method
|
19
|
+
def initialize(exp, superclass_method: false)
|
22
20
|
super()
|
23
21
|
|
24
22
|
@definition = ::Xumlidot::Types::MethodSignature.new
|
@@ -26,7 +24,7 @@ module Xumlidot
|
|
26
24
|
@definition.args = Args.new(exp.dup[0..2]).definition # only pass the method definition into args
|
27
25
|
@definition.superclass_method = superclass_method
|
28
26
|
|
29
|
-
|
27
|
+
# @assignments = Assignments.new
|
30
28
|
|
31
29
|
process(exp)
|
32
30
|
end
|
@@ -35,6 +33,7 @@ module Xumlidot
|
|
35
33
|
@definition.to_s
|
36
34
|
end
|
37
35
|
|
36
|
+
# rubocop:disable Metrics/AbcSize
|
38
37
|
def process_defn(exp)
|
39
38
|
exp.shift unless auto_shift_type # node type
|
40
39
|
exp.shift if exp.first.is_a?(Sexp) && exp.first.value == :self # remove :self
|
@@ -47,14 +46,12 @@ module Xumlidot
|
|
47
46
|
more = exp.shift
|
48
47
|
process(more) if more.is_a?(Sexp) && !more.empty?
|
49
48
|
s()
|
50
|
-
rescue
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
STDERR.puts e.backtrace.reverse
|
55
|
-
end
|
56
|
-
s()
|
49
|
+
rescue StandardError => e
|
50
|
+
warn " ** bug: unable to proces defn #{exp}"
|
51
|
+
|
52
|
+
sdebug('MethodSignature#process_defn', e)
|
57
53
|
end
|
54
|
+
# rubocop:enable Metrics/AbcSize
|
58
55
|
|
59
56
|
def process_defs(exp)
|
60
57
|
process_defn(exp)
|
@@ -66,30 +63,37 @@ module Xumlidot
|
|
66
63
|
def process_call(exp)
|
67
64
|
exp.shift # remove the :call
|
68
65
|
|
69
|
-
|
70
|
-
|
71
|
-
|
66
|
+
_recv = process(exp.shift) # recv
|
67
|
+
_name = exp.shift
|
68
|
+
_args = process(exp.shift) # args
|
72
69
|
|
73
70
|
exp
|
74
|
-
rescue
|
75
|
-
|
76
|
-
STDERR.puts "ERROR (MethodSignature#process_call) #{e.message}"
|
77
|
-
STDERR.puts e.backtrace.reverse
|
78
|
-
end
|
71
|
+
rescue StandardError => e
|
72
|
+
sdebug('MethodSignature#process_call', e)
|
79
73
|
exp
|
80
74
|
end
|
81
75
|
|
82
76
|
def process_lasgn(exp)
|
83
77
|
exp.shift # remove :lasgn
|
84
78
|
|
85
|
-
|
79
|
+
_name = exp.shift.to_s
|
86
80
|
value = exp.shift
|
87
81
|
|
88
|
-
|
82
|
+
# @assignments[name] = value
|
89
83
|
|
90
84
|
process(value)
|
91
85
|
s()
|
92
86
|
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def sdebug(name, error)
|
91
|
+
return s() unless ENV['XUMLIDOT_DEBUG']
|
92
|
+
|
93
|
+
warn error.backtrace.reverse
|
94
|
+
warn "ERROR (#{name}) #{error.message}"
|
95
|
+
s()
|
96
|
+
end
|
93
97
|
end
|
94
98
|
end
|
95
99
|
end
|
@@ -10,9 +10,7 @@ module Xumlidot
|
|
10
10
|
#
|
11
11
|
# The main parser will handle method,
|
12
12
|
# constants, etc
|
13
|
-
#
|
14
13
|
class ModuleDefinition < MethodBasedSexpProcessor
|
15
|
-
|
16
14
|
attr_reader :definition
|
17
15
|
|
18
16
|
def initialize(exp, namespace = nil)
|
@@ -24,32 +22,34 @@ module Xumlidot
|
|
24
22
|
process(exp)
|
25
23
|
end
|
26
24
|
|
25
|
+
# rubocop:disable Metrics/AbcSize
|
27
26
|
def process_module(exp)
|
28
27
|
exp.shift # remove :module
|
29
28
|
definition = exp.shift
|
30
29
|
|
31
30
|
# Processes the name of the module
|
32
|
-
if Sexp === definition
|
31
|
+
if Sexp === definition # rubocop:disable Style/CaseEquality
|
33
32
|
case definition.sexp_type
|
34
|
-
when :colon2
|
33
|
+
when :colon2 # Reached in the event that a name is a compound
|
35
34
|
name = definition.flatten
|
36
35
|
name.delete :const
|
37
36
|
name.delete :colon2
|
38
37
|
name.each do |v|
|
39
38
|
@definition.name << ::Xumlidot::Types::Constant.new(v, @namespace)
|
40
39
|
end
|
41
|
-
when :colon3
|
40
|
+
when :colon3 # Reached in the event that a name begins with ::
|
42
41
|
@definition.name << ::Xumlidot::Types::Constant.new(definition.last, '::')
|
43
42
|
else
|
44
43
|
raise "unknown type #{exp.inspect}"
|
45
44
|
end
|
46
|
-
|
47
|
-
|
48
|
-
# e.g. module Foo; end
|
45
|
+
# FIXME: bug - fix when we've added specs
|
46
|
+
else # Symbol === definition
|
47
|
+
# if we have a symbol we have the actual module name e.g. module Foo; end
|
49
48
|
@definition.name << ::Xumlidot::Types::Constant.new(definition, @namespace)
|
50
49
|
end
|
51
50
|
s()
|
52
51
|
end
|
52
|
+
# rubocop:enable Metrics/AbcSize
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|