Skip to content

Commit

Permalink
Improved comments
Browse files Browse the repository at this point in the history
  • Loading branch information
NikolayPianikov committed Mar 13, 2024
1 parent 9b78dc1 commit d51baae
Show file tree
Hide file tree
Showing 12 changed files with 148 additions and 54 deletions.
73 changes: 38 additions & 35 deletions src/Pure.DI.Core/Core/Code/ClassCommenter.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
namespace Pure.DI.Core.Code;

internal class ClassCommenter(
ITypeResolver typeResolver,
IFormatter formatter,
IComments comments,
IBuilder<IEnumerable<string>, Uri> mermaidUrlBuilder)
IBuilder<IEnumerable<string>, Uri> mermaidUrlBuilder,
IBuilder<ImmutableArray<Root>, IEnumerable<ResolverInfo>> resolversBuilder)
: ICommenter<Unit>
{
public void AddComments(CompositionCode composition, Unit unit)
Expand Down Expand Up @@ -36,54 +37,61 @@ public void AddComments(CompositionCode composition, Unit unit)

var orderedRoots = composition.Roots
.OrderByDescending(root => root.IsPublic)
.ThenBy(root => root.PropertyName)
.ThenBy(root => root.DisplayName)
.ThenBy(root => root.Node.Binding)
.ToArray();

if (composition.Roots.Length > 0)
if (orderedRoots.Length > 0)
{
var rootComments = comments.FormatList(
"Composition roots:",
orderedRoots.Select(root => (CreateTerms(root), CreateDescriptions(root))),
"<b>Composition roots</b>",
orderedRoots.Select(root => (CreateRootTerms(root), CreateRootDescriptions(root))),
false);

foreach (var rootComment in rootComments)
{
code.AppendLine(rootComment);
}

IReadOnlyCollection<string> CreateTerms(Root root) =>
root.IsPublic
? [$"<see cref=\"{ResolveType(root.Injection.Type)}\"/> {root.PropertyName}"]
: [$"<see cref=\"{ResolveType(root.Injection.Type)}\"/> {privateRootAdditionalComment}"];
IReadOnlyCollection<string> CreateRootTerms(Root root)
{
var term = new StringBuilder();
term.Append(formatter.FormatRef(root.Injection.Type));
term.Append(' ');
term.Append(root.IsPublic ? formatter.FormatRef(root) : privateRootAdditionalComment);

var resolvers = resolversBuilder.Build(ImmutableArray.Create(root));
if (!resolvers.Any())
{
return [term.ToString()];
}

term.Append("<br/>or using ");
term.Append(formatter.FormatRef($"Resolve{{T}}({(root.Injection.Tag != null ? "object" : "")})"));
term.Append(" method: <c>Resolve&lt;");
term.Append(comments.Escape(root.TypeDescription.Name));
term.Append("&gt;(");
term.Append(root.Injection.Tag != null ? root.Injection.Tag.ValueToString() : "");
term.Append(")</c>");
return [term.ToString()];
}

IReadOnlyCollection<string> CreateDescriptions(Root root) =>
IReadOnlyCollection<string> CreateRootDescriptions(Root root) =>
root.Source.Comments.Count > 0
? root.Source.Comments.Select(comments.Escape).ToList()
: [ $"Provides a composition root of type <see cref=\"{ResolveType(root.Node.Type)}\"/>." ];
: [ $"Provides a composition root of type {formatter.FormatRef(root.Node.Type)}." ];
}

code.AppendLine("/// </summary>");

var root = orderedRoots.FirstOrDefault(i => i.IsPublic);
if (root is not null)
{
var classArgsStr = "()";
if (!composition.Args.IsEmpty)
{
classArgsStr = $"({string.Join(", ", composition.Args.Select(arg => $"{arg.Node.Arg?.Source.ArgName ?? "..."}"))})";
}

var rootArgsStr = "";
if (!root.Args.IsEmpty || (root.Kind & RootKinds.Method) == RootKinds.Method)
{
rootArgsStr = $"({string.Join(", ", root.Args.Select(arg => $"{arg.Node.Arg?.Source.ArgName ?? "..."}"))})";
}

var name = composition.Source.Source.Name;
code.AppendLine("/// <example>");
code.AppendLine($"/// This shows how to get an instance of type <see cref=\"{ResolveType(root.Node.Type)}\"/> using the composition root <see cref=\"{root.PropertyName}\"/>:");
code.AppendLine($"/// This shows how to get an instance of type {formatter.FormatRef(root.Node.Type)} using the composition root {formatter.FormatRef(root)}:");
code.AppendLine("/// <code>");
code.AppendLine($"/// {(composition.DisposablesCount == 0 ? "" : "using ")}var composition = new {name.ClassName}{classArgsStr};");
code.AppendLine($"/// var instance = composition.{root.PropertyName}{rootArgsStr};");
code.AppendLine($"/// {(composition.DisposablesCount == 0 ? "" : "using ")}var composition = new {composition.Source.Source.Name.ClassName}({string.Join(", ", composition.Args.Where(i => i.Node.Arg?.Source.Kind == ArgKind.Class).Select(arg => arg.VariableName))});");
code.AppendLine($"/// var instance = composition.{formatter.Format(root)};");
code.AppendLine("/// </code>");
code.AppendLine("/// </example>");
}
Expand All @@ -95,13 +103,8 @@ IReadOnlyCollection<string> CreateDescriptions(Root root) =>
}

code.AppendLine("/// This class was created by <a href=\"https://github.com/DevTeam/Pure.DI\">Pure.DI</a> source code generator.");
code.AppendLine("/// </summary>");
code.AppendLine("/// <seealso cref=\"Pure.DI.DI.Setup\"/>");
code.AppendLine("/// <seealso cref=\"Pure.DI.IConfiguration.Bind(object[])\"/>");
code.AppendLine("/// <seealso cref=\"Pure.DI.IConfiguration.Bind{T}(object[])\"/>");
}

private string ResolveType(ITypeSymbol type) =>
comments.Escape(
typeResolver.Resolve(type).Name
.Replace('<', '{')
.Replace('>', '}'));
}
4 changes: 2 additions & 2 deletions src/Pure.DI.Core/Core/Code/ClassDiagramBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public LinesBuilder Build(CompositionCode composition)
rootArgsStr = $"({string.Join(", ", root.Args.Select(arg => $"{arg.InstanceType} {arg.VariableName}"))})";
}

lines.AppendLine($"{(root.IsPublic ? "+" : "-")}{FormatType(root.Injection.Type, DefaultFormatOptions)} {root.PropertyName}{rootArgsStr}");
lines.AppendLine($"{(root.IsPublic ? "+" : "-")}{FormatType(root.Injection.Type, DefaultFormatOptions)} {root.DisplayName}{rootArgsStr}");
}

if (hasResolveMethods)
Expand Down Expand Up @@ -127,7 +127,7 @@ public LinesBuilder Build(CompositionCode composition)
cancellationToken.ThrowIfCancellationRequested();
if (dependency.Target.Root is not null && rootProperties.TryGetValue(dependency.Injection, out var root))
{
lines.AppendLine($"{composition.Source.Source.Name.ClassName} ..> {FormatType(dependency.Source.Type, DefaultFormatOptions)} : {FormatInjection(root.Injection, DefaultFormatOptions)} {root.PropertyName}");
lines.AppendLine($"{composition.Source.Source.Name.ClassName} ..> {FormatType(dependency.Source.Type, DefaultFormatOptions)} : {FormatInjection(root.Injection, DefaultFormatOptions)} {root.DisplayName}");
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion src/Pure.DI.Core/Core/Code/CompositionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public CompositionCode Build(DependencyGraph graph)
var publicRoots = roots
.OrderByDescending(i => i.IsPublic)
.ThenBy(i => i.Node.Binding.Id)
.ThenBy(i => i.PropertyName)
.ThenBy(i => i.DisplayName)
.ToImmutableArray();

var composition = new CompositionCode(
Expand Down
63 changes: 63 additions & 0 deletions src/Pure.DI.Core/Core/Code/Formatter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace Pure.DI.Core.Code;

internal class Formatter(
ITypeResolver typeResolver,
IComments comments)
: IFormatter
{
public string Format(Root root)
{
var sb = new StringBuilder();
sb.Append(root.DisplayName);
if (!root.IsMethod)
{
return sb.ToString();
}

var typeArgs= root.TypeDescription.TypeArgs;
if (typeArgs.Count > 0)
{
sb.Append("&lt;");
sb.Append(string.Join(", ", typeArgs.Select(i => i.Name)));
sb.Append("&gt;");
}

sb.Append('(');
sb.Append(string.Join(", ", root.Args.Select(i => i.VariableName)));
sb.Append(')');
return sb.ToString();
}

public string FormatRef(Root root)
{
var sb = new StringBuilder();
sb.Append(root.DisplayName);
if (!root.IsMethod)
{
return FormatRef(sb.ToString());
}

var typeArgs= root.TypeDescription.TypeArgs;
if (typeArgs.Count > 0)
{
sb.Append('{');
sb.Append(string.Join(", ", typeArgs.Select(i => i.Name)));
sb.Append('}');
}

sb.Append('(');
sb.Append(string.Join(", ", root.Args.Select(i => i.ContractType)));
sb.Append(')');
return FormatRef(sb.ToString());
}

public string FormatRef(string text) =>
$"<see cref=\"{text}\"/>";

public string FormatRef(ITypeSymbol type) =>
FormatRef(
comments.Escape(
typeResolver.Resolve(type).Name
.Replace('<', '{')
.Replace('>', '}')));
}
12 changes: 12 additions & 0 deletions src/Pure.DI.Core/Core/Code/IFormatter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Pure.DI.Core.Code;

internal interface IFormatter
{
string Format(Root root);

string FormatRef(Root root);

string FormatRef(string text);

string FormatRef(ITypeSymbol type);
}
4 changes: 2 additions & 2 deletions src/Pure.DI.Core/Core/Code/ResolverClassesBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ private static void ImplementInterface(CompositionCode composition, ResolverInfo
{
var isStatic = (defaultRoot.Kind & RootKinds.Static) == RootKinds.Static;
var isMethod = !defaultRoot.Args.IsEmpty || (defaultRoot.Kind & RootKinds.Method) == RootKinds.Method;
code.AppendLine($"return {(isStatic ? composition.Source.Source.Name.ClassName : "composition")}.{defaultRoot.PropertyName}{(isMethod ? "()": "")};");
code.AppendLine($"return {(isStatic ? composition.Source.Source.Name.ClassName : "composition")}.{defaultRoot.DisplayName}{(isMethod ? "()": "")};");
}
else
{
Expand Down Expand Up @@ -182,6 +182,6 @@ private static string GetRoot(CompositionCode composition, Root root)
{
var target = (root.Kind & RootKinds.Static) == RootKinds.Static ? composition.Source.Source.Name.ClassName : "composition";
var isMethod = !root.Args.IsEmpty || (root.Kind & RootKinds.Method) == RootKinds.Method;
return $"{target}.{root.PropertyName}{(isMethod ? "()": "")}";
return $"{target}.{root.DisplayName}{(isMethod ? "()": "")}";
}
}
5 changes: 2 additions & 3 deletions src/Pure.DI.Core/Core/Code/RootMethodsBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public CompositionCode Build(CompositionCode composition)

private void BuildRoot(CompositionCode composition, Root root)
{
rootCommenter.AddComments(composition, root);
var code = composition.Code;
var rootArgsStr = "";
if (root.IsMethod)
Expand Down Expand Up @@ -76,7 +77,7 @@ private void BuildRoot(CompositionCode composition, Root root)
name.Append(root.TypeDescription.Name);

name.Append(' ');
name.Append(root.PropertyName);
name.Append(root.DisplayName);

var typeArgs = root.TypeDescription.TypeArgs;
if (typeArgs.Count > 0)
Expand All @@ -87,8 +88,6 @@ private void BuildRoot(CompositionCode composition, Root root)
}

name.Append(rootArgsStr);

rootCommenter.AddComments(composition, root);

code.AppendLine(name.ToString());
code.AppendLine("{");
Expand Down
33 changes: 25 additions & 8 deletions src/Pure.DI.Core/Core/Code/RootMethodsCommenter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
namespace Pure.DI.Core.Code;

internal class RootMethodsCommenter(IComments comments): ICommenter<Root>
internal class RootMethodsCommenter(
IFormatter formatter,
IComments comments)
: ICommenter<Root>
{
public void AddComments(CompositionCode composition, Root root)
{
Expand All @@ -10,18 +13,32 @@ public void AddComments(CompositionCode composition, Root root)
}

var rootComments = root.Source.Comments;
if (rootComments.Count <= 0)
{
return;
}

var code = composition.Code;
code.AppendLine("/// <summary>");
foreach (var comment in comments.Format(rootComments, true))
if (rootComments.Count > 0)
{
foreach (var comment in comments.Format(rootComments, true))
{
code.AppendLine(comment);
}
}
else
{
code.AppendLine(comment);
code.AppendLine($"/// Provides a composition root of type {formatter.FormatRef(root.Node.Type)}.");
}

code.AppendLine("/// </summary>");
if (!root.IsPublic)
{
return;
}

code.AppendLine("/// <example>");
code.AppendLine($"/// This shows how to get an instance of type {formatter.FormatRef(root.Node.Type)}:");
code.AppendLine("/// <code>");
code.AppendLine($"/// {(composition.DisposablesCount == 0 ? "" : "using ")}var composition = new {composition.Source.Source.Name.ClassName}({string.Join(", ", composition.Args.Where(i => i.Node.Arg?.Source.Kind == ArgKind.Class).Select(arg => arg.VariableName))});");
code.AppendLine($"/// var instance = composition.{formatter.Format(root)};");
code.AppendLine("/// </code>");
code.AppendLine("/// </example>");
}
}
2 changes: 1 addition & 1 deletion src/Pure.DI.Core/Core/Code/StaticConstructorBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public CompositionCode Build(CompositionCode composition)
{
foreach (var root in resolver.Roots)
{
code.AppendLine($"{Names.OnNewRootMethodName}<{typeResolver.Resolve(root.Injection.Type)}, {typeResolver.Resolve(root.Node.Type)}>(val{className}, \"{root.PropertyName}\", {root.Injection.Tag.ValueToString()}, {root.Node.Lifetime.ValueToString()});");
code.AppendLine($"{Names.OnNewRootMethodName}<{typeResolver.Resolve(root.Injection.Type)}, {typeResolver.Resolve(root.Node.Type)}>(val{className}, \"{root.DisplayName}\", {root.Injection.Tag.ValueToString()}, {root.Node.Lifetime.ValueToString()});");
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Pure.DI.Core/Core/Models/Root.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ internal record Root(
{
public bool IsPublic => !string.IsNullOrWhiteSpace(Name);

public string PropertyName => this.GetPropertyName();
public string DisplayName => this.GetPropertyName();
}
1 change: 1 addition & 0 deletions src/Pure.DI.Core/Generator.Composition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ private static void Setup() => DI.Setup(nameof(Generator))
.Bind().To<Variator<TT>>()
.Bind().To<Profiler>()
.Bind().To<BaseSymbolsProvider>()
.Bind().To<Formatter>()

// Comments
.Bind(Tag.Type).To<ClassCommenter>()
Expand Down
1 change: 0 additions & 1 deletion src/Pure.DI.Core/Pure.DI.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
<DesignTime>True</DesignTime>
<DependentUpon>GenericTypeArguments.g.tt</DependentUpon>
</Compile>
<Compile Remove="Core\ProcessExtensions.cs" />
</ItemGroup>

</Project>

0 comments on commit d51baae

Please sign in to comment.