mermaid-js / mermaid

Generation of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown
https://mermaid.js.org
MIT License
71.83k stars 6.52k forks source link

[Class Diagram] Missing return type with multiple generic parameters #3188

Closed rami3l closed 1 year ago

rami3l commented 2 years ago

Describe the bug When trying to write the Class Diagram description below, I'd expect the method line to be rendered as +dict() dict<K, V>:

classDiagram

class Foo {
    +dict() dict~K, V~
}
classDiagram

class Foo {
    +dict() dict~K, V~
}

... but instead I got the following:

image

ashishjain0512 commented 2 years ago

@rami3l Thanks for reporting this. This sure is a worthy bug to be fixed. I will approve this, and we will wait for the PR fix.

h0lg commented 1 year ago

Yes please! +1

Even worse, if one of the generic parameters is itself a generic type - like in Dict~K, List~V~~ - generation of the diagram fails with a stack overflow:

Uncaught (in promise) RangeError: Maximum call stack size exceeded
    at String.replace (<anonymous>)
    at dc (common.ts:164:36)
    at dc (common.ts:167:12)
    at dc (common.ts:167:12)
    at dc (common.ts:167:12)
    ...

with the line numbers and columns referring to https://cdnjs.cloudflare.com/ajax/libs/mermaid/src/diagrams/common/common.ts

Ethan826 commented 1 year ago

I'd love to see a fix too, and am grateful for this cool library! In the meantime I'm using this disgusting hack, which works for multiple generics.

classDiagram

    class FooService~R, E, A~ {
      query(queryParams QueryParams): ReaderTaskEither~R,E,Quux~A~~
    }
    <<interface>> FooService
Will-Low commented 1 year ago

It seems to be reading left angle brackets as the beginning of HTML tags. If you use &lt; anywhere that you need a left angle bracket, it seems to avoid this issue. I also confirmed that it works for nested generics.

classDiagram
    class Cache~K, V~{
        -map: HashMap&lt;K, V>
        +add(key: K)
        +get(key: &K) Option~V~
    }
classDiagram
    class Cache~K, V~{
        -map: HashMap&lt;K, V>
        +add(key: K)
        +get(key: &K) Option~V~
    }
rami3l commented 1 year ago

Oh, no! The original post now gets me an error, which is even worse:

Unable to render rich display

Maximum call stack size exceeded

For more information, see https://docs.github.com/get-started/writing-on-github/working-with-advanced-formatting/creating-diagrams#creating-mermaid-diagrams
h0lg commented 1 year ago

It seems to be reading left angle brackets as the beginning of HTML tags. If you use &lt; anywhere that you need a left angle bracket, it seems to avoid this issue. I also confirmed that it works for nested generics.

classDiagram
    class Cache~K, V~{
        -map: HashMap&lt;K, V>
        +add(key: K)
        +get(key: &K) Option~V~
    }

Using &lt; seems sketchy in most cases as it seems undocumented and also doesn't work for relation label syntax, for which the ; is verboten, see https://github.com/mermaid-js/mermaid/blob/6ccdc2bd01d1459e47eba4b560116c2e048f0ac2/packages/mermaid/src/diagrams/class/parser/classDiagram.jison#L113

h0lg commented 1 year ago

Unicode angle brackets seem to be working fine for relation labels, class labels, generics return types and method arguments, and even C#-style generic method type arguments.

classDiagram
direction LR

class Contract_Metadata ["Contract+Metadata"] {

}

FluentMetadata_ClassMetadata_T <|-- Contract_Metadata : ClassMetadata❰Contract❱
class FluentMetadata_ClassMetadata_T ["ClassMetadata❰T❱"]

Contract_Metadata : #IClassBuilder❰Contract❱ Class
Contract_Metadata : #Property❰TResult❱(Expression❰Func❰Contract, TResult❱❱ expression) IProperty❰Contract, TResult❱
Contract_Metadata : #CopyMetadataFrom❰TBaseType❱() void
Contract_Metadata : -GetTypeBuilder❰TBuilder❱()$ TypeMetadataBuilder❰TBuilder❱

Stylewise, 〈You〉 ❬Can❭ ❰Pick❱ ⟨Your⟩ 〈Poison〉.

h0lg commented 1 year ago

Because this issue goes syntactically into the C# and .Net direction, let me plug the project that got me interested in it: netAmermaid - an automated documentation tool for visually exploring .NET assemblies along type relations using rapid diagramming. HTH.

jgreywolf commented 1 year ago

The main issue here is the use of a comma inside the generic definition. ie: between ~ and ~

I am working on a fix for this from another issue as well

Yury-Fridlyand commented 1 year ago

+1

class foo {
  +accept(Visitor~R, C~, C) R
}

causes

image

class foo {
  +accept(Visitor<R, C>, C) R
}

is rendered as

image

Thanks for the workaround, that works:

class foo {
  +accept(Visitor&lt;R, C>, C) R
}

image

simomosi commented 1 year ago

I have the same problem on version 10.1.0

The following code gives compilation errors (Maximum call stack size exceeded)

    class Foo {
        Map~string, int~ bar
    }
Error: Evaluation failed: Error: Maximum call stack size exceeded
    at pptr://__puppeteer_evaluation_script__:45:17
    at ExecutionContext._ExecutionContext_evaluate (file:///home/simomosi/code/dynamic-forms/node_modules/puppeteer-core/lib/esm/puppeteer/common/ExecutionContext.js:254:15)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async ExecutionContext.evaluate (file:///home/simomosi/code/dynamic-forms/node_modules/puppeteer-core/lib/esm/puppeteer/common/ExecutionContext.js:143:16)
    at async CDPJSHandle.evaluate (file:///home/simomosi/code/dynamic-forms/node_modules/puppeteer-core/lib/esm/puppeteer/common/JSHandle.js:56:16)
    at async CDPElementHandle.$eval (file:///home/simomosi/code/dynamic-forms/node_modules/puppeteer-core/lib/esm/puppeteer/common/ElementHandle.js:86:24)
    at async renderMermaid (file:///home/simomosi/code/dynamic-forms/node_modules/@mermaid-js/mermaid-cli/src/index.js:241:22)
    at async parseMMD (file:///home/simomosi/code/dynamic-forms/node_modules/@mermaid-js/mermaid-cli/src/index.js:213:20)
    at async run (file:///home/simomosi/code/dynamic-forms/node_modules/@mermaid-js/mermaid-cli/src/index.js:508:20)
    at async cli (file:///home/simomosi/code/dynamic-forms/node_modules/@mermaid-js/mermaid-cli/src/index.js:179:3)

The following code does not render angle brackets

    class Foo {
        Map<string, int> bar
    }

Workaround: using unicode characters (thank you @h0lg )

    class Foo {
        Map❬string, int❭ bar
    }
ParticleG commented 1 year ago

One year later and this still haven't been fixed

jgreywolf commented 1 year ago

I may close this in favor of #3287 - as these are symptoms of the same issue. I am working on this however