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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '08c6d11a210e378f99226f1933944c6023d2bb3b0b5a8eeaba85050fe6e8b3cb'
|
4
|
+
data.tar.gz: d8a37ae51f5d1dbc416d05241b456e614f56f82d23b972d9a8e1507dc84835d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bae461d270a21d92c15ff2694b955fc1972e43d6b973da8620032d96533bbfcb02c426793286a0a044b1eeb2f6a01c072e19bb2184a7c1908f596df3f7e6532c
|
7
|
+
data.tar.gz: '08f435ea1c0dddbcf49c53ab6c18820a6aceb67d2f504cbbe315203f9ea9f465dd1c378384bd70abe1202c83aede6f64793f0a7840a321af1052696bf477d203'
|
data/bin/xumlidot
CHANGED
@@ -5,35 +5,6 @@ require_relative '../lib/xumlidot'
|
|
5
5
|
options = ::Xumlidot::Options.parse(ARGV)
|
6
6
|
|
7
7
|
# TODO: user input
|
8
|
-
directories =
|
8
|
+
directories = ARGV
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
# This is our tree of klasses/modules etc
|
13
|
-
# since we can't assume rails conventions for naming
|
14
|
-
# in a Ruby program.
|
15
|
-
constants = ::Xumlidot::Parsers::Stack::Constants.new
|
16
|
-
|
17
|
-
# TODO: move into directory tree
|
18
|
-
dt.find_all_rb_files do |path|
|
19
|
-
STDERR.puts path if ::Xumlidot::Options.debug == true
|
20
|
-
file_contents = File.read(path)
|
21
|
-
|
22
|
-
@parser = Xumlidot::Parsers::File.new(file_contents, constants)
|
23
|
-
@parser.parse
|
24
|
-
end
|
25
|
-
|
26
|
-
# If a class is inherited from but does not exist in the constants
|
27
|
-
# we will create a dummy class.
|
28
|
-
#
|
29
|
-
# if a class is inherited from, we want to find it using the constant lookup
|
30
|
-
# rules definind in the resolver
|
31
|
-
#
|
32
|
-
# and what ... we want to add a reference too it?
|
33
|
-
#
|
34
|
-
# This REALLY should be done whenever we add a superklass
|
35
|
-
# i.e. yeah, its a hack
|
36
|
-
constants.resolve_inheritance()
|
37
|
-
|
38
|
-
diagram = ::Xumlidot::Diagram.new(constants, options)
|
39
|
-
diagram.draw
|
10
|
+
::Xumlidot::Loader.new(directories, options).load
|
@@ -6,8 +6,16 @@ module Xumlidot
|
|
6
6
|
class Diagram
|
7
7
|
class Dot
|
8
8
|
module Method
|
9
|
+
CHARACTER_SUBSTITUTIONS = {
|
10
|
+
'>' => '\>',
|
11
|
+
'<' => '\<',
|
12
|
+
'{' => '\{',
|
13
|
+
'}' => '\}',
|
14
|
+
'|' => '\|'
|
15
|
+
}.freeze
|
16
|
+
|
9
17
|
def to_dot
|
10
|
-
to_s.gsub(
|
18
|
+
to_s.gsub(/[#{CHARACTER_SUBSTITUTIONS.keys.join}]/, CHARACTER_SUBSTITUTIONS)
|
11
19
|
end
|
12
20
|
end
|
13
21
|
|
@@ -29,22 +37,29 @@ module Xumlidot
|
|
29
37
|
end
|
30
38
|
|
31
39
|
def draw_composition(composee)
|
32
|
-
"\"#{draw_identifier(composee.definition)}\"
|
40
|
+
"\"#{draw_identifier(composee.definition)}\"" \
|
41
|
+
" -> \"#{draw_identifier(@definition)}\"" \
|
42
|
+
' [label="", arrowhead="diamond", arrowtail="diamond"]'
|
33
43
|
end
|
34
44
|
|
35
|
-
def
|
45
|
+
def draw_inheritance # rubocop:disable Metrics/AbcSize
|
36
46
|
return nil if @definition.superklass.empty? && @definition.inherited_modules.empty?
|
37
47
|
|
38
|
-
dot =
|
39
|
-
|
40
|
-
dot += "\"#{draw_identifier(@definition)}\"
|
48
|
+
dot = ''
|
49
|
+
unless @definition.superklass.empty?
|
50
|
+
dot += "\"#{draw_identifier(@definition)}\"" \
|
51
|
+
" -> \"#{draw_ancestor(@definition.superklass)}\"" \
|
52
|
+
" [label=\"\", arrowhead=\"empty\", arrowtail=\"onormal\"]\n"
|
41
53
|
end
|
42
54
|
|
43
55
|
return dot if @definition.inherited_modules.empty?
|
44
56
|
|
45
57
|
@definition.inherited_modules.each do |m|
|
46
58
|
next if m.empty?
|
47
|
-
|
59
|
+
|
60
|
+
dot += "\"#{draw_identifier(@definition)}\"" \
|
61
|
+
" -> \"#{draw_ancestor(m)}\"" \
|
62
|
+
" [label=\"#{m.type}s\", arrowhead=\"empty\", arrowtail=\"onormal\"]\n"
|
48
63
|
end
|
49
64
|
|
50
65
|
dot
|
@@ -52,19 +67,19 @@ module Xumlidot
|
|
52
67
|
|
53
68
|
private
|
54
69
|
|
55
|
-
def draw_methods
|
70
|
+
def draw_methods # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
56
71
|
@attributes.each { |a| a.extend(Attribute) }
|
57
72
|
@class_methods.each { |a| a.extend(Method) }
|
58
73
|
@instance_methods.each { |a| a.extend(Method) }
|
59
74
|
|
60
75
|
km = ''
|
61
76
|
km += @attributes.map(&:to_dot).join('\l')
|
62
|
-
km += '\\l'
|
77
|
+
km += '\\l' if @attributes.any?
|
63
78
|
|
64
79
|
km += @class_methods.map(&:to_dot).join('\l')
|
65
80
|
km += '\\l' unless km.end_with?('\\l')
|
66
|
-
km += '|' if instance_methods.size.positive?
|
67
81
|
|
82
|
+
km += '|' if instance_methods.any?
|
68
83
|
km += @instance_methods.map(&:to_dot).join('\l')
|
69
84
|
km += '\\l' unless km.end_with?('\\l')
|
70
85
|
km
|
data/lib/xumlidot/diagram/dot.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'dot/klass'
|
2
4
|
require_relative 'dot/module'
|
3
5
|
|
4
6
|
module Xumlidot
|
5
7
|
class Diagram
|
6
8
|
class Dot
|
7
|
-
|
8
|
-
def initialize(stack, options = nil)
|
9
|
+
def initialize(stack)
|
9
10
|
@stack = stack
|
10
|
-
@options = options
|
11
11
|
@output = []
|
12
12
|
end
|
13
13
|
|
14
14
|
# We have to draw any connecting labels AFTER we have drawn the klasses
|
15
15
|
# in order to have something to connect.
|
16
|
-
def draw
|
16
|
+
def draw # rubocop:disable Metrics/AbcSize
|
17
17
|
@output << header
|
18
18
|
@stack.traverse do |klass|
|
19
19
|
klass.extend(::Xumlidot::Diagram::Dot::Klass)
|
@@ -21,15 +21,15 @@ module Xumlidot
|
|
21
21
|
end
|
22
22
|
|
23
23
|
@stack.traverse do |klass|
|
24
|
-
# Check - i
|
24
|
+
# Check - i shouldn't need to extend twice
|
25
25
|
klass.extend(::Xumlidot::Diagram::Dot::Klass)
|
26
26
|
|
27
|
-
if
|
28
|
-
output = klass.
|
27
|
+
if ::Xumlidot::Options.inheritance
|
28
|
+
output = klass.draw_inheritance
|
29
29
|
@output << output unless output.nil?
|
30
30
|
end
|
31
31
|
|
32
|
-
if
|
32
|
+
if ::Xumlidot::Options.composition
|
33
33
|
klass.constants.each do |k|
|
34
34
|
@output << klass.draw_composition(k)
|
35
35
|
end
|
@@ -1,17 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Xumlidot
|
2
3
|
class Diagram
|
3
4
|
module Shared
|
4
5
|
module Naming
|
5
|
-
def draw_identifier(
|
6
|
-
[
|
6
|
+
def draw_identifier(definition = @definition)
|
7
|
+
[definition.name.name, definition.name.namespace.reverse].reverse.flatten.join('::')
|
7
8
|
end
|
8
9
|
|
9
10
|
def draw_name
|
10
11
|
@definition.name.name.join('::')
|
11
12
|
end
|
12
13
|
|
13
|
-
def draw_ancestor(
|
14
|
-
[
|
14
|
+
def draw_ancestor(definition = @definition)
|
15
|
+
[definition.name, definition.namespace.reverse].reverse.flatten.join('::')
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
@@ -10,19 +10,22 @@ module Xumlidot
|
|
10
10
|
|
11
11
|
def draw
|
12
12
|
xmi = "<ownedParameter kind=\"inout\" name=\"#{name_to_xmi}\" xmi:id=\"#{id}\" xmi:type=\"uml:Parameter\">"
|
13
|
-
|
14
|
-
|
13
|
+
if default
|
14
|
+
xmi += "<defaultValue value=\"#{default_to_xmi}\" xmi:id=\"#{default_id}\" xmi:type=\"uml:LiteralString\"/>"
|
15
|
+
end
|
16
|
+
"#{xmi}</ownedParameter>"
|
15
17
|
end
|
16
18
|
|
17
19
|
private
|
18
20
|
|
19
21
|
def name_to_xmi
|
20
|
-
name
|
22
|
+
name&.encode(xml: :text)
|
21
23
|
end
|
22
24
|
|
23
25
|
def default_to_xmi
|
24
26
|
return default unless default.is_a?(String)
|
25
|
-
|
27
|
+
|
28
|
+
default.encode(xml: :text)
|
26
29
|
end
|
27
30
|
|
28
31
|
def default_id
|
@@ -8,16 +8,16 @@ module Xumlidot
|
|
8
8
|
module Attribute
|
9
9
|
include ::Xumlidot::Diagram::Xmi::ID
|
10
10
|
|
11
|
-
# TODO - public/private visibility on attributes
|
11
|
+
# TODO: - public/private visibility on attributes
|
12
12
|
def draw
|
13
|
-
|
14
|
-
|
13
|
+
'<ownedAttribute aggregation="none" isDerived="false" isDerivedUnion="false" isID="false"' \
|
14
|
+
" isLeaf=\"false\" isReadOnly=\"false\" isStatic=\"false\" name=\"#{name_to_xmi}\"" \
|
15
|
+
" visibility=\"public\" xmi:id=\"#{id}\" xmi:type=\"uml:Property\"></ownedAttribute>"
|
15
16
|
end
|
16
17
|
|
17
18
|
def name_to_xmi
|
18
|
-
name
|
19
|
+
name&.encode(xml: :text)
|
19
20
|
end
|
20
|
-
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -3,6 +3,46 @@
|
|
3
3
|
require 'securerandom'
|
4
4
|
|
5
5
|
module Xumlidot
|
6
|
+
class ID
|
7
|
+
class << self
|
8
|
+
# rubocop:disable Layout/LineLength
|
9
|
+
PREGENERATED = %w[ 915803defa2bd0509fc1ff7a652081d4 e891fc71118502b95030b5e15d887622 2cf60373a8305b3f64bb93a5fa0e786c 35cd5b04a0ab4542aede1e37046fab5e
|
10
|
+
e1521c43130d064474e1585be1d69c6f 59975b5d607a197e676e2534e3dce454 9e52022530441f1688dfab381bba4069 f84f7b576ba1ab5929b4208cebfe7935
|
11
|
+
37e5d86bb891a70011261ad861118a73 09646c77f8dfd088487c91f75c387a4c 9a064273fb75db2d41ad146063940862 ecc9ae948a23543ad23e61b0f907ae6b
|
12
|
+
b922777242d6e4d182e979a19b6b8fd9 b7f1299975494da9811c061f008cacba c906375f1de4be9d3dd3ea56e7917ea6 4265f6134237c7d0c9a4f12b838d1849
|
13
|
+
2d75d4762aa997551f95c76ff23a1e52 fe32489778ddc04b5b2e29a69a25c44e 8e89af98ee73225cac65ade347f5d653 70668faf589fcdd1034db5e8e38c0b8c
|
14
|
+
5b4d3919edab18b46790dc2af405982e bb35181dc1d23696cb914287fb3073da 1adca3c4c42e345682e0abe24dee32fb 611e830b410e4216c80b5fb62f0f0d20
|
15
|
+
648b5d6b3d87b62a3fd34620c391c6e5 bd0747fa99c86e03dd6bbeec3989f859 52653ebf9f0c0930523f583ca3a54476 52e2bdc77cba152a5f8a1e7703893b13
|
16
|
+
08b98d56e4b3e9dd7415cd0174550e01 63de406c477145edb70df08e1fe3d3e9 93f7b64cbd8e96ac5b54e0b83cfef84b cae3e7e7fc79276237aecaf68ab1bdc3
|
17
|
+
d2bde85b6c67f2c4e4f21f4eb24a9e11 b6239715d7b6dfbe845bf6218ffa9267 d018d840347248a3da9989cd56f10532 1fc72578fa0f6820991a2068aac595b0
|
18
|
+
f200b2bf3d28ce99cadeb505fe2a13f9 aba7ec911338260e448768655f9f7f62 e5019785cc3b2db9866887002aab0e82 a9490aac41fa641bf17595f5adc014e2
|
19
|
+
85917936118146692ec4ebaff9bffa25 13fe8089229ff0a7a824a11683e1afa4 8f4dcf8694457f5d09b69513034eb896 aa841e2dda7b46f397dfee83ebebfcb3
|
20
|
+
e84c823e04f190a46b92c7e96d39d802 8dc5d1471bda113d37134e6e457be7f3 ee0989ea42bd2a2e06b0b923bc27aac7 b21b9efefa95229940367caa25d7c7b6
|
21
|
+
7f32d97647fa4d3bb1cb0f8842f6280c 65864053fcd398271fd0482e4b8d6291 22c52a000c617293244d2346679bbcc7 f745cfcd9617f0ee9e8b7a609ccce424
|
22
|
+
85ee520fa2e905d454ccdbf94d789e81 f260df13675880d30ff85dd6713b3df8 afdbe21f7540febe19e2dd2efb1770fe 9c6e6b915115f94f74777e1fe3683805
|
23
|
+
8517f315cc89778e32d62b0e2ee0c01e 2303ed4f97dd09d24427400e3ed9dbaf 72549f0fe322198493927ff113bb9841 c27b2914926e6c8c7406199b0532ba00
|
24
|
+
79940b95278e119378da6e15eea86a90 cd3ee7977ead372f732a8c586ea566a7 ea6370883b3de89a8b38a03c1ec9d591 92ed3a3d54ac7c28e7544ea22f6bfe97
|
25
|
+
8c2302bf6185908b24798f359a2e4838 bef733b51d12963d596f5ecfd5197201 3fa6ac50361036266b73bca0ad3dee57 a5545b87d99a3b7c9533085498ff460e
|
26
|
+
dc3115e7ced845fc6303b2b294a42437 027b8863405ce601db60d685af987dee 71ac366b83d49ca62c3f7c0c7c101f43 6647027529522180e0ae96a176e5766d
|
27
|
+
22e2726ab1b3df71e314f8145180f1c8 b800ccd5d685adac614624ffd5abb098 6c395e62f19d0f5b04f7cea5dd616a24 e2bbe604833cc15c393450d215008306
|
28
|
+
7fa0acb9786d57b2ef4d9027f6cc7992 73d5302aedef54fb51cd08173c1f1829 01cef3c8b0d5ef6cae8574d1a5044b2b c695a6a12c418bb56699b2f5c6559da3
|
29
|
+
a14c60d2210dfea6e625208b72aa79e9 1c60dc02eece351995820d7436e7752e d2a2b30eecceb9f453697103b01b203a 3ae847a28c2248460a37e24686860479
|
30
|
+
354982e26fd1da65403c9e70866e14f7 66485373131b4d5e02261f9d085be072 2e3e154c3ec06e401f48c7f444583d45 e57c33100b8f66813ee9265e4f023e03
|
31
|
+
5afa58ca1c74f449d1b18cc3cb39b19f d5775ea87353bb12f31318533ed17382 c55778698f7c896c6f7e1a35f8698a06 178d5cdabad7e9f82f326a9ebbd01737
|
32
|
+
31cf106e33c94b139f8c8c4820b46524 50a49cf6d0b9bedcbcef845917889a62 cc8aa4100a6f3855df3518a0a4474b74 c98c57ab3db339c74d44d6da5b2e0e62
|
33
|
+
a04e46e4a1f5fea64b3a47a3cc8ca0de 750156c36b6990f2a4763949775ea6a1 423cb15b7efee4800449579ce561a58e 424041648b3414d67743957b9e2ad66c ].freeze
|
34
|
+
# rubocop:enable Layout/LineLength
|
35
|
+
|
36
|
+
def reset
|
37
|
+
@fixed = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def fixed
|
41
|
+
@fixed ||= PREGENERATED.dup
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
6
46
|
class Diagram
|
7
47
|
class Xmi
|
8
48
|
# Helper - everything needs an id and these ids need to be used in the
|
@@ -31,7 +71,11 @@ module Xumlidot
|
|
31
71
|
private
|
32
72
|
|
33
73
|
def new_id
|
34
|
-
|
74
|
+
if ::Xumlidot::Options.use_debug_ids
|
75
|
+
::Xumlidot::ID.fixed.shift
|
76
|
+
else
|
77
|
+
SecureRandom.hex
|
78
|
+
end
|
35
79
|
end
|
36
80
|
end
|
37
81
|
end
|
@@ -24,39 +24,38 @@ module Xumlidot
|
|
24
24
|
end
|
25
25
|
|
26
26
|
# TODO: Split this into model and diagram classes
|
27
|
-
class Model
|
28
|
-
end
|
29
|
-
|
30
|
-
|
31
|
-
end
|
27
|
+
# class Model
|
28
|
+
# end
|
29
|
+
# class Diagram
|
30
|
+
# end
|
32
31
|
|
33
|
-
def draw_klass
|
32
|
+
def draw_klass # rubocop:disable Metrics/AbcSize
|
34
33
|
definition.name.extend(Name)
|
35
34
|
xmi = "<ownedMember isAbstract=\"false\" isActive=\"false\" isLeaf=\"false\" name=\"#{definition.name.to_xmi}\" visibility=\"public\" xmi:id=\"#{id}\" xmi:type=\"uml:Class\">"
|
36
|
-
xmi += draw_model_inheritance if
|
35
|
+
xmi += draw_model_inheritance if ::Xumlidot::Options.inheritance
|
37
36
|
xmi += extend_and_draw(attributes)
|
38
37
|
xmi += extend_and_draw(class_methods)
|
39
38
|
xmi += extend_and_draw(instance_methods)
|
40
|
-
xmi
|
39
|
+
"#{xmi}</ownedMember>"
|
41
40
|
end
|
42
41
|
|
43
42
|
# Draws a diagram element i.e. the part which is rendered
|
44
|
-
def draw_diagram
|
43
|
+
def draw_diagram
|
45
44
|
xml = %(<uml:DiagramElement preferredShapeType="Class" subject="#{id}" xmi:id="#{id}de">
|
46
45
|
</uml:DiagramElement>)
|
47
46
|
|
48
47
|
return xml if @definition.superklass.empty? && @definition.inherited_modules.empty?
|
49
|
-
return xml unless
|
48
|
+
return xml unless ::Xumlidot::Options.inheritance
|
50
49
|
|
51
|
-
xml
|
50
|
+
xml + draw_diagram_generalisation
|
52
51
|
end
|
53
52
|
|
54
53
|
def draw_diagram_generalisation
|
55
54
|
xml = ''
|
56
55
|
|
57
|
-
|
56
|
+
unless @definition.superklass.empty?
|
58
57
|
xml += %(<uml:DiagramElement fromDiagramElement="#{@definition.superklass.id}de" preferredShapeType="Generalization" subject="#{gen_id}" toDiagramElement="#{id}de">
|
59
|
-
|
58
|
+
</uml:DiagramElement>)
|
60
59
|
end
|
61
60
|
|
62
61
|
return xml if @definition.inherited_modules.empty?
|
@@ -65,7 +64,7 @@ module Xumlidot
|
|
65
64
|
next if m.empty?
|
66
65
|
|
67
66
|
xml += %(<uml:DiagramElement fromDiagramElement="#{m.id}de" preferredShapeType="Generalization" subject="#{gen_id}" toDiagramElement="#{id}de">
|
68
|
-
|
67
|
+
</uml:DiagramElement>)
|
69
68
|
end
|
70
69
|
|
71
70
|
xml
|
@@ -77,12 +76,12 @@ module Xumlidot
|
|
77
76
|
# general =
|
78
77
|
# id = IMPORTANT; will be used to draw the lines in the diagram
|
79
78
|
#
|
80
|
-
def draw_model_inheritance
|
79
|
+
def draw_model_inheritance # rubocop:disable Metrics/AbcSize
|
81
80
|
return '' if @definition.superklass.empty? && @definition.inherited_modules.empty?
|
82
81
|
|
83
82
|
xml = ''
|
84
83
|
|
85
|
-
|
84
|
+
unless @definition.superklass.empty?
|
86
85
|
xml += %(<generalization general="#{@definition.superklass.id}" xmi:id="#{gen_id}" xmi:type="uml:Generalization">
|
87
86
|
</generalization>)
|
88
87
|
end
|
@@ -101,11 +100,11 @@ module Xumlidot
|
|
101
100
|
def draw_model_composition(composee)
|
102
101
|
%(<ownedMember isAbstract="false" isDerived="false" isLeaf="false" xmi:id="#{association_id}" xmi:type="uml:Association">
|
103
102
|
<memberEnd xmi:idref="#{association_end_id}"/>
|
104
|
-
<ownedEnd aggregation="none" association="#{association_id}" isDerived="false" isDerivedUnion="false" isLeaf="false" isNavigable="true" isReadOnly="false" isStatic="false" type="#{id}" xmi:id="
|
103
|
+
<ownedEnd aggregation="none" association="#{association_id}" isDerived="false" isDerivedUnion="false" isLeaf="false" isNavigable="true" isReadOnly="false" isStatic="false" type="#{id}" xmi:id="#{association_end_id}" xmi:type="uml:Property">
|
105
104
|
</ownedEnd>
|
106
105
|
<memberEnd xmi:idref="#{composee.association_end_id}"/>
|
107
|
-
|
108
|
-
|
106
|
+
<ownedEnd aggregation="composite" association="#{association_id}" isDerived="false" isDerivedUnion="false" isLeaf="false" isNavigable="true" isReadOnly="false" isStatic="false" type="#{composee.id}" xmi:id="#{composee.association_end_id}" xmi:type="uml:Property">
|
107
|
+
</ownedEnd>
|
109
108
|
</ownedMember>)
|
110
109
|
end
|
111
110
|
|
@@ -14,17 +14,20 @@ module Xumlidot
|
|
14
14
|
return '<<' if name == :<<
|
15
15
|
return '>>' if name == :>>
|
16
16
|
return '<=>' if name == :<=>
|
17
|
+
|
17
18
|
name
|
18
19
|
end
|
19
20
|
|
20
21
|
def draw
|
21
|
-
xmi =
|
22
|
+
xmi = '<ownedOperation isAbstract="false" isLeaf="false" isOrdered="false" isQuery="false"' \
|
23
|
+
" isStatic=\"#{superclass_method}\" isUnique=\"true\" name=\"#{name_to_xmi}\"" \
|
24
|
+
" visibility=\"#{visibility}\" xmi:id=\"#{id}\" xmi:type=\"uml:Operation\">"
|
22
25
|
xmi += "<ownedParameter kind=\"return\" xmi:id=\"#{return_id}\" xmi:type=\"uml:Parameter\"/>"
|
23
26
|
args.each do |argument|
|
24
27
|
argument.extend(::Xumlidot::Diagram::Xmi::Argument)
|
25
28
|
xmi += argument.draw
|
26
29
|
end
|
27
|
-
xmi
|
30
|
+
"#{xmi}</ownedOperation>"
|
28
31
|
end
|
29
32
|
|
30
33
|
private
|
data/lib/xumlidot/diagram/xmi.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'xmi/argument'
|
2
4
|
require_relative 'xmi/attribute'
|
3
5
|
require_relative 'xmi/klass'
|
@@ -8,16 +10,9 @@ require 'rexml/document'
|
|
8
10
|
module Xumlidot
|
9
11
|
class Diagram
|
10
12
|
class Xmi
|
11
|
-
|
12
13
|
include REXML
|
13
14
|
|
14
15
|
class Elements < Array
|
15
|
-
|
16
|
-
def initialize(options)
|
17
|
-
super()
|
18
|
-
@options = options
|
19
|
-
end
|
20
|
-
|
21
16
|
def draw
|
22
17
|
xml = header
|
23
18
|
uniq.each { |de| xml += de }
|
@@ -46,7 +41,7 @@ module Xumlidot
|
|
46
41
|
private
|
47
42
|
|
48
43
|
def header
|
49
|
-
%(<uml:Model name="#{
|
44
|
+
%(<uml:Model name="#{::Xumlidot::Options.model_name}" xmi:id="jcBKnwaFYHEAAQV_">)
|
50
45
|
end
|
51
46
|
|
52
47
|
def footer
|
@@ -58,12 +53,13 @@ module Xumlidot
|
|
58
53
|
private
|
59
54
|
|
60
55
|
def header
|
61
|
-
%(<uml:Diagram diagramType="ClassDiagram" documentation=""
|
62
|
-
|
56
|
+
%(<uml:Diagram diagramType="ClassDiagram" documentation=""
|
57
|
+
name="#{::Xumlidot::Options.title}" toolName="Visual Paradigm" xmi:id="QfZKnwaFYHEAAQj3">
|
58
|
+
<uml:Diagram.element>)
|
63
59
|
end
|
64
60
|
|
65
61
|
def footer
|
66
|
-
%(
|
62
|
+
%(</uml:Diagram.element>
|
67
63
|
</uml:Diagram>)
|
68
64
|
end
|
69
65
|
end
|
@@ -76,7 +72,7 @@ module Xumlidot
|
|
76
72
|
end
|
77
73
|
|
78
74
|
# reverse lookup
|
79
|
-
def has_value?(id)
|
75
|
+
def has_value?(id) # rubocop:disable Naming/PredicateName
|
80
76
|
@id_to_namespace[id] != nil
|
81
77
|
end
|
82
78
|
|
@@ -94,20 +90,19 @@ module Xumlidot
|
|
94
90
|
end
|
95
91
|
end
|
96
92
|
|
97
|
-
def initialize(stack
|
93
|
+
def initialize(stack)
|
98
94
|
@stack = stack
|
99
|
-
@options = options
|
100
95
|
|
101
96
|
@namespace_to_id = NamespaceToId.new
|
102
97
|
|
103
|
-
@model = ModelElements.new
|
104
|
-
@diagram = DiagramElements.new
|
98
|
+
@model = ModelElements.new
|
99
|
+
@diagram = DiagramElements.new
|
105
100
|
|
106
|
-
@model_associations = ModelAssociationElements.new
|
107
|
-
@diagram_associations = DiagramAssociationElements.new
|
101
|
+
@model_associations = ModelAssociationElements.new
|
102
|
+
@diagram_associations = DiagramAssociationElements.new
|
108
103
|
end
|
109
104
|
|
110
|
-
def draw
|
105
|
+
def draw # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
111
106
|
# First traversal we're just assigning ids to everything so that when
|
112
107
|
# we come to draw things we can do a lookup on the ids for any composition
|
113
108
|
# aggregation or subclass relationships.
|
@@ -117,10 +112,12 @@ module Xumlidot
|
|
117
112
|
|
118
113
|
klass.definition.inherited_modules.each do |m|
|
119
114
|
next if m.empty?
|
115
|
+
|
120
116
|
m.extend(::Xumlidot::Diagram::Xmi::Superklass)
|
121
|
-
end
|
117
|
+
end
|
122
118
|
|
123
119
|
next if @namespace_to_id.has?(klass.draw_identifier)
|
120
|
+
|
124
121
|
@namespace_to_id[klass.draw_identifier] = klass.id
|
125
122
|
end
|
126
123
|
|
@@ -136,22 +133,24 @@ module Xumlidot
|
|
136
133
|
# do the same with the inherited modules
|
137
134
|
klass.definition.inherited_modules.each do |m|
|
138
135
|
next if m.empty?
|
136
|
+
|
139
137
|
id = @namespace_to_id[m.draw_identifier]
|
140
138
|
m.force_id(id)
|
141
|
-
end
|
139
|
+
end
|
142
140
|
|
143
141
|
# if we have not added an id for this element it is likely a duplicate
|
144
142
|
# so do not draw it.
|
145
|
-
next unless @namespace_to_id.has_value?(klass.id)
|
143
|
+
next unless @namespace_to_id.has_value?(klass.id) # rubocop:disable Style/PreferredHashMethods
|
146
144
|
|
147
|
-
@model << klass.draw_klass
|
148
|
-
@diagram << klass.draw_diagram
|
145
|
+
@model << klass.draw_klass
|
146
|
+
@diagram << klass.draw_diagram
|
149
147
|
|
150
|
-
if
|
148
|
+
if ::Xumlidot::Options.composition
|
151
149
|
klass.constants.each do |k|
|
152
150
|
# Likewise to the above, unless we have an id for the class
|
153
151
|
# we don't want to draw the relationships
|
154
|
-
next unless @namespace_to_id.has_value?(k.id)
|
152
|
+
next unless @namespace_to_id.has_value?(k.id) # rubocop:disable Style/PreferredHashMethods
|
153
|
+
|
155
154
|
@model_associations << klass.draw_model_composition(k)
|
156
155
|
@diagram_associations << klass.draw_diagram_composition(k)
|
157
156
|
end
|
data/lib/xumlidot/diagram.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'diagram/dot'
|
2
4
|
require_relative 'diagram/xmi'
|
3
5
|
|
4
6
|
module Xumlidot
|
5
7
|
class Diagram
|
6
|
-
def initialize(stack,
|
7
|
-
@diagram = if
|
8
|
-
::Xumlidot::Diagram::Dot.new(stack
|
8
|
+
def initialize(stack, _options)
|
9
|
+
@diagram = if ::Xumlidot::Options.diagram_type == :dot
|
10
|
+
::Xumlidot::Diagram::Dot.new(stack)
|
9
11
|
else
|
10
|
-
::Xumlidot::Diagram::Xmi.new(stack
|
12
|
+
::Xumlidot::Diagram::Xmi.new(stack)
|
11
13
|
end
|
12
14
|
end
|
13
15
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'find'
|
2
4
|
|
3
5
|
module Xumlidot
|
@@ -9,7 +11,7 @@ module Xumlidot
|
|
9
11
|
@excluded = Regexp.new(@options.exclude)
|
10
12
|
end
|
11
13
|
|
12
|
-
def find_all_rb_files
|
14
|
+
def find_all_rb_files
|
13
15
|
@directories.each do |directory|
|
14
16
|
Find.find(directory) do |path|
|
15
17
|
next if path =~ @exluded
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Xumlidot
|
4
|
+
# This is code that was living in bin/xumlidot. We need to leverage
|
5
|
+
# it for running integration tests though
|
6
|
+
class Loader
|
7
|
+
def initialize(directories, options)
|
8
|
+
@directories = directories
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def load
|
13
|
+
dt = Xumlidot::DirectoryTree.new(directories, options)
|
14
|
+
|
15
|
+
# This is our tree of klasses/modules etc
|
16
|
+
# since we can't assume rails conventions for naming
|
17
|
+
# in a Ruby program.
|
18
|
+
constants = ::Xumlidot::Parsers::Stack::Constants.new
|
19
|
+
|
20
|
+
# TODO: move into directory tree
|
21
|
+
dt.find_all_rb_files do |path|
|
22
|
+
warn path if ::Xumlidot::Options.debug == true
|
23
|
+
file_contents = File.read(path)
|
24
|
+
|
25
|
+
@parser = Xumlidot::Parsers::File.new(file_contents, constants)
|
26
|
+
@parser.parse
|
27
|
+
end
|
28
|
+
|
29
|
+
# If a class is inherited from but does not exist in the constants
|
30
|
+
# we will create a dummy class.
|
31
|
+
#
|
32
|
+
# if a class is inherited from, we want to find it using the constant lookup
|
33
|
+
# rules defining in the resolver
|
34
|
+
#
|
35
|
+
# and what ... we want to add a reference too it?
|
36
|
+
#
|
37
|
+
# This REALLY should be done whenever we add a superklass
|
38
|
+
# i.e. yeah, its a hack
|
39
|
+
constants.resolve_inheritance
|
40
|
+
|
41
|
+
diagram = ::Xumlidot::Diagram.new(constants, options)
|
42
|
+
diagram.draw
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
attr_accessor :directories, :options
|
48
|
+
end
|
49
|
+
end
|