Skip to content

Commit

Permalink
Support for generating many to many association in mermaid-class-diag…
Browse files Browse the repository at this point in the history
…ram-from-csharp (#132)

Added support for merging two one to many composition into one many to many association in class diagrams
  • Loading branch information
ebjornset authored Nov 2, 2024
1 parent cccbefb commit a0fd97e
Show file tree
Hide file tree
Showing 14 changed files with 103 additions and 91 deletions.
23 changes: 22 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
{
"sarif-viewer.connectToGithubCodeScanning": "off"
"sarif-viewer.connectToGithubCodeScanning": "off",
"explorer.fileNesting.enabled": true,
"explorer.fileNesting.patterns": {
// shows *.feature.cs files as nested items
"*.feature": "${capture}.feature.cs"
},
"files.exclude": {
// excludes compilation result
"**/obj/": true,
"**/bin/": true
},
"cucumber.glue": [
// sets the location of the step definition classes
"src/develop/DryGen.*/Steps/**/*.cs"
],
"cucumber.features": [
// sets the location of the feature files
"src/develop/DryGen.*/Features/**/*.feature"
],
"dotnet.automaticallySyncWithActiveItem": true,
"csharp.preview.improvedLaunchExperience": true,
"dotnet.automaticallyCreateSolutionInWorkspace": false
}
12 changes: 0 additions & 12 deletions docs/templates/releasenotes/2024-10-29-v-2.0.0-prerelease.1.md

This file was deleted.

15 changes: 15 additions & 0 deletions docs/templates/releasenotes/yyyy-MM-dd-v-x.y.z.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.!.!.replace-token-for-release-notes-header.!.!.
> [!IMPORTANT]
> In v 2.x .Net 6 and .Net 7 will no longer be supported, since they're no longer supported by Microsoft.
### Improvements in this version
## Prerelease 2
- Added support for generating many to many association in `mermaid-class-diagram-from-csharp`.
## Prerelease 1 (2024-10-29)
- Fixed an issue where `mermaid-er-diagram-from-efcore` would fail when an input assebly referenced Asp.Net Core.
- Ie the .csproj file contained `<Project Sdk="Microsoft.NET.Sdk.Web">` or `<FrameworkReference Include="Microsoft.AspNetCore.App|All">` or referenced such an assembly.
- Added support for generating many to many relations in `mermaid-er-diagram-from-efcore`.
- Switched to [docfx](https://dotnet.github.io/docfx/) for generating the documentation.
- docfx uses .Net, so Ruby is no longer needed in the development toolchain

Have fun!
14 changes: 0 additions & 14 deletions src/DryGen.Core/AssemblyLoadException.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,10 @@
using System;
#if (NET6_0)
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
#endif

namespace DryGen.Core;

#if (NET6_0)
[Serializable]
#endif
public sealed class AssemblyLoadException : Exception
{
public AssemblyLoadException(string? message) : base(message)
{
}

#if (NET6_0)
[ExcludeFromCodeCoverage]
private AssemblyLoadException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
#endif
}
14 changes: 0 additions & 14 deletions src/DryGen.Core/InvalidContentException.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,10 @@
using System;
#if (NET6_0)
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
#endif

namespace DryGen.Core;

#if (NET6_0)
[Serializable]
#endif
public sealed class InvalidContentException : Exception
{
public InvalidContentException(string? message) : base(message)
{
}

#if (NET6_0)
[ExcludeFromCodeCoverage]
private InvalidContentException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
#endif
}
13 changes: 0 additions & 13 deletions src/DryGen.Core/TypeLoadException.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
using System;
#if (NET6_0)
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
#endif

namespace DryGen.Core;

#if (NET6_0)
[Serializable]
#endif
public sealed class TypeLoadException : Exception
{
public TypeLoadException(string? message) : base(message)
{
}

#if (NET6_0)
[ExcludeFromCodeCoverage]
private TypeLoadException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
#endif
}
14 changes: 0 additions & 14 deletions src/DryGen.Core/TypeMemberException.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,10 @@
using System;
#if (NET6_0)
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
#endif

namespace DryGen.Core;

#if (NET6_0)
[Serializable]
#endif
public sealed class TypeMemberException : Exception
{
public TypeMemberException(string? message) : base(message)
{
}

#if (NET6_0)
[ExcludeFromCodeCoverage]
private TypeMemberException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
#endif
}
23 changes: 23 additions & 0 deletions src/DryGen.MermaidFromCSharp/ClassDiagram/ClassDiagramClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ public void AddRelationship(
relationships.Add(relationShip);
}

public void RemoveRelationship(ClassDiagramRelationship relationship) {
relationships?.Remove(relationship);
}

public void RemoveBidirectionalRelationshipDuplicates()
{
relationships.RemoveAll(r =>
Expand All @@ -80,6 +84,25 @@ public void RemoveBidirectionalRelationshipDuplicates()
r.To.Relationships.Any(x => x.To == this && x.RelationsshipType == ClassDiagramRelationshipType.Aggregation));
}

public void MergeTwoOneToManyIntoOneMayToMany()
{
bool wasModified;
do
{
// Must use an outer loop since a self referencing many to many will modify the relationships collection and the enumeration will crash
wasModified = false;
foreach (var relationship in relationships.Where(x => x.RelationsshipType == ClassDiagramRelationshipType.Composition && !x.IsBidirectional)) {
var backRelationship = relationship.To.Relationships.FirstOrDefault(x => x.To == this && x.RelationsshipType == ClassDiagramRelationshipType.Composition && x != relationship);
if (backRelationship == null) {
continue;
}
relationship.MergeAsManyToManyWith(backRelationship);
wasModified = true;
break;
}
} while (wasModified);
}

internal void PromoteMethodToExtendedClass(ClassDiagramMethod method, ClassDiagramClass classDiagramClass)
{
methods.Remove(method);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ private void GenerateClassDiagramStructure(IEnumerable<ClassDiagramClass> classD
{
classDiagramClass.RemoveBidirectionalRelationshipDuplicates();
}
foreach (var classDiagramClass in classDiagramClasses)
{
classDiagramClass.MergeTwoOneToManyIntoOneMayToMany();
}
}

private static ClassDiagramClass[] ConvertExtensionMethodsToInstanceMethodsOnKnownTypes(IEnumerable<ClassDiagramClass> classDiagramClasses)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,11 @@ public ClassDiagramRelationship(
public string Label { get; set; }
public string PropertyName { get; }
public bool IsBidirectional { get; set; }

public void MergeAsManyToManyWith(ClassDiagramRelationship backRelationship) {
FromCardinality = ClassDiagramRelationshipCardinality.ZeroOrMore;
RelationsshipType = ClassDiagramRelationshipType.Association;
IsBidirectional = true;
To.RemoveRelationship(backRelationship);
}
}
15 changes: 0 additions & 15 deletions src/DryGen/OptionsException.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,10 @@
using System;

#if (NET6_0)
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
#endif

namespace DryGen;

#if (NET6_0)
[Serializable]
#endif
public sealed class OptionsException : Exception
{
public OptionsException(string message) : base(message)
{
}

#if (NET6_0)
[ExcludeFromCodeCoverage]
private OptionsException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
#endif
}
2 changes: 1 addition & 1 deletion src/develop/DryGen.ITests/reqnroll.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"enabled": true,
"filepath": ".specflow.livingdoc.data.json"
},
"stepAssemblies": [
"bindingAssemblies": [
{
"assembly": "DryGen.DevUtils"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -634,16 +634,42 @@ Scenario: Generates ER relations with labels when the property name and type nam
"""

Scenario: Generates self referencing many to many relationship. WIP
Scenario: Generates many to many relationship
Given this C# source code
"""
using System.Collections.Generic;
namespace Test
{
public class MyClassOne
{
public ICollection<MyClassTwo> AssociatedTo { get; } = [];
}
public class MyClassTwo
{
public ICollection<MyClassOne> AssociatedFrom { get; } = [];
}
}
"""
When I generate a Class diagram
Then I should get this generated representation
"""
classDiagram
class MyClassOne
class MyClassTwo
MyClassOne "*" <--> "*" MyClassTwo : associated to
"""

Scenario: Generates self referencing many to many relationship.
Given this C# source code
"""
using System.Collections.Generic;
namespace Test
{
public class MyClass
{
public ICollection<MyClass> MyClassesOne { get; } = [];
public ICollection<MyClass> MyClassesTwo { get; } = [];
public ICollection<MyClass> AssociatedTo { get; } = [];
public ICollection<MyClass> AssociatedFrom { get; } = [];
}
}
"""
Expand All @@ -652,8 +678,6 @@ Scenario: Generates self referencing many to many relationship. WIP
"""
classDiagram
class MyClass
MyClass *-- "*" MyClass : my classes one
MyClass *-- "*" MyClass : my classes two
MyClass "*" <--> "*" MyClass : associated to
"""

2 changes: 1 addition & 1 deletion src/develop/DryGen.UTests/reqnroll.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"enabled": true,
"filepath": ".specflow.livingdoc.data.json"
},
"stepAssemblies": [
"bindingAssemblies": [
{
"assembly": "DryGen.DevUtils"
}
Expand Down

0 comments on commit a0fd97e

Please sign in to comment.