Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
pierre3 committed Mar 2, 2024
2 parents e3605c4 + 842ab60 commit 7dfe158
Show file tree
Hide file tree
Showing 81 changed files with 1,918 additions and 778 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,4 @@ ModelManifest.xml

# Intellij files
.idea
/test/SourceGeneratorTest/generated-uml

7 changes: 7 additions & 0 deletions PlantUmlClassDiagramGenerator.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SourceGeneratorTest", "test
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlantUmlClassDiagramGenerator.SourceGenerator", "src\PlantUmlClassDiagramGenerator.SourceGenerator\PlantUmlClassDiagramGenerator.SourceGenerator.csproj", "{26525450-7352-470B-B556-34269D828BD8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceGeneratorTest.Library", "test\SourceGeneratorTest.Library\SourceGeneratorTest.Library.csproj", "{CB61E9FE-757A-4BED-BD45-1E6D6180740F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -54,6 +56,10 @@ Global
{26525450-7352-470B-B556-34269D828BD8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26525450-7352-470B-B556-34269D828BD8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26525450-7352-470B-B556-34269D828BD8}.Release|Any CPU.Build.0 = Release|Any CPU
{CB61E9FE-757A-4BED-BD45-1E6D6180740F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB61E9FE-757A-4BED-BD45-1E6D6180740F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB61E9FE-757A-4BED-BD45-1E6D6180740F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB61E9FE-757A-4BED-BD45-1E6D6180740F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -65,6 +71,7 @@ Global
{73621E9E-991E-4930-A78A-B6BEAADF15B6} = {BA69B69C-C802-4077-B693-8845A154AD13}
{BC099683-E481-4BA2-9278-6ABDB28534DC} = {D0EC41DE-8A29-463D-8915-CB623E02CDA0}
{26525450-7352-470B-B556-34269D828BD8} = {BA69B69C-C802-4077-B693-8845A154AD13}
{CB61E9FE-757A-4BED-BD45-1E6D6180740F} = {D0EC41DE-8A29-463D-8915-CB623E02CDA0}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F8F6C51C-3BD1-44B3-803A-176BCC69458E}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using PlantUmlClassDiagramGenerator.SourceGenerator.Extensions;

namespace PlantUmlClassDiagramGenerator.SourceGenerator.Associations;

Expand All @@ -19,12 +19,16 @@ public override string ToString()
var nodeLabel = Label == "" ? "" : $" : {Label}";
var rootLabel = RootLabel == "" ? "" : $" \"{RootLabel}\"";
var leafLabel = LeafLabel == "" ? "" : $"\"{LeafLabel}\" ";
var rootName = RootSymbol.MetadataName.Contains('`')
? $"\"{RootSymbol.MetadataName}\""
: RootSymbol.MetadataName;
var leafName = LeafSymbol.MetadataName.Contains('`')
? $"\"{LeafSymbol.MetadataName}\""
: LeafSymbol.MetadataName;
var rootName = RootSymbol.GetMetadataName();
if (rootName.Contains('`'))
{
rootName = $"\"{rootName}\"";
}
var leafName = LeafSymbol.GetMetadataName();
if (leafName.Contains('`'))
{
leafName = $"\"{leafName}\"";
}
return $"{rootName}{rootLabel} {Kind.Node} {leafLabel}{leafName}{nodeLabel}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace PlantUmlClassDiagramGenerator.SourceGenerator.Extensions;

public static class EventSymbolExtensions
public static class IEventSymbolExtensions
{

public static string GetTypeString(this IEventSymbol symbol)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace PlantUmlClassDiagramGenerator.SourceGenerator.Extensions;

public static class FieldSymbolExtensions
public static class IFieldSymbolExtensions
{
public static string GetTypeString(this IFieldSymbol symbol)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace PlantUmlClassDiagramGenerator.SourceGenerator.Extensions;

public static class MethodSymbolExtensions
public static class IMethodSymbolExtensions
{
public static string GetName(this IMethodSymbol symbol)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace PlantUmlClassDiagramGenerator.SourceGenerator.Extensions;

public static class NamedTypeSymbolExtensions
public static class INamedTypeSymbolExtensions
{
public static string GetTypeKindString(this INamedTypeSymbol symbol)
{
Expand Down Expand Up @@ -54,15 +54,18 @@ public static string GetTypeArgumentsString(this INamedTypeSymbol symbol)
: "";
}

public static bool ContainsObjectCreationInConstructor(this INamedTypeSymbol symbol, ITypeSymbol type)
public static bool ContainsObjectCreationInConstructor(this INamedTypeSymbol symbol, string memberName)
{
return symbol.Constructors
.SelectMany(x => x.DeclaringSyntaxReferences)
.Select(syntaxRef => syntaxRef.GetSyntax())
.OfType<ConstructorDeclarationSyntax>()
.SelectMany(syntax => syntax.Body?.DescendantNodes())
.OfType<ObjectCreationExpressionSyntax>()
.Any(node => node.Type.ToString() == type.Name);
.OfType<AssignmentExpressionSyntax>()
.Any(node =>
node.Left is IdentifierNameSyntax left
&& left.Identifier.Text == memberName
&& node.Right is ObjectCreationExpressionSyntax);
}

public static IEnumerable<INamedTypeSymbol> ToSingleEnumerable(this INamedTypeSymbol symbol)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace PlantUmlClassDiagramGenerator.SourceGenerator.Extensions;

public static class PropertySymbolExtensions
public static class IPropertySymbolExtensions
{

public static string GetTypeString(this IPropertySymbol symbol)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Microsoft.CodeAnalysis;

namespace PlantUmlClassDiagramGenerator.SourceGenerator.Extensions;

public static class ISymbolExtensions
{
public static readonly string AutoGeneratedNamespace = "PlantUmlClassDiagramGenerator.SourceGenerator.Attributes";
public static readonly string PlantUmlDiagramAttributeName = $"{AutoGeneratedNamespace}.PlantUmlDiagramAttribute";
public static readonly string PlantUmlIgnoreAttributeName = $"{AutoGeneratedNamespace}.PlantUmlIgnoreAttribute";

public static bool HasPlantUmlDiagramAttribute(this ISymbol symbol)
=> symbol.GetAttributes().Any(attr => attr.AttributeClass?.ToString() == PlantUmlDiagramAttributeName);

public static bool HasPlantUmlIgnoreAttribute(this ISymbol symbol)
=> symbol.GetAttributes().Any(attr => attr.AttributeClass?.ToString() == PlantUmlIgnoreAttributeName);

public static bool NamespaceStartsWith(this ISymbol symbol, string value)
=> symbol.ContainingNamespace.ToString().StartsWith(value);

public static object? GetPlantUmlDiagramAttributeArg(this ISymbol symbol, string argName)
{
var attribute = symbol.GetAttributes().FirstOrDefault(attr => attr.AttributeClass?.ToString() == PlantUmlDiagramAttributeName);
return attribute?.NamedArguments.FirstOrDefault(arg => arg.Key == argName).Value.Value;
}

public static bool IsAutoGeneratedSymbol(this ISymbol symbol)
{
return symbol.ContainingNamespace.ToString() == AutoGeneratedNamespace
|| symbol.ContainingNamespace.ToString().Contains("<");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Microsoft.CodeAnalysis;

namespace PlantUmlClassDiagramGenerator.SourceGenerator.Extensions;

public static class ITypeSymbolExtensions
{
public static string GetMetadataName(this ITypeSymbol typeSymbol, string punctuation = "::")
{
var parts = typeSymbol.ToDisplayParts(
new SymbolDisplayFormat(
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypes));
var containingTypes = parts
.Take(parts.Length -1)
.Where(p => p.Kind != SymbolDisplayPartKind.Punctuation)
.Select(p => p.ToString());
return string.Join(punctuation, [.. containingTypes, typeSymbol.MetadataName]);
}

public static string GetTypeName(this ITypeSymbol symbol)
{
return symbol.ToDisplayString(
symbol.NullableAnnotation == NullableAnnotation.Annotated
? NullableFlowState.MaybeNull
: NullableFlowState.None,
SymbolDisplayFormat.MinimallyQualifiedFormat);
}

public static string GetOutputFilePath(this ITypeSymbol symbol, string basePath)
{
return Path.Combine([basePath,
symbol.ContainingAssembly.Name,
.. symbol.ContainingNamespace.ToString().Replace("<", "").Replace(">", "").Split('.'),
symbol.GetMetadataName(".") + ".puml"]);
}
}



This file was deleted.

109 changes: 109 additions & 0 deletions src/PlantUmlClassDiagramGenerator.SourceGenerator/GeneratorOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using PlantUmlClassDiagramGenerator.SourceGenerator.Extensions;
namespace PlantUmlClassDiagramGenerator.SourceGenerator;

public class GeneratorOptions(AnalyzerConfigOptionsProvider config, string assemblyName)
{

[Flags]
public enum Accessibilities
{
None = 0,
Public = 0x01,
Protected = 0x02,
Internal = 0x04,
ProtectedInternal = 0x08,
PrivateProtected = 0x10,
Private = 0x20,
All = Public | Protected | Internal | ProtectedInternal | PrivateProtected | Private
}

public string AssemblyName { get; set; } = assemblyName;
public string OutputDir { get; set; } = GetOutputDir(config);
public bool AttributeRequierd { get; set; } = GetAttributeRequierd(config);
public Accessibilities IncludeMemberAccessibilities { get; set; } = GetIncludeAccessibilities(config);
public Accessibilities ExcludeMemberAccessibilities { get; set; } = GetExcludeAccessibilities(config);

public static Accessibilities GetIncludeAccessibilities(AnalyzerConfigOptionsProvider config)
{
return GetAccessibilities(config, "build_property.PlantUmlGenerator_IncludeMemberAccessibilities", Accessibilities.All);
}

public static Accessibilities GetExcludeAccessibilities(AnalyzerConfigOptionsProvider config)
{
return GetAccessibilities(config, "build_property.PlantUmlGenerator_ExcludeMemberAccessibilities", Accessibilities.None);
}

private static Accessibilities GetAccessibilities(AnalyzerConfigOptionsProvider config, string optionName, Accessibilities defaultValue)
{
return config.GlobalOptions.TryGetValue(optionName, out var acc)
? (Enum.TryParse<Accessibilities>(acc, out var value)
? value
: defaultValue)
: defaultValue;
}

public static bool GetAttributeRequierd(AnalyzerConfigOptionsProvider config)
{
return !config.GlobalOptions.TryGetValue("build_property.PlantUmlGenerator_AttributeRequierd", out var requierd)
|| (!bool.TryParse(requierd, out var boolean)
|| boolean);
}

public static string GetOutputDir(AnalyzerConfigOptionsProvider config)
{
return config.GlobalOptions.TryGetValue("build_property.PlantUmlGenerator_OutputDir", out var path)
? path
: (config.GlobalOptions.TryGetValue("build_property.projectDir", out var dir)
? Path.Combine(dir, "generated-uml")
: "");
}

public bool DeclaredTypeFilter(INamedTypeSymbol symbol)
{
return !symbol.IsAutoGeneratedSymbol()
&& !symbol.HasPlantUmlIgnoreAttribute()
&& (!AttributeRequierd || symbol.HasPlantUmlDiagramAttribute());
}

public bool MemberTypeFilter(ISymbol memberSymbol, INamedTypeSymbol typeSymbol)
{
var i = typeSymbol.GetPlantUmlDiagramAttributeArg("IncludeMemberAccessibilities");
var e = typeSymbol.GetPlantUmlDiagramAttributeArg("ExcludeMemberAccessibilities");
var includes = i is not null
? (Accessibilities)i
: IncludeMemberAccessibilities;
var excludes = e is not null
? (Accessibilities)e
: ExcludeMemberAccessibilities;
return !memberSymbol.HasPlantUmlIgnoreAttribute()
&& HasAccessibility(memberSymbol, includes, excludes);
}

private static bool HasAccessibility(ISymbol symbol, Accessibilities includes, Accessibilities excludes)
{
return symbol.DeclaredAccessibility switch
{
Accessibility.Public
=> includes.HasFlag(Accessibilities.Public)
&& !excludes.HasFlag(Accessibilities.Public),
Accessibility.Protected
=> includes.HasFlag(Accessibilities.Protected)
&& !excludes.HasFlag(Accessibilities.Protected),
Accessibility.Internal or Accessibility.Friend
=> includes.HasFlag(Accessibilities.Internal)
&& !excludes.HasFlag(Accessibilities.Internal),
Accessibility.ProtectedOrInternal or Accessibility.ProtectedOrFriend
=> includes.HasFlag(Accessibilities.ProtectedInternal)
&& !excludes.HasFlag(Accessibilities.ProtectedInternal),
Accessibility.ProtectedAndInternal or Accessibility.ProtectedAndFriend
=> includes.HasFlag(Accessibilities.PrivateProtected)
&& !excludes.HasFlag(Accessibilities.PrivateProtected),
Accessibility.Private
=> includes.HasFlag(Accessibilities.Private)
&& !excludes.HasFlag(Accessibilities.Private),
_ => false
};
}
}
Loading

0 comments on commit 7dfe158

Please sign in to comment.