Skip to content

Commit

Permalink
Merge pull request #103 from pierre3/feature/source-generator
Browse files Browse the repository at this point in the history
Feature/source generator 1.0.0
  • Loading branch information
pierre3 authored May 19, 2024
2 parents 8a21980 + fcbe7d4 commit 15cb93b
Show file tree
Hide file tree
Showing 55 changed files with 959 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
[Flags]
internal enum Accessibilities
{
NotSet = 0x8000,
None = 0,
Public = 0x01,
Protected = 0x02,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace PlantUmlClassDiagramGenerator.SourceGenerator.Options;

[Flags]
internal enum AssociationTypes
{
NotSet = 0x8000,
None = 0,
Inheritance = 0x01,
Realization = 0x02,
Property = 0x04,
Field = 0x08,
MethodParameter = 0x10,
Nest = 0x20,
All = Inheritance | Realization | Property | Field | MethodParameter | Nest
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace PlantUmlClassDiagramGenerator.SourceGenerator.Options;

public static class GeneratorAttributes
internal static class GeneratorAttributes
{
private static readonly string AutoGeneratedNamespace = "PlantUmlClassDiagramGenerator.SourceGenerator.Attributes";
private static readonly string PlantUmlDiagramAttributeName = $"{AutoGeneratedNamespace}.PlantUmlDiagramAttribute";
Expand Down Expand Up @@ -71,14 +71,14 @@ public static bool DeclaredTypeFilter(INamedTypeSymbol symbol)

public static bool MemberTypeFilter(ISymbol memberSymbol, INamedTypeSymbol typeSymbol)
{
var i = typeSymbol.GetPlantUmlDiagramAttributeArg("IncludeMemberAccessibilities");
var e = typeSymbol.GetPlantUmlDiagramAttributeArg("ExcludeMemberAccessibilities");
var includes = i is not null
? (Accessibilities)i
: AssemblyAttribute.GetIncludeMemberAttributes(typeSymbol);
var excludes = e is not null
? (Accessibilities)e
: AssemblyAttribute.GetExcludeMemberAttributes(typeSymbol);
var i = (Accessibilities)(typeSymbol.GetPlantUmlDiagramAttributeArg("IncludeMemberAccessibilities") ?? Accessibilities.NotSet);
var e = (Accessibilities)(typeSymbol.GetPlantUmlDiagramAttributeArg("ExcludeMemberAccessibilities") ?? Accessibilities.NotSet);
var includes = i.HasFlag(Accessibilities.NotSet)
? AssemblyAttribute.GetIncludeMemberAttributes(typeSymbol.ContainingAssembly)
: i;
var excludes = e.HasFlag(Accessibilities.NotSet)
? AssemblyAttribute.GetExcludeMemberAttributes(typeSymbol.ContainingAssembly)
: e;
return !memberSymbol.HasPlantUmlIgnoreAttribute()
&& HasAccessibility(memberSymbol, includes, excludes);
}
Expand Down Expand Up @@ -128,6 +128,15 @@ Accessibility.ProtectedAndInternal or Accessibility.ProtectedAndFriend
};
}

public static AssociationTypes DisableAssociationTypes(this INamedTypeSymbol symbol)
{
var t = (AssociationTypes)(symbol.GetPlantUmlDiagramAttributeArg("DisableAssociationTypes") ?? AssociationTypes.NotSet);
return t.HasFlag(AssociationTypes.NotSet)
? AssemblyAttribute.GetDisableAssociationTypesAttributes(symbol.ContainingAssembly)
: t;
}


private static class AssemblyAttribute
{
private static readonly IDictionary<IAssemblySymbol, ImmutableArray<INamedTypeSymbol>> extraAssociationTargets
Expand All @@ -142,6 +151,9 @@ private static readonly IDictionary<IAssemblySymbol, Accessibilities> includeMem
private static readonly IDictionary<IAssemblySymbol, Accessibilities> excludeMemberAccessibilities
= new Dictionary<IAssemblySymbol, Accessibilities>(SymbolEqualityComparer.Default);

private static readonly IDictionary<IAssemblySymbol, AssociationTypes> disableAssociationTypes
= new Dictionary<IAssemblySymbol, AssociationTypes>(SymbolEqualityComparer.Default);

public static ImmutableArray<INamedTypeSymbol> GetExtraAssociationTargets(INamedTypeSymbol symbol)
{
if (extraAssociationTargets.TryGetValue(symbol.ContainingAssembly, out var value))
Expand Down Expand Up @@ -174,40 +186,66 @@ public static bool HasPlantUmlDiagramAttribute(INamedTypeSymbol symbol)
}
}

public static Accessibilities GetIncludeMemberAttributes(INamedTypeSymbol symbol)
public static Accessibilities GetIncludeMemberAttributes(IAssemblySymbol assemblySymbol)
{
if (includeMemberAccessibilities.TryGetValue(symbol.ContainingAssembly, out var value))
if (includeMemberAccessibilities.TryGetValue(assemblySymbol, out var value))
{
return value;
}
else
{
var accessibilities = symbol.GetPlantUmlDiagramAttributeArg("IncludeMemberAccessibilities") is Accessibilities acc
? acc
: Accessibilities.All;
var accessibilities = (Accessibilities)(assemblySymbol.GetPlantUmlDiagramAttributeArg("IncludeMemberAccessibilities")
?? Accessibilities.NotSet);
if (accessibilities.HasFlag(Accessibilities.NotSet))
{
accessibilities = Accessibilities.All;
}
includeMemberAccessibilities.Add(
symbol.ContainingAssembly,
assemblySymbol,
accessibilities);
return accessibilities;
}
}

public static Accessibilities GetExcludeMemberAttributes(INamedTypeSymbol symbol)
public static Accessibilities GetExcludeMemberAttributes(IAssemblySymbol assemblySymbol)
{
if (excludeMemberAccessibilities.TryGetValue(symbol.ContainingAssembly, out var value))
if (excludeMemberAccessibilities.TryGetValue(assemblySymbol, out var value))
{
return value;
}
else
{
var accessibilities = symbol.GetPlantUmlDiagramAttributeArg("ExcludeMemberAccessibilities") is Accessibilities acc
? acc
: Accessibilities.None;
var accessibilities = (Accessibilities)(assemblySymbol.GetPlantUmlDiagramAttributeArg("ExcludeMemberAccessibilities")
?? Accessibilities.NotSet);
if (accessibilities.HasFlag(Accessibilities.NotSet))
{
accessibilities = Accessibilities.None;
}
excludeMemberAccessibilities.Add(
symbol.ContainingAssembly,
assemblySymbol,
accessibilities);
return accessibilities;
}
}
public static AssociationTypes GetDisableAssociationTypesAttributes(IAssemblySymbol assemblySymbol)
{
if (disableAssociationTypes.TryGetValue(assemblySymbol, out var value))
{
return value;
}
else
{
var associationTypes = (AssociationTypes)(assemblySymbol.GetPlantUmlDiagramAttributeArg("DisableAssociationTypes")
?? AssociationTypes.NotSet);
if (associationTypes.HasFlag(AssociationTypes.NotSet))
{
associationTypes = AssociationTypes.None;
}
disableAssociationTypes.Add(
assemblySymbol,
associationTypes);
return associationTypes;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,6 @@ internal class GeneratorOptions(AnalyzerConfigOptionsProvider config, string ass
public string AssemblyName { get; set; } = assemblyName;
public string OutputDir { get; set; } = GetOutputDir(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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,14 @@
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryType>git</RepositoryType>
<PackageTags>plantuml;SourceGenerator</PackageTags>
<PackageReleaseNotes>[0.6.0-beta]
- Partially deprecated properties that can be configured in project files (.csproj).
From this version onwards, only `PlantUmlGenerator_OutputDir` is configurable.
- Modified the `PlantUmlDiagramAttribute` to be applicable at the assembly level.
When applied at the assembly level, it targets all types defined within it for output.
- Added the `PlantUmlAssociationAttribute`.
This allows for the definition of custom associations.
- Added the `PlantUmlIgnoreAssociationAttribute`.
Attach this attribute to members or method parameters where associations are not desired, thereby excluding them from association creation.
- Introduced the `PlantUmlExtraAssociationTargetsAttribute`.
This allows for additional specification of types targeted for association creation.
<PackageReleaseNotes>[1.0.0]
- Added `DisableAssociationTypes` property to `PlantUmlDiagramAttribute`.
- Fixed behavior when setting `IncludeMemberAccessibilities` and `ExcludeMemberAccessibilities` properties of `PlantUmlDiagramAttribute`.
</PackageReleaseNotes>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<AssemblyVersion>0.6.0.0</AssemblyVersion>
<FileVersion>0.6.0.0</FileVersion>
<Version>0.6.0-beta</Version>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" PrivateAssets="all" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ private void SetMethodDeclaration(IMethodSymbol methodSymbol)

private void SetPropertyAssociation(IPropertySymbol propertySymbol, IImmutableSet<INamedTypeSymbol> symbols)
{
if (Symbol.DisableAssociationTypes().HasFlag(AssociationTypes.Property))
{
return;
}
if (propertySymbol.HasPlantUmlIgnoreAssociationAttribute())
{
return;
Expand Down Expand Up @@ -241,6 +245,10 @@ private void SetCustomAssociation(ISymbol targetSymbol, ITypeSymbol targetTypeSy

private void SetFieldAssociation(IFieldSymbol fieldSymbol, IImmutableSet<INamedTypeSymbol> symbols)
{
if (Symbol.DisableAssociationTypes().HasFlag(AssociationTypes.Field))
{
return;
}
if (fieldSymbol.HasPlantUmlIgnoreAssociationAttribute())
{
return;
Expand Down Expand Up @@ -299,6 +307,10 @@ private void SetFieldAssociation(IFieldSymbol fieldSymbol, IImmutableSet<INamedT

private void SetMethodAssociation(IMethodSymbol methodSymbol, IImmutableSet<INamedTypeSymbol> symbols)
{
if (Symbol.DisableAssociationTypes().HasFlag(AssociationTypes.MethodParameter))
{
return;
}
foreach (var parameter in methodSymbol.Parameters)
{
if (parameter.HasPlantUmlIgnoreAssociationAttribute())
Expand All @@ -324,10 +336,13 @@ private void SetMethodAssociation(IMethodSymbol methodSymbol, IImmutableSet<INam

private void SetInheritance(IImmutableSet<INamedTypeSymbol> symbols)
{
if (Symbol.DisableAssociationTypes().HasFlag(AssociationTypes.Inheritance))
{
return;
}
if (Symbol.BaseType is not null
&& Symbol.BaseType.SpecialType != SpecialType.System_Object
&& Symbol.BaseType.SpecialType != SpecialType.System_Enum
&& Symbol.BaseType.SpecialType != SpecialType.System_ValueType)
&& (HasReference(Symbol.BaseType, symbols)
|| IsExtraAssociationTarget(Symbol.BaseType, ExtraAssociationTargets)))
{
var rootLabel = Symbol.BaseType.IsGenericType ? Symbol.BaseType.GetTypeArgumentsString() : "";
Associations.Add(AssociationNode.Inheritance.Create(Symbol.BaseType, Symbol, rootLabel: rootLabel));
Expand All @@ -337,15 +352,27 @@ private void SetInheritance(IImmutableSet<INamedTypeSymbol> symbols)

private void SetRealization(IImmutableSet<INamedTypeSymbol> symbols)
{
if (Symbol.DisableAssociationTypes().HasFlag(AssociationTypes.Realization))
{
return;
}
foreach (var type in Symbol.Interfaces)
{
var rootLabel = type.IsGenericType ? type.GetTypeArgumentsString() : "";
Associations.Add(AssociationNode.Realization.Create(type, Symbol, rootLabel: rootLabel));
AddToIncludeItems(type, symbols);
if (HasReference(type, symbols)
|| IsExtraAssociationTarget(type, ExtraAssociationTargets))
{
var rootLabel = type.IsGenericType ? type.GetTypeArgumentsString() : "";
Associations.Add(AssociationNode.Realization.Create(type, Symbol, rootLabel: rootLabel));
AddToIncludeItems(type, symbols);
}
}
}
private void SetNest(INamedTypeSymbol nestedTypeSymbol, IImmutableSet<INamedTypeSymbol> symbols)
{
if (Symbol.DisableAssociationTypes().HasFlag(AssociationTypes.Nest))
{
return;
}
if (nestedTypeSymbol.HasPlantUmlIgnoreAssociationAttribute())
{
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace PlantUmlClassDiagramGenerator.SourceGenerator.Attributes;
[global::System.Flags]
internal enum Accessibilities
{
NotSet = 0x8000,
None = 0,
Public = 0x01,
Protected = 0x02,
Expand All @@ -25,7 +26,21 @@ internal enum Accessibilities
Private = 0x20,
All = Public | Protected | Internal | ProtectedInternal | PrivateProtected | Private
}
[global::System.Flags]
internal enum AssociationTypes
{
NotSet = 0x8000,
None = 0,
Inheritance = 0x01,
Realization = 0x02,
Property = 0x04,
Field = 0x08,
MethodParameter = 0x10,
Nest = 0x20,
All = Inheritance | Realization | Property | Field | MethodParameter | Nest
}
[global::System.AttributeUsage(
global::System.AttributeTargets.Assembly
| global::System.AttributeTargets.Class
Expand All @@ -34,8 +49,9 @@ internal enum Accessibilities
| global::System.AttributeTargets.Struct)]
internal class PlantUmlDiagramAttribute : global::System.Attribute
{
public Accessibilities IncludeMemberAccessibilities { get; set; } = Accessibilities.All;
public Accessibilities ExcludeMemberAccessibilities { get; set; } = Accessibilities.None;
public Accessibilities IncludeMemberAccessibilities { get; set; } = Accessibilities.NotSet;
public Accessibilities ExcludeMemberAccessibilities { get; set; } = Accessibilities.NotSet;
public AssociationTypes DisableAssociationTypes { get; set; } = AssociationTypes.NotSet;
}
[global::System.AttributeUsage(
Expand Down
Loading

0 comments on commit 15cb93b

Please sign in to comment.