nituml: Can generate UML package diagrams from nit source.
authorLucas Bajolet <r4pass@hotmail.com>
Tue, 23 Sep 2014 15:45:27 +0000 (11:45 -0400)
committerLucas Bajolet <r4pass@hotmail.com>
Tue, 23 Sep 2014 18:06:23 +0000 (14:06 -0400)
Signed-off-by: Lucas Bajolet <r4pass@hotmail.com>

src/nituml.nit
src/uml/uml.nit
src/uml/uml_module.nit [new file with mode: 0644]

index 3d5f3ba..04cb4b3 100644 (file)
@@ -21,6 +21,13 @@ import uml
 
 redef class ToolContext
        var umlphase: Phase = new UMLPhase(self, null)
+
+       var opt_gen = new OptionEnum(["class", "package"], "Choose which type of uml diagram to generate", 0, "--diagram")
+
+       redef init do
+               option_context.add_option opt_gen
+               super
+       end
 end
 
 private class UMLPhase
@@ -28,7 +35,11 @@ private class UMLPhase
        redef fun process_mainmodule(mainmodule, mmodules)
        do
                var d = new UMLModel(mainmodule.model, mainmodule, toolcontext)
-               print d.generate_class_uml.write_to_string
+               if toolcontext.opt_gen.value == 0 then
+                       print d.generate_class_uml.write_to_string
+               else if toolcontext.opt_gen.value == 1 then
+                       print d.generate_package_uml.write_to_string
+               end
        end
 end
 
index 2a881a9..0403540 100644 (file)
@@ -17,3 +17,4 @@ module uml
 
 import uml_base
 import uml_class
+import uml_module
diff --git a/src/uml/uml_module.nit b/src/uml/uml_module.nit
new file mode 100644 (file)
index 0000000..55d16f3
--- /dev/null
@@ -0,0 +1,158 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Services for generation of a UML package diagram based on a `Model`
+module uml_module
+
+import uml_base
+import uml_class
+
+redef class UMLModel
+       # Generates a UML package diagram from a `Model`
+       fun generate_package_uml: Streamable do
+               var tpl = new Template
+               tpl.add "digraph G \{\n"
+               tpl.add """     fontname = "Bitstream Vera Sans"
+                       fontsize = 8
+                       node [
+                               fontname = "Bitstream Vera Sans"
+                               fontsize = 8
+                               shape = "record"
+                       ]
+                       edge [
+                               fontname = "Bitstream Vera Sans"
+                               fontsize = 8
+                       ]\n"""
+               tpl.add model.tpl_module(ctx, mainmodule)
+               tpl.add "\}"
+               return tpl
+       end
+end
+
+redef class Model
+       # Returns a UML package diagram of `main`
+       fun tpl_module(ctx: ToolContext, main: MModule): Streamable do
+               return main.tpl_module(ctx, main)
+       end
+end
+
+redef class MModule
+       redef fun tpl_module(ctx, main) do
+               var t = new Template
+               t.add "subgraph cluster{name} \{\n"
+               t.add "label = \"{name}\"\n"
+               for i in mclassdefs do
+                       if not ctx.private_gen and i.mclass.visibility != public_visibility then continue
+                       t.add i.tpl_module(ctx, main)
+               end
+               t.add "\}\n"
+               return t
+       end
+end
+
+redef class MEntity
+       # Builds a dot UML package diagram entity from `self`
+       fun tpl_module(ctx: ToolContext, main: MModule): Streamable is abstract
+end
+
+redef class MClassDef
+
+       # Colour for the border of a class when first introduced
+       #
+       # Defaults to a shade of green
+       var intro_colour = "#58B26A"
+
+       # Colour for the border of a class when refined
+       #
+       # Defaults to a shade of red
+       var redef_colour = "#B24758"
+
+       redef fun tpl_module(ctx, main) do
+               var t = new Template
+               t.add "{mmodule}{name} [\n\tlabel = \"\{"
+               if mclass.kind == abstract_kind then
+                       t.add "abstract\\n{name}"
+               else if mclass.kind == interface_kind then
+                       t.add "interface\\n{name}"
+               else
+                       t.add "{name}"
+               end
+               if mclass.arity > 0 then
+                       t.add "["
+                       var formal = mclass.intro.parameter_names
+                       t.add formal.first
+                       for i in [1 .. formal.length[ do
+                               t.add ", "
+                               t.add formal[i]
+                       end
+                       t.add "]"
+               end
+               t.add "|"
+               for i in mpropdefs do
+                       if not i isa MAttributeDef then continue
+                       if not ctx.private_gen and i.mproperty.visibility != public_visibility then continue
+                       t.add i.tpl_module(ctx, main)
+                       t.add "\\l"
+               end
+               t.add "|"
+               for i in mpropdefs do
+                       if not i isa MMethodDef then continue
+                       if not ctx.private_gen and i.mproperty.visibility != public_visibility then continue
+                       t.add i.tpl_module(ctx, main)
+                       t.add "\\l"
+               end
+               t.add "\}\""
+               if is_intro then
+                       t.add "color=\"{intro_colour}\""
+               else
+                       t.add "color=\"{redef_colour}\""
+               end
+               t.add "\n]\n"
+               var supers = in_hierarchy.direct_greaters
+               for i in supers do
+                       if i.mmodule != mmodule then continue
+                       t.add "{i.mmodule}{i.name} -> {mmodule}{name} [dir=back"
+                       if i.mclass.kind == interface_kind then
+                               t.add " arrowtail=open style=dashed"
+                       else
+                               t.add " arrowtail=empty"
+                       end
+                       t.add "]\n"
+               end
+               return t
+       end
+end
+
+redef class MMethodDef
+       redef fun tpl_module(ctx, main) do
+               var t = new Template
+               t.add mproperty.visibility.tpl_class
+               t.add " "
+               t.add name.escape_to_dot
+               t.add msignature.tpl_class(ctx, main)
+               return t
+       end
+end
+
+redef class MAttributeDef
+       redef fun tpl_module(ctx, main) do
+               var t = new Template
+               t.add mproperty.visibility.tpl_class
+               t.add " "
+               t.add name
+               t.add ": "
+               t.add static_mtype.tpl_class(ctx, main)
+               return t
+       end
+end