Code Monkey home page Code Monkey logo

swiftplantuml's Introduction

SwiftPlantUML

Generate UML class diagrams from swift code with this Command Line Interface (CLI) and Swift Package.

Build Status codecov codebeat badge docs Xcode Extension Twitter CII Best Practices

Use one or more Swift files as input for a diagram to visualize class, struct, protocol, enum and extension types with their instance and static members as well as their inheritance and implementation relationships

Example Diagram

Table of Contents (click to expand)

Usage

Command Line

Example to generate and render diagram, based on a single Swift file, in your browser:

swiftplantuml ./Tests/SwiftPlantUMLFrameworkTests/TestData/basics.txt

Run swiftplantuml in the directory containing the Swift files to be considered for diagram generation. Directories will be searched recursively.

$ swiftplantuml classdiagram --help
OVERVIEW: Generate PlantUML script and view it and diagram in browser

USAGE: swift-plant-uml classdiagram [--config <config>] [--exclude <exclude> ...] [--output <format>] [--sdk <sdk>] [--verbose] [<paths> ...]

ARGUMENTS:
  <paths>                 List of paths to the files or directories containing
                          swift sources

OPTIONS:
  --config <config>       Path to custom configuration filed (otherwise will
                          search for `.swiftplantuml.yml` in current directory)
  --exclude <exclude>     paths to ignore source files. Takes precedence over
                          arguments
  --output <format>       Defines output format. Options: browser,
                          browserImageOnly, consoleOnly
  --sdk <sdk>             MacOSX SDK path used to handle type inference
                          resolution, usually `$(xcrun --show-sdk-path -sdk
                          macosx)`
  --hide-extensions/--merge-extensions/--show-extensions
                          Decide if/how Swift extensions shall be considered for class diagram generation (default:
                          hideExtensions)
  --verbose               Verbose
  --version               Show the version.
  -h, --help              Show help information.

As classdiagram is the default subcommand you can omit it.

Note: unknown type in diagrams for variables declared with type inference (e.g. var hasBasket = false) unless you specify sdk argument

Type inference details (click to expand)

In the following example the property hasBasket is of type Bool but the type is inferred and not explicitly declared.

class Bicycle: Vehicle {
    var hasBasket = false
}

SwiftPlantUML requires the macosx SDK in order to properly recognize the inferred type. If you have Xcode installed (which includes the macosx SDK) then use --sdk $(xcrun --show-sdk-path -sdk macosx).

No inferred type (default) inferred type
Generated PlantUML ~hasBasket ~hasBasket : Bool
Command swiftplantuml classdiagram Tests/SwiftPlantUMLFrameworkTests/TestData/demo.txt swiftplantuml classdiagram Tests/SwiftPlantUMLFrameworkTests/TestData/demo.txt --sdk $(xcrun --show-sdk-path -sdk macosx)

Swift package

dependencies: [
    .package(url: "https://github.com/MarcoEidinger/SwiftPlantUML.git", .upToNextMajor(from: "0.5.0"))
]

This project has yet to reach a major version. Anything may change at anytime, and the public API should not be considered stable. However, I'll try to reserve breaking changes for new minor versions. You might feel more comfortable pinning the version to .upToNextMinor or even to an .exact version.

API documentation

Xcode source editor extension

See MarcoEidinger/SwiftPlantUML-Xcode-Extension for more details

Installation

Using Homebrew

brew install swiftplantuml

previously you were able to use brew install MarcoEidinger/formulae/swiftplantuml (and you still can)

Using Mint

$ mint install MarcoEidinger/SwiftPlantUML

Installing from source

You can also build and install from source by cloning this project and running make install (Xcode 12 or later).

Manually Run the following commands to build and install manually:

$ git clone https://github.com/MarcoEidinger/SwiftPlantUML.git
$ cd SwiftPlantUML
$ make install

Note: Working with Multiple Swift Versions

SwiftPlantUML hooks into SourceKit and therefore needs a Swift toolschain.

You should always run SwiftPlantUML with the same toolchain you use to compile your code.

You may want to override SwiftPlantUML's default Swift toolchain if you have multiple toolchains or Xcodes installed.

Here's the order in which SwiftPlantUML determines which Swift toolchain to use:

  • $XCODE_DEFAULT_TOOLCHAIN_OVERRIDE
  • $TOOLCHAIN_DIR or $TOOLCHAINS
  • xcrun -find swift
  • /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain
  • /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain
  • ~/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain
  • ~/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain

sourcekitd.framework is expected to be found in the usr/lib/ subdirectory of the value passed in the paths above.

So if you encounter Fatal error: Loading sourcekitd.framework/Versions/A/sourcekitd failed then please check result of xcode-select -p to see if that directory subsequently contains a Swift toolschain. You can use sudo xcode-select -s <pathToYourXcodeInstallation> to rectify the situation, e.g.

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

Configuration

Configure SwiftPlantUML by adding a .swiftplantuml.yml file from the directory you'll run SwiftPlantUML from. Note: the same configuration options can be set programmatically with Configuration.

Options

You can

  • include/exclude files (wildcards supported)
  • include/exclude elements by name (wildcards supported)
  • limit elements and members based on their access level, e.g. show only public types
  • hide extensions or merge extensions (with their known type)
Show Extensions (Default) Merge Extensions Hide Extensions
Show Extensions Merge Extensions Hide Extensions
Clutter but represents codebase accurately Reduced clutter. No loss of information No clutter but loss of information
  • hide nested types
  • hide member access level attribute
  • configure styles, use skin parameters and even include external files or themes
  • exclude inheritance relationships based on parent (wildcards supported), e.g. do not show inheritance to Codable

Theming

Default Amiga Reddress-darkblue Sketchy Outline Many More Available
default amiga reddress-darkblue sketchy-outline See here for more examples

Examples

Simple Example:

files:
    exclude:
    - "Tests/**/*.swift" # paths to ignore for diagram. Takes precedence over `included`.
elements:
  havingAccessLevel:
  - public
  - open
  showMembersWithAccessLevel:
  - public
  - open
  showNestedTypes: false
  showExtensions: merged
theme: plain # see https://plantuml.com/theme
texts:
  title: |
    <u>Formatted</u> title example
    on <i>several</i> lines and using <font color=red>html</font>
skinparamCommands: # see https://plantuml.com/skinparam
- skinparam classBackgroundColor PaleGreen
- skinparam classArrowColor SeaGreen
- skinparam classBorderColor SpringGreen
- skinparam stereotypeCBackgroundColor YellowGreen
- skinparam stereotypeCBackgroundColor<< Foo >> DimGray
relationships:
  inheritance:
    label: "inherits from"
    style:
      lineStyle: dotted
      lineColor: DarkViolet
      textColor: DarkViolet
    exclude:
    - "Codable"

Rich example: here

Code Completion during Editing

codeCompletion

To get code completion during editing use Visual Studio Code, the YAML extension created by Red Hat and the JSON schema for SwiftPlantUML.

In Visual Studio Code: Code -> Preferences -> Settings -> search for yaml

Screen Shot 2021-02-27 at 5 57 49 AM

Click on Edit in settings.json and add the respective entry:

"yaml.schemas": {"https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML/main/Configuration/Schema/json-schema-swiftplantuml.json": "/.swiftplantuml.yml" }

Large Diagrams

Online tools like PlantText do not support large diagrams. If your diagram image is incompletely rendered (or not visible at all) by PlantText in the browser then

  • download PlantUML Java archive to your machine
  • use swiftplantuml to generate the script and
  • generate the actual image with plantuml locally

Here is the respective command (which assumes that plantuml.jar was downloaded in the current directory from which swifptlantuml runs)

swiftplantuml ./Sources/ --output consoleOnly > sources.txt | java -DPLANTUML_LIMIT_SIZE=8192 -jar plantuml.jar $1

This will result in the creation of sources.png file containing the class diagram up to the size limit.

PlantUML limits image width and height to 4096 with the option to override this limit (-DPLANTUML_LIMIT_SIZE) of which I made use in the command above.

In the table below you see the difference of class diagram output based on the same script. FYI: this script/diagram has 63 entities.

PlantText Output PlantUML Output (Default Size Limit) PlantUML Output (Custom Size Limit)
sources_planttext sources_plantumljar sources_plantumljar_increasedlimit

Generate UML documentation from a binary framework

You can use swifplantuml to parse the .swiftmodule file of a binary framework, for details and a concrete example please read my article Generate UML documentation from a binary framework (xcframework).

Planned improvements

  • being able to render associations between elements

Known limitations

See Large Diagrams

Logging

CLI will log only error messages per default.

To log messages with lower priority (warning, info, debug) use the --verbose option.

Note: using --output consoleOnly, to print the PlantUML script in the console, will log any messages into a log file. This has the advantage that you can pipe the PlantUML script into a file without problems. You can tail the log file with tail -f /tmp/swiftplantuml.log

Manual page

Installing swiftplantuml with Homebrew or from source (make install) will also install a man page which you can view with:

man swiftplantuml

manual page for swiftplantuml

Acknowledgements

This project was inspired by https://github.com/palaniraja/swiftuml and its various predecessors. Out of personal preference I chose to start a new project. I wanted to provide a tool for Swift developers written in Swift! This will hopefully allow me and potential contributors to work on planned improvements faster and more efficient.

Last but not least a big shoutout to the great developers of PlantUML and the people who operate the related online servers / tools available on http://plantuml.com/ and https://www.planttext.com/

swiftplantuml's People

Contributors

marcoeidinger avatar ttozzi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swiftplantuml's Issues

cannot install using home-brew on MacOS10.15.7 with Xcode 12.4

I get the message:
Traceback (most recent call last):
brew extract or brew create and brew tap-new to create a formula file in a tap on GitHub instead.: Invalid usage: Non-checksummed download of swiftplantuml formula file from an arbitrary URL is unsupported! (UsageError)

Support access level `open`

Elements (classes, structs, ...) or members (properties and functions) with access level open will currently not be parsed and converted into PlantUML script.

Configuration: adding header, title, legend, caption, footer

In the .swiftplantuml.yml configuration file it would be helpful to add one or more of the following command commands:

  • header
  • title
  • legend
  • caption
  • footer

Example visualization

SVG

Example PlantUML script

@startuml
header
<u>Simple</u> header example
on <i>several</i> lines and using <font color=red>html</font>
end header

title
<u>Simple</u> title example
on <i>several</i> lines and using <font color=red>html</font>
end title

caption
<u>Simple</u> caption example
on <i>several</i> lines and using <font color=red>html</font>
end caption

footer
<u>Simple</u> footer example
on <i>several</i> lines and using <font color=red>html</font>
end footer

legend
<u>Simple</u> legend example
on <i>several</i> lines and using <font color=red>html</font>
end legend

class Class1 {}
class Class2 {}

Class1 -- Class2
@enduml

No access level indicator for fileprivate members

Members do not show an access level indicator if they have fileprivate access level

class aClass {
    var computedProperty: String {}
    func aFunction() {}
}

fileprivate extension aClass {
    var extComputedProperty: String { "" }
    func extFunction()
}

Current (unexpected) output

@startuml
' STYLE START
hide empty members
skinparam shadowing false
' STYLE END


class "aClass" as aClass << (C, DarkSeaGreen) >> { 
  ~computedProperty : String
  ~aFunction() 
}
class "aClass" as aClass0 << (X, Orchid) extension >> { 
  extComputedProperty : String
  extFunction() 
}

aClass <.. aClass0 : ext
@enduml

Expected output

@startuml
' STYLE START
hide empty members
skinparam shadowing false
' STYLE END


class "aClass" as aClass << (C, DarkSeaGreen) >> { 
  ~computedProperty : String
  ~aFunction() 
}
class "aClass" as aClass0 << (X, Orchid) extension >> { 
  -extComputedProperty : String
  -extFunction() 
}

aClass <.. aClass0 : ext
@enduml

Determine inferred type for variables

In version 0.2.1 and lower

unknown type for variables declared with type inference (e.g. var count = 0) => this is a limitation of SourceKitten :(

Apparently SourceKitten is able to provide the information but macosx SDK is needed (~ Xcode)

Installation not possible

Although I'd had loved to install the tool, it is not possible; neither as app, nor via homebrew.

Environment:
MacOS 11.1
Xcode Version 12.3 (12C33)

When installing as App according to the instructions (download, unzip, move to programs, start), no entry for Xcode appears in system settings.

When installing with brew, this message is displayed:

brew install https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML/main/swiftplantuml.rb
Traceback (most recent call last):
brew extract or brew create and brew tap-new to create a formula file in a tap on GitHub instead.: Invalid usage: Non-checksummed download of swiftplantuml formula file from an arbitrary URL is unsupported! (UsageError)
brew extract or brew create and brew tap-new to create a formula file in a tap on GitHub instead.: Invalid usage: Non-checksummed download of swiftplantuml formula file from an arbitrary URL is unsupported! (UsageError)

Any way to get around this?

Support of nested types

Enumerations are often created to support a specific class or structureโ€™s functionality. Similarly, it can be convenient to define utility classes and structures purely for use within the context of a more complex type. To accomplish this, Swift enables you to define nested types, whereby you nest supporting enumerations, classes, and structures within the definition of the type they support.

To nest a type within another type, write its definition within the outer braces of the type it supports. Types can be nested to as many levels as are required.

Nested Types do not get rendered by SwiftPlantUML

Ideally, there would be an option to render them.

Example Input

public struct OuterOuter {
    public struct Outer {
        public enum Inner {}
    }
}

Possible Output

PossibleOutput

documentation badge percentage

Sorry to bother with a question not directly related to the project, but how do you get the percentage on your documentation badge (at the README.md)? is it generated by jazzy? is it a real calculated value or is it hardcoded? I could not find where it was calculated.

Screenshot 2022-05-05 at 13 08 45

Syntax error in protocol multiple inheritance with '&' separator

Description

Converting a protocol code that inherits multiple protocols separated by '&' into PlantUML text results in a syntax error.
This does not occur when they are separated by ','.

Steps to Reproduce

Separated by "&"

input

public protocol ResponseSerializer<SerializedObject>: DataResponseSerializerProtocol & DownloadResponseSerializerProtocol { }

output

DataResponseSerializerProtocol & DownloadResponseSerializerProtocol <|.. ResponseSerializer : inherits

-> Error occurred

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-02-18 แ„‹แ…ฉแ„’แ…ฎ 11 05 20

Separated by ","

input

public protocol ResponseSerializer<SerializedObject>: DataResponseSerializerProtocol, DownloadResponseSerializerProtocol { }

output

DataResponseSerializerProtocol <|.. ResponseSerializer : conforms to
DownloadResponseSerializerProtocol <|.. ResponseSerializer : conforms to

It seems that it should be modified to work the same as when separated by ',' even when separated by '&' ๐Ÿค”

Error type in composed struct

Hi!

First of all, I want to thank you for your work, I really love โค๏ธ this project, I've been waiting for a tool like this (sourcery+plantuml) for quite a long time!

Next, I've found a problem that I don't if it's a bug or I'm missing something.

I've two files:

Container.swift
public struct Container: Codable {

    public var url: String
    public var headers: ContainerHeaders?

    public init(url: String, headers: ContainerHeaders? = nil) {
        self.url = url

        self.headers = headers
    }

    public enum CodingKeys: String, CodingKey {
        case url
        case headers
    }
}
ContainerHeaders.swift
public struct ContainerHeaders: Codable {

    public var name: String
    public var value: String

    public init(name: String, value: String) {
        self.name = name
        self.value = value
    }
}

With those, I try to generate a diagram using this command

swiftplantuml classdiagram  Container.swift ContainerHeaders.swift --sdk $(xcrun --show-sdk-path -sdk macosx) --output consoleOnly

Which results in an error, as it can bee seen in the output given:

@startuml
' STYLE START
hide empty members
skinparam shadowing false
' STYLE END


class "Container" as Container << (S, SkyBlue) struct >> {
  +url : String
  +headers : <<error type>>
  +init(url:headers:)
}
class "ContainerHeaders" as ContainerHeaders << (S, SkyBlue) struct >> {
  +name : String
  +value : String
  +init(name:value:)
}
Container --|> Codable : inherits
ContainerHeaders --|> Codable : inherits

@enduml

So, is this a bug or do I miss something?

Excluded and included files have no effect

I have files structured in this way:

โฏ tree -a
.
โ”œโ”€โ”€ .DS_Store
โ”œโ”€โ”€ .swiftplantuml.yml
โ”œโ”€โ”€ also_ok
โ”‚ย ย  โ””โ”€โ”€ swift.swift
โ”œโ”€โ”€ ok
โ”‚ย ย  โ””โ”€โ”€ swift.swift
โ””โ”€โ”€ unwanted
    โ””โ”€โ”€ swift.swift

4 directories, 5 files

Each swif.swift file contains one protocol named after the directory.

Configuration file contains:

files:
  include:
  - ok
  - also_ok
  exclude:
  - unwanted

Then swiftplantuml . --verbose output is as follows:

14:03:28.543 ๐Ÿ’™ INFO ConfigurationProvider.readSwiftConfig():28 - search for config file in current directory with name '.swiftplantuml.yml'
14:03:28.546 ๐Ÿ’™ INFO ConfigurationProvider.readSwiftConfig():30 - .swiftplantuml.yml file found
14:03:28.546 ๐Ÿ’™ INFO ClassDiagram.run():65 - SDK: no SDK path provided
14:03:28.546 ๐Ÿ’™ INFO FileCollector.getFiles():24 - paths will be ignored in favor of configuration (files:include: also_ok, ok)
14:03:28.636 ๐Ÿ’š DEBUG SyntaxStructureProvider.create():31 - read file:///{redacted}/unwanted/swift.swift  in 0.08880603313446045
14:03:28.636 ๐Ÿ’š DEBUG SyntaxStructureProvider.create():31 - read file:///{redacted}/also_ok/swift.swift  in 0.0003809928894042969
14:03:28.637 ๐Ÿ’š DEBUG SyntaxStructureProvider.create():31 - read file:///{redacted}/ok/swift.swift  in 0.0004260540008544922
14:03:28.637 ๐Ÿ’š DEBUG PlantUMLScript.init():60 - PlantUML script created in 1.5974044799804688e-05 seconds
14:03:28.637 ๐Ÿ’™ INFO ClassDiagramGenerator.logProcessingDuration():61 - Class diagram generated in 0.08993899822235107 seconds and will be presented now

It seems like the exclude option is either not printed or totally ignored here:
14:03:28.546 ๐Ÿ’™ INFO FileCollector.getFiles():24 - paths will be ignored in favor of configuration (files:include: also_ok, ok)
and even though include option is specified it still creates diagram for types found in unwanted directory:
14:03:28.636 ๐Ÿ’š DEBUG SyntaxStructureProvider.create():31 - read file:///{redacted}/unwanted/swift.swift in 0.08880603313446045

The same behaviour is for: swiftplantuml . --verbose --exclude unwanted, without configuration file:

14:23:28.450 ๐Ÿ’™ INFO ConfigurationProvider.readSwiftConfig():28 - search for config file in current directory with name '.swiftplantuml.yml'
14:23:28.456 ๐Ÿ’™ INFO ConfigurationProvider.decodeYml():49 - cannot find/read yaml file
14:23:28.456 ๐Ÿ’™ INFO ConfigurationProvider.readSwiftConfig():33 - return default configuration
14:23:28.456 ๐Ÿ’™ INFO ClassDiagram.run():65 - SDK: no SDK path provided
14:23:28.551 ๐Ÿ’š DEBUG SyntaxStructureProvider.create():31 - read file:///{redacted}/unwanted/swift.swift  in 0.09683799743652344
14:23:28.552 ๐Ÿ’š DEBUG SyntaxStructureProvider.create():31 - read file:///{redacted}/also_ok/swift.swift  in 0.0007170438766479492
14:23:28.553 ๐Ÿ’š DEBUG SyntaxStructureProvider.create():31 - read file:///{redacted}/ok/swift.swift  in 0.0006769895553588867
14:23:28.553 ๐Ÿ’š DEBUG PlantUMLScript.init():60 - PlantUML script created in 7.009506225585938e-05 seconds
14:23:28.553 ๐Ÿ’™ INFO ClassDiagramGenerator.logProcessingDuration():61 - Class diagram generated in 0.09848403930664062 seconds and will be presented now

In both cases, the graph is as follows:

@startuml
' STYLE START
hide empty members
skinparam shadowing false
' STYLE END
set namespaceSeparator none


class "Unwanted" as Unwanted << (P, GoldenRod) protocol >> {  
}
class "AlsoOk" as AlsoOk << (P, GoldenRod) protocol >> {  
}
class "Ok" as Ok << (P, GoldenRod) protocol >> {  
}


@enduml

The expected output would be to not read files from unwanted directory (regardless if it's specified in excluded or not), thus types defined there won't end up in the diagram.

Throws error when passing in paths

its throws an error saying :Could not read contents of...
this is the command line i entered : swiftplantuml classdiagram Views Model Controllers

Incorrect inheritance/extensions when parent class is not scanned first

If subclasses and/or extensions are scanned before their parent class then the class diagram gets generated incorrectly.

Example

internal class aSublcass: aClass {}

internal extension aClass {
    var extComputedProperty: String { "" }
    private func extFunction() {}
}

class aClass {
    var computedProperty: String { "" }
    func aFunction() {}
}

internal extension aClass {
    private func extFunction2()
}

Current (unexpected) output

incorrect

Expected output

correct

Support nested types in extensions and extending nested types

Related: MarcoEidinger/SwiftPlantUML-Xcode-Extension#26

Example

public enum APublic {
    public enum BPublic {
        public static func publicFuncDefinedInType() {}
    }
}

// Extension is declared public, so each top level member "inherits" that access level.
public extension APublic.BPublic {
    
    // Hence this is public even if it is not annotated
    static func hasAccessLevel() -> String { return "public" }
    
    // Also this class is public
    class CPublic { // NEW: nested type defined in extension
        // However, its members must be annotated. This is public
        public static func publicFunc() {}
        
        // This is internal because no explicit access level modifier is used
        static func internalFunc() {}
    }
}

// Extension has no explicit access level modifier and therefore it is internal
// so each top level member "inherits" that access level.
extension APublic.BPublic {
    
    public static func publicFuncAddedInExtenion() {} // NEW: extending nested type
    
    class CInternal {
        public static func publicFunc() {}
    }
}

extension APublic.BPublic.CPublic {
    public static func publicFuncAddedInExtenion() {} // NEW: extending nested type

    static func internalFuncAddedInExtenion() {}
    
    private static func privateFuncAddedInExtenion() {}
}

private extension APublic.BPublic.CInternal {
    private class DPrivate {
        init() {}
    }
    
    // compiles but `DPublic` will not be accessible as it is defined in a private extension
    public class DPublic {
        public init() {}
    }
}

Expected output

Note: extensions will always be rendered/processed no matter what elements.havingAccessLevel you specify in configuration.

  • Reason: extensions may not have an explicit access-level modifier, i.e. any type members added in an extension have the same default access level as type members declared in the original type being extended but also it is possible to set explicitly set an access level for type member declaration.
  • Example: extension APublic.BPublic adding new type members have a default access level of internal but you can add also public or private type members. Hiding extension APublic.BPublicwhen specifyingelements.havingAccessLevel = public` would potentially result in loss of information as the extension may have added public-type members
elements:
  showNestedTypes: true
  showExtensions: all
  havingAccessLevel:
  - public
  - internal
  - private

Result


elements:
  showNestedTypes: true
  showExtensions: all
  havingAccessLevel:
  - public
  - internal

Result


elements:
  showNestedTypes: true
  showExtensions: all
  havingAccessLevel:
  - public

Result


elements:
  showNestedTypes: true
  showExtensions: merged
  havingAccessLevel:
  - public
  - internal
  - private

Result


elements:
  showNestedTypes: true
  showExtensions: merged
  havingAccessLevel:
  - public
  - internal

Result


elements:
  showNestedTypes: true
  showExtensions: merged
  havingAccessLevel:
  - public

Result


elements:
  showNestedTypes: false
  showExtensions: all
  havingAccessLevel:
  - public
  - internal
  - private

Result

No access level for extension members if no explicit

Members of an extension do not show an access level indicator if there is no explicit access level modifier.

class aClass {
    var computedProperty: String {}
    func aFunction() {}
}

extension aClass {
    var extComputedProperty: String { "" }
    func extFunction()
}

The implicit access level for extComputedProperty and extFunction is internal. Therefore indicator ~ shall be represented in PlantUMLScript.

Current (unexpected) output

@startuml
' STYLE START
hide empty members
skinparam shadowing false
' STYLE END


class "aClass" as aClass << (C, DarkSeaGreen) >> { 
  ~computedProperty : String
  ~aFunction() 
}
class "aClass" as aClass0 << (X, Orchid) extension >> { 
  extComputedProperty : String
  extFunction()
}

aClass <.. aClass0 : ext
@enduml

Expected output

@startuml
' STYLE START
hide empty members
skinparam shadowing false
' STYLE END


class "aClass" as aClass << (C, DarkSeaGreen) >> { 
  ~computedProperty : String
  ~aFunction() 
}
class "aClass" as aClass0 << (X, Orchid) extension >> { 
  ~extComputedProperty : String
  ~extFunction()
}

aClass <.. aClass0 : ext
@enduml

Merging extensions to avoid clutter

Today it is possible to show or hide extensions. There should be a third option, i.e. to merge extensions (with their known type)

Even if extensions are merged, the extension members (computed properties, function) should be distinguishable from the main type definition. This can be achieved with a visual indicator.

Show Extensions (Default) Merge Extensions (NEW) Hide Extensions
ShowExtensions MergeExtensions HideExtensions
Clutter but represents codebase accurately Reduced clutter. No loss of information No clutter but loss of information

Error in generated output

I tried to generate the diagrams for a large project. I couldn't see the result in my browser.
So, I tried saving the console report in a file and then running plantuml to get the diagram.
But not it gives me this error:
Error line 9428 in file: diagram.plant
and here is that line:
Handler<Void, [SelectedTenant]> <|-- FetchTenantHandler : inherits
Is there anything wrong with this line?

Incorrect relationship label when protocol is not scanned first

If subclasses and/or extensions are scanned before their parent class then the class diagram gets generated incorrectly.

Example

class aClass: aProtocol {
    var computedProperty: String { "" }
    func aFunction() {}
}

protocol aProtocol {
    func aProtFunction() {}
}

Current (unexpected) output

protocolNotFirst

Expected output

protocolFirst

Built-in themes from PlantUML

Previously it was possible to include a 3rd party theme through the !include directive and that was reflected in SwiftPlantUML by includeRemoteURL option in yml configuration.

Nowadays PlantUML has !theme directive and ships with many built-in themes. See https://plantuml.com/theme for further details

The goal is to cover those built-in themes

Can this be used to create a call graph?

Hello,

I'm seeking a method to visualize all the classes in my project but also identify dependencies \ relationship. (basically which class calls another.)

Is it possible to achieve this with the tool?
For example, scanning Car.swift will produce something similar to

+-------------------+        +-------------------+       +----------------------+
|   Music           |  <--   |   Car             | -->   |   Engine             |
+-------------------+        +-------------------+       +----------------------+
| + startMusic()    |        | + startCar()      |       | + startEngine()      |
+-------------------+        +-------------------+       +----------------------+
class Car {
    static func startCar() {
        print("Car started")
        Engine.startEngine()
        Music.startMusic()
    }
}
class Music {
    static func startMusic() {
        print("Music started")
    }
}
class Engine {
    static func startEngine() {
        print("Engine started")
    }
}

Request URI is too long

Hello,
I am not quite sure if it is a bug or something to improve, but I am trying to export a diagram for the whole project. I get the URL error below:
Request-URI Too Long
The requested URL's length exceeds the capacity limit for this server.
Apache/2.4.41 (Ubuntu) Server at planttext.com Port 443

Url is, really pages long because of the codebase size, but I don't know if it is possible to make it otherwise. Should I use the CLI tool for every module or is there a better way of doing it?

Note: I found the output option; if I make it console-only, I can use it. It sounds good to have and I get the UML text exported, however, maybe it is possible to fix the browser options somehow? Wondering if you had the problem in mind.

Also note, planttext cannot create the big UML diagram that I exported so it is their problem actually.

Thanks in advance, the project is really cool I would like to use it in my career.

Turns out whitespace is important

When setting relationships between elements, it turns out that A+--B and A+--B yield different results visually. Not using spaces even results in errors. Please have a look at the attached images. SwiftPlantUML doesn't include spaces in the relationships.

no_space with_space

illegal hardware instruction swiftplantuml

Repository i'm trying to get UML of:
https://github.com/WalletConnect/WalletConnectSwift

Installed SwiftPlantUML via brew on macOS

Commands i tried:

  • swiftplantuml
  • swiftplantuml classdiagram
  • swiftplantuml classdiagram Sources

Error i get:

SourceKittenFramework/library_wrapper.swift:31: Fatal error: Loading sourcekitd.framework/Versions/A/sourcekitd failed

illegal hardware instruction  swiftplantuml classdiagram Sources

Configuration File to influence generation of PlantUML script / diagram

Configure generation of PlantUML script and with a configuration file (.yml) .

  • specify built-in PlantUML options, e.g. skinparam shall be covered.
  • allow SwiftPlantUML specific options, e.g. including elements (class, struct, enum, ...) in PlantUML script based on their access level.

Example:

output: browser
files:
  include:
  - Sources/SwiftPlantUMLFramework/Plant*.swift
  exclude:
  - Tests
generateElementsWithAccessLevel:
- public
- internal
- private
generateMembersWithAccessLevel:
- public
- internal
- private
showGenerics: true
hideShowCommands:
- hide empty members
skinparamCommands:
- skinparam shadowing false
relationships:
  struct:
    lineStyle: bold
    lineColor: AliceBlue
    textColor: AntiqueWhite
relationshipLabels:
  inheritance: inherits
  realize: confirms to
  dependency: ext
stereotypes:
  class:
    spot:
      character: C
      color: DarkSeaGreen
  struct:
    name: struct
    spot:
      character: S
      color: SkyBlue
  extension:
    name: extension
    spot:
      character: X
      color: Orchid
  enum:
    name: enum
    spot:
      character: E
      color: LightSteelBlue
  protocol:
    name: protocol
    spot:
      character: P
      color: GoldenRod

The plan is to support a single configuration file for the file scanning process. Multiple/Nested configuration files like in SwiftLint (Reference) is not planned.

Command not found when trying to run from command-line

After installing with brew, running swiftplantuml classdiagram --help produces command not found: swiftplantuml. There is no executable in usr/local/bin (or anywhere on my system that I can find), only an app is installed in the Applications directory and Xcode extension added

canot build the CLI tool

I tried to build the CLI tool as described by I get the following error (MacOS 10.15.7):
SwiftPlantUML git:(main) make install
Fetching https://github.com/jpsim/Yams.git
Fetching https://github.com/jpsim/SourceKitten
Fetching https://github.com/apple/swift-argument-parser.git
Fetching https://github.com/drmohundro/SWXMLHash.git
Cloning https://github.com/drmohundro/SWXMLHash.git
Resolving https://github.com/drmohundro/SWXMLHash.git at 5.0.1
Cloning https://github.com/apple/swift-argument-parser.git
Resolving https://github.com/apple/swift-argument-parser.git at 0.3.2
Cloning https://github.com/jpsim/SourceKitten
Resolving https://github.com/jpsim/SourceKitten at 0.31.0
Cloning https://github.com/jpsim/Yams.git
Resolving https://github.com/jpsim/Yams.git at 4.0.4
[15/15] Linking swiftplantuml
install: : No such file or directory
make: *** [install] Error 71

Feature request: find relationship chains between 2 classes/structs

In my case I have a class-container (Class1) and another class (Class2) which is not directly linked with Class1.

Now I need to figure out how to pass Class2 to Class1. It seems the simplest way is:
1)find all the paths between Class1 and Class2 in this generated graph with the specified max lenght in text format
2)find the class container which contains Class1 and Class2 objects (directly or indirectly)

Is it possible to do with your tool?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.