Source code for pycodeanalyzer.core.diagrams.plantuml

"""PlantUML diagram language

This module allow to create PlantUML class diagram from abstractions.
"""

from typing import List, Tuple

from pycodeanalyzer.core.abstraction.objects import (
    AbstractClass,
    AbstractEnum,
    AbstractFunction,
    AbstractObject,
)
from pycodeanalyzer.core.diagrams.iclassdiagrambuild import IClassDiagramBuild


[docs]class PlantUMLClassDiagramBuild(IClassDiagramBuild): """Mermaid.js class diagram builder""" def __init__(self) -> None: super().__init__(__name__) self.reset()
[docs] def reset(self) -> None: self.klasses: List[AbstractClass] = [] self.enums: List[AbstractEnum] = [] self.relations: List[Tuple[str, str]] = [] self.parents: List[Tuple[str, str]] = [] self.target: AbstractObject = None
[docs] def createClass( self, target: AbstractClass, linkedClasses: List[AbstractClass], linkedEnums: List[AbstractEnum], linkedFunctions: List[AbstractFunction], ) -> None: self.target = target self.__addClass(target) for klass in linkedClasses: self.__addClass(klass) if target.isParent(klass): self.__addInheritance(target, klass) else: self.__addDependancy(target, klass) for enum in linkedEnums: self.__addEnum(enum) self.__addDependancy(target, enum)
[docs] def createEnum(self, target: AbstractEnum) -> None: self.target = target self.__addEnum(target)
[docs] def build(self) -> str: res = "@startuml\n" for klass in self.klasses: res += "class " + klass.name res += " <<" + klass.getMainClassifier() + ">>\n" if not klass.origin: continue res += "{\n" for member in klass.members: res += ( self.__getVisibilityMark(member[2]) + " " + (self.__getTypeString(member[0]) + " " + member[1] + "\n") ) for method in klass.methodes: paramstr = "" for param in method[2]: paramstr += self.__getTypeString(param[0]) + " " + param[1] + ", " res += ( self.__getVisibilityMark(method[3]) + self.__getTypeString(method[0]) + " " + method[1] + "(" + paramstr[:-2] + ")\n" ) res += "}\n" for enum in self.enums: res += "enum " + enum.name if not enum.origin: res += " <<External>>\n" continue res += " <<Enum>>\n" res += "{\n" for value in enum.values: res += value + "\n" res += "}\n" for relation in self.parents: res += relation[0] + " --|> " + relation[1] + "\n" for relation in self.relations: res += relation[0] + " ..|> " + relation[1] + "\n" res += "@enduml\n" return res
def __addInheritance( self, target: AbstractClass, linkedObject: AbstractObject ) -> None: relation = (target.name, linkedObject.name) if relation not in self.parents: self.parents.append(relation) def __addDependancy( self, target: AbstractObject, linkedObject: AbstractObject ) -> None: relation = (target.name, linkedObject.name) if relation not in self.relations: self.relations.append(relation) def __addClass(self, abstractClass: AbstractClass) -> None: if abstractClass not in self.klasses: self.klasses.append(abstractClass) def __addEnum(self, abstractEnum: AbstractEnum) -> None: if abstractEnum not in self.enums: self.enums.append(abstractEnum) def __getVisibilityMark(self, text: str) -> str: if text == "private": return "-" if text == "protected": return "#" return "+" def __getTypeString(self, type: str) -> str: res = type res = res.strip() return res