Skip to content

Commit cc60916

Browse files
committed
feat: runtime comment provider
1 parent 4393f63 commit cc60916

14 files changed

+213
-21
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.Collections.Generic;
2+
3+
namespace Tomlet.Tests.CommentProvider;
4+
5+
public class TestInlineCommentProvider : ICommentProvider
6+
{
7+
public static Dictionary<string, string> Comments = new Dictionary<string, string>();
8+
9+
private readonly string _name;
10+
11+
public TestInlineCommentProvider(string name)
12+
{
13+
_name = name;
14+
}
15+
16+
public string GetComment()
17+
{
18+
return Comments[_name];
19+
}
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.Collections.Generic;
2+
3+
namespace Tomlet.Tests.CommentProvider;
4+
5+
public class TestPrecedingCommentProvider : ICommentProvider
6+
{
7+
public static Dictionary<string, string> Comments = new Dictionary<string, string>();
8+
9+
private readonly string _name;
10+
11+
public TestPrecedingCommentProvider(string name)
12+
{
13+
_name = name;
14+
}
15+
16+
public string GetComment()
17+
{
18+
return Comments[_name];
19+
}
20+
}

Tomlet.Tests/CommentSerializationTests.cs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
using System;
12
using Tomlet.Models;
3+
using Tomlet.Tests.CommentProvider;
24
using Tomlet.Tests.TestModelClasses;
35
using Xunit;
6+
using Xunit.Abstractions;
47

58
namespace Tomlet.Tests;
69

@@ -72,7 +75,7 @@ public void CommentsOnTableArraysWork()
7275
tomlString.Comments.InlineComment = "Inline comment on value";
7376
table.PutValue("key", tomlString);
7477

75-
var tableArray = new TomlArray {table};
78+
var tableArray = new TomlArray { table };
7679
tableArray.Comments.PrecedingComment = "This is a preceding comment on the table-array itself";
7780

7881
doc.PutValue("table-array", tableArray);
@@ -91,7 +94,7 @@ public void CommentsOnTableArraysWork()
9194
public void CommentsOnPrimitiveArraysWork()
9295
{
9396
var doc = TomlDocument.CreateEmpty();
94-
var tomlNumbers = new TomlArray {1, 2, 3};
97+
var tomlNumbers = new TomlArray { 1, 2, 3 };
9598
doc.PutValue("numbers", tomlNumbers);
9699

97100
tomlNumbers[0].Comments.PrecedingComment = "This is a preceding comment on the first value of the array";
@@ -103,7 +106,7 @@ public void CommentsOnPrimitiveArraysWork()
103106
2, # This is an inline comment on the second value of the array
104107
3,
105108
]".ReplaceLineEndings();
106-
109+
107110
//Replace tabs with spaces because this source file uses spaces
108111
var actual = doc.SerializedValue.Trim().Replace("\t", " ").ReplaceLineEndings();
109112
Assert.Equal(expected, actual);
@@ -115,10 +118,33 @@ public void CommentAttributesWork()
115118
var config = TomletMain.To<ExampleMailboxConfigClass>(TestResources.ExampleMailboxConfigurationTestInput);
116119

117120
var doc = TomletMain.DocumentFrom(config);
118-
121+
119122
Assert.Equal("The name of the mailbox", doc.GetValue("mailbox").Comments.InlineComment);
120123
Assert.Equal("Your username for the mailbox", doc.GetValue("username").Comments.InlineComment);
121124
Assert.Equal("The password you use to access the mailbox", doc.GetValue("password").Comments.InlineComment);
122125
Assert.Equal("The rules for the mailbox follow", doc.GetArray("rules").Comments.PrecedingComment);
123126
}
127+
128+
[Fact]
129+
public void CommentProviderTest()
130+
{
131+
TestPrecedingCommentProvider.Comments["PrecedingComment"] = Guid.NewGuid().ToString();
132+
TestInlineCommentProvider.Comments["InlineComment"] = Guid.NewGuid().ToString();
133+
134+
var data = new CommentProviderTestModel()
135+
{
136+
PrecedingComment = "Dynamic Preceding Comment",
137+
InlineComment = "Inline Comment",
138+
};
139+
140+
var doc = TomletMain.DocumentFrom(data);
141+
142+
Assert.Equal(TestPrecedingCommentProvider.Comments["PrecedingComment"],
143+
doc.GetValue("PrecedingComment").Comments.PrecedingComment);
144+
Assert.Equal("PlainInlineComment", doc.GetValue("PrecedingComment").Comments.InlineComment);
145+
146+
Assert.Equal(TestInlineCommentProvider.Comments["InlineComment"],
147+
doc.GetValue("InlineComment").Comments.InlineComment);
148+
Assert.Equal("PlainPrecedingComment", doc.GetValue("InlineComment").Comments.PrecedingComment);
149+
}
124150
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Tomlet.Attributes;
2+
using Tomlet.Tests.CommentProvider;
3+
4+
namespace Tomlet.Tests.TestModelClasses;
5+
6+
public class CommentProviderTestModel
7+
{
8+
[TomlPrecedingCommentProvider(typeof(TestPrecedingCommentProvider), new object[] { "PrecedingComment" })]
9+
[TomlInlineComment("PlainInlineComment")]
10+
public string PrecedingComment { get; set; }
11+
12+
[TomlInlineCommentProvider(typeof(TestInlineCommentProvider), new object[] { "InlineComment" })]
13+
[TomlPrecedingComment("PlainPrecedingComment")]
14+
public string InlineComment { get; set; }
15+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System;
2+
using System.Linq;
3+
4+
namespace Tomlet.Attributes;
5+
6+
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
7+
public class TomlCommentProviderAttribute : Attribute
8+
{
9+
private readonly Type _provider;
10+
private readonly object[] _args;
11+
private readonly Type[] _constructorParamsType;
12+
13+
public string GetComment()
14+
{
15+
var constructor = _provider.GetConstructor(_constructorParamsType) ??
16+
throw new ArgumentException("Fail to get a constructor matching the parameters");
17+
var instance = constructor.Invoke(_args) as ICommentProvider ??
18+
throw new Exception("Fail to create an instance of the provider");
19+
return instance.GetComment();
20+
}
21+
22+
public TomlCommentProviderAttribute(Type provider, object[] args)
23+
{
24+
if (!typeof(ICommentProvider).IsAssignableFrom(provider))
25+
{
26+
throw new ArgumentException("Provider must implement ICommentProvider");
27+
}
28+
29+
_provider = provider;
30+
_args = args ?? new object[] { };
31+
_constructorParamsType = args?.Select(a => a.GetType()).ToArray() ?? new Type[] { };
32+
}
33+
}

Tomlet/Attributes/TomlInlineCommentAttribute.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33
namespace Tomlet.Attributes;
44

55
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
6-
public class TomlInlineCommentAttribute : Attribute
6+
public class TomlInlineCommentAttribute : TomlInlineCommentProviderAttribute
77
{
8-
internal string Comment { get; }
9-
10-
public TomlInlineCommentAttribute(string comment)
8+
public TomlInlineCommentAttribute(string comment) : base(typeof(TomlSimpleCommentProvider),
9+
new object[] { comment })
1110
{
12-
Comment = comment;
1311
}
1412
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
3+
namespace Tomlet.Attributes;
4+
5+
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
6+
public class TomlInlineCommentProviderAttribute : TomlCommentProviderAttribute
7+
{
8+
public TomlInlineCommentProviderAttribute(Type provider) : base(provider, new object[] { })
9+
{
10+
}
11+
12+
public TomlInlineCommentProviderAttribute(Type provider, object[] args) : base(provider, args)
13+
{
14+
}
15+
}

Tomlet/Attributes/TomlPrecedingCommentAttribute.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33
namespace Tomlet.Attributes;
44

55
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
6-
public class TomlPrecedingCommentAttribute : Attribute
6+
public class TomlPrecedingCommentAttribute : TomlPrecedingCommentProviderAttribute
77
{
8-
internal string Comment { get; }
9-
10-
public TomlPrecedingCommentAttribute(string comment)
8+
public TomlPrecedingCommentAttribute(string comment) : base(typeof(TomlSimpleCommentProvider),
9+
new object[] { comment })
1110
{
12-
Comment = comment;
1311
}
1412
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
3+
namespace Tomlet.Attributes;
4+
5+
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
6+
public class TomlPrecedingCommentProviderAttribute : TomlCommentProviderAttribute
7+
{
8+
public TomlPrecedingCommentProviderAttribute(Type provider) : base(provider, new object[] { })
9+
{
10+
}
11+
12+
public TomlPrecedingCommentProviderAttribute(Type provider, object[] args) : base(provider, args)
13+
{
14+
}
15+
}

Tomlet/CommentProviderUtil.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
3+
namespace Tomlet;
4+
5+
internal static class CommentProviderUtil
6+
{
7+
public static string GetComment(Type provider)
8+
{
9+
var constructor = provider.GetConstructor(Type.EmptyTypes);
10+
if (constructor == null)
11+
{
12+
throw new ArgumentException("Provider must have a parameterless constructor");
13+
}
14+
15+
var instance = (ICommentProvider)constructor.Invoke(null);
16+
return instance.GetComment();
17+
}
18+
}

0 commit comments

Comments
 (0)