Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Tomlet.Tests/CommentProvider/TestInlineCommentProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Collections.Generic;

namespace Tomlet.Tests.CommentProvider;

public class TestInlineCommentProvider : ICommentProvider
{
public static Dictionary<string, string> Comments = new Dictionary<string, string>();

private readonly string _name;

public TestInlineCommentProvider(string name)
{
_name = name;
}

public string GetComment()
{
return Comments[_name];
}
}
20 changes: 20 additions & 0 deletions Tomlet.Tests/CommentProvider/TestPrecedingCommentProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Collections.Generic;

namespace Tomlet.Tests.CommentProvider;

public class TestPrecedingCommentProvider : ICommentProvider
{
public static Dictionary<string, string> Comments = new Dictionary<string, string>();

private readonly string _name;

public TestPrecedingCommentProvider(string name)
{
_name = name;
}

public string GetComment()
{
return Comments[_name];
}
}
94 changes: 90 additions & 4 deletions Tomlet.Tests/CommentSerializationTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
using System;
using System.Collections.Generic;
using Tomlet.Models;
using Tomlet.Tests.CommentProvider;
using Tomlet.Tests.TestModelClasses;
using Xunit;
using Xunit.Abstractions;

namespace Tomlet.Tests;

public class CommentSerializationTests
{
public CommentSerializationTests(ITestOutputHelper testOutputHelper)
{
}

[Fact]
public void CommentsOnSimpleKeyValuePairsWork()
{
Expand Down Expand Up @@ -72,7 +80,7 @@ public void CommentsOnTableArraysWork()
tomlString.Comments.InlineComment = "Inline comment on value";
table.PutValue("key", tomlString);

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

doc.PutValue("table-array", tableArray);
Expand All @@ -91,7 +99,7 @@ public void CommentsOnTableArraysWork()
public void CommentsOnPrimitiveArraysWork()
{
var doc = TomlDocument.CreateEmpty();
var tomlNumbers = new TomlArray {1, 2, 3};
var tomlNumbers = new TomlArray { 1, 2, 3 };
doc.PutValue("numbers", tomlNumbers);

tomlNumbers[0].Comments.PrecedingComment = "This is a preceding comment on the first value of the array";
Expand All @@ -103,7 +111,7 @@ public void CommentsOnPrimitiveArraysWork()
2, # This is an inline comment on the second value of the array
3,
]".ReplaceLineEndings();

//Replace tabs with spaces because this source file uses spaces
var actual = doc.SerializedValue.Trim().Replace("\t", " ").ReplaceLineEndings();
Assert.Equal(expected, actual);
Expand All @@ -115,10 +123,88 @@ public void CommentAttributesWork()
var config = TomletMain.To<ExampleMailboxConfigClass>(TestResources.ExampleMailboxConfigurationTestInput);

var doc = TomletMain.DocumentFrom(config);

Assert.Equal("The name of the mailbox", doc.GetValue("mailbox").Comments.InlineComment);
Assert.Equal("Your username for the mailbox", doc.GetValue("username").Comments.InlineComment);
Assert.Equal("The password you use to access the mailbox", doc.GetValue("password").Comments.InlineComment);
Assert.Equal("The rules for the mailbox follow", doc.GetArray("rules").Comments.PrecedingComment);
}

[Fact]
public void CommentProviderTest()
{
TestPrecedingCommentProvider.Comments["PrecedingComment"] = Guid.NewGuid().ToString();
TestInlineCommentProvider.Comments["InlineComment"] = Guid.NewGuid().ToString();

var data = new CommentProviderTestModel()
{
PrecedingComment = "Dynamic Preceding Comment",
InlineComment = "Inline Comment",
};

var doc = TomletMain.DocumentFrom(data);

Assert.Equal(TestPrecedingCommentProvider.Comments["PrecedingComment"],
doc.GetValue("PrecedingComment").Comments.PrecedingComment);
Assert.Equal("PlainInlineComment", doc.GetValue("PrecedingComment").Comments.InlineComment);

Assert.Equal(TestInlineCommentProvider.Comments["InlineComment"],
doc.GetValue("InlineComment").Comments.InlineComment);
Assert.Equal("PlainPrecedingComment", doc.GetValue("InlineComment").Comments.PrecedingComment);
}

[Fact]
public void PaddingLinesTest()
{
var data = new PaddingTestModel()
{
A = "str a",
B = 1,
C = new PaddingTestModel.NestedModel()
{
E = "str",
F = 2,
},
D = new List<PaddingTestModel.NestedModel>()
{
new()
{
E = "str0",
F = 0,
},
new()
{
E = "str1",
F = 1,
},
}
};

var expected = @"
A = ""str a""
B = 1

# Nested Object
[C]
# Preceding Comment
E = ""str"" # Preceding Comment
# Preceding Comment
F = 2 # Preceding Comment


# Nested Array
[[D]]
# Preceding Comment
E = ""str0"" # Preceding Comment
# Preceding Comment
F = 0 # Preceding Comment

[[D]]
# Preceding Comment
E = ""str1"" # Preceding Comment
# Preceding Comment
F = 1 # Preceding Comment
".Trim();
Assert.Equal(expected.ReplaceLineEndings(), TomletMain.TomlStringFrom(data).ReplaceLineEndings().Trim());
}
}
15 changes: 15 additions & 0 deletions Tomlet.Tests/TestModelClasses/CommentProviderTestModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Tomlet.Attributes;
using Tomlet.Tests.CommentProvider;

namespace Tomlet.Tests.TestModelClasses;

public class CommentProviderTestModel
{
[TomlPrecedingCommentProvider(typeof(TestPrecedingCommentProvider), new object[] { "PrecedingComment" })]
[TomlInlineComment("PlainInlineComment")]
public string PrecedingComment { get; set; }

[TomlInlineCommentProvider(typeof(TestInlineCommentProvider), new object[] { "InlineComment" })]
[TomlPrecedingComment("PlainPrecedingComment")]
public string InlineComment { get; set; }
}
32 changes: 32 additions & 0 deletions Tomlet.Tests/TestModelClasses/PaddingTestModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Collections.Generic;
using Tomlet.Attributes;

namespace Tomlet.Tests.TestModelClasses;

public class PaddingTestModel
{
public string A { get; set; }

public int B { get; set; }

[TomlPaddingLines(1)]
[TomlDoNotInlineObject]
[TomlPrecedingComment("Nested Object")]
public NestedModel C { get; set; }

[TomlPaddingLines(1)]
[TomlDoNotInlineObject]
[TomlPrecedingComment("Nested Array")]
public List<NestedModel> D { get; set; }

public class NestedModel
{
[TomlPrecedingComment("Preceding Comment")]
[TomlInlineComment("Preceding Comment")]
public string E { get; set; }

[TomlPrecedingComment("Preceding Comment")]
[TomlInlineComment("Preceding Comment")]
public int F { get; set; }
}
}
33 changes: 33 additions & 0 deletions Tomlet/Attributes/TomlCommentProviderAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Linq;

namespace Tomlet.Attributes;

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class TomlCommentProviderAttribute : Attribute
{
private readonly Type _provider;
private readonly object[] _args;
private readonly Type[] _constructorParamsType;

public string GetComment()
{
var constructor = _provider.GetConstructor(_constructorParamsType) ??

Check warning on line 15 in Tomlet/Attributes/TomlCommentProviderAttribute.cs

View workflow job for this annotation

GitHub Actions / build

'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'System.Type.GetConstructor(Type[])'. The field 'Tomlet.Attributes.TomlCommentProviderAttribute._provider' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.

Check warning on line 15 in Tomlet/Attributes/TomlCommentProviderAttribute.cs

View workflow job for this annotation

GitHub Actions / build

'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'System.Type.GetConstructor(Type[])'. The field 'Tomlet.Attributes.TomlCommentProviderAttribute._provider' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.

Check warning on line 15 in Tomlet/Attributes/TomlCommentProviderAttribute.cs

View workflow job for this annotation

GitHub Actions / build

'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'System.Type.GetConstructor(Type[])'. The field 'Tomlet.Attributes.TomlCommentProviderAttribute._provider' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.

Check warning on line 15 in Tomlet/Attributes/TomlCommentProviderAttribute.cs

View workflow job for this annotation

GitHub Actions / build

'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors' in call to 'System.Type.GetConstructor(Type[])'. The field 'Tomlet.Attributes.TomlCommentProviderAttribute._provider' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
throw new ArgumentException("Fail to get a constructor matching the parameters");
var instance = constructor.Invoke(_args) as ICommentProvider ??
throw new Exception("Fail to create an instance of the provider");
return instance.GetComment();
}

public TomlCommentProviderAttribute(Type provider, object[] args)
{
if (!typeof(ICommentProvider).IsAssignableFrom(provider))
{
throw new ArgumentException("Provider must implement ICommentProvider");
}

_provider = provider;
_args = args ?? new object[] { };
_constructorParamsType = args?.Select(a => a.GetType()).ToArray() ?? new Type[] { };
}
}
8 changes: 3 additions & 5 deletions Tomlet/Attributes/TomlInlineCommentAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
namespace Tomlet.Attributes;

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class TomlInlineCommentAttribute : Attribute
public class TomlInlineCommentAttribute : TomlInlineCommentProviderAttribute
{
internal string Comment { get; }

public TomlInlineCommentAttribute(string comment)
public TomlInlineCommentAttribute(string comment) : base(typeof(TomlSimpleCommentProvider),
new object[] { comment })
{
Comment = comment;
}
}
15 changes: 15 additions & 0 deletions Tomlet/Attributes/TomlInlineCommentProviderAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;

namespace Tomlet.Attributes;

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class TomlInlineCommentProviderAttribute : TomlCommentProviderAttribute
{
public TomlInlineCommentProviderAttribute(Type provider) : base(provider, new object[] { })
{
}

public TomlInlineCommentProviderAttribute(Type provider, object[] args) : base(provider, args)
{
}
}
14 changes: 14 additions & 0 deletions Tomlet/Attributes/TomlPaddingLinesAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace Tomlet.Attributes;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Property)]
public class TomlPaddingLinesAttribute: Attribute
{
public int PaddingLines { get; }

public TomlPaddingLinesAttribute(int paddingLines)
{
PaddingLines = paddingLines;
}
}
8 changes: 3 additions & 5 deletions Tomlet/Attributes/TomlPrecedingCommentAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
namespace Tomlet.Attributes;

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class TomlPrecedingCommentAttribute : Attribute
public class TomlPrecedingCommentAttribute : TomlPrecedingCommentProviderAttribute
{
internal string Comment { get; }

public TomlPrecedingCommentAttribute(string comment)
public TomlPrecedingCommentAttribute(string comment) : base(typeof(TomlSimpleCommentProvider),
new object[] { comment })
{
Comment = comment;
}
}
15 changes: 15 additions & 0 deletions Tomlet/Attributes/TomlPrecedingCommentProviderAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;

namespace Tomlet.Attributes;

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class TomlPrecedingCommentProviderAttribute : TomlCommentProviderAttribute
{
public TomlPrecedingCommentProviderAttribute(Type provider) : base(provider, new object[] { })
{
}

public TomlPrecedingCommentProviderAttribute(Type provider, object[] args) : base(provider, args)
{
}
}
18 changes: 18 additions & 0 deletions Tomlet/CommentProviderUtil.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;

namespace Tomlet;

internal static class CommentProviderUtil
{
public static string GetComment(Type provider)
{
var constructor = provider.GetConstructor(Type.EmptyTypes);

Check warning on line 9 in Tomlet/CommentProviderUtil.cs

View workflow job for this annotation

GitHub Actions / build

'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Type.GetConstructor(Type[])'. The parameter 'provider' of method 'Tomlet.CommentProviderUtil.GetComment(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.

Check warning on line 9 in Tomlet/CommentProviderUtil.cs

View workflow job for this annotation

GitHub Actions / build

'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Type.GetConstructor(Type[])'. The parameter 'provider' of method 'Tomlet.CommentProviderUtil.GetComment(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.

Check warning on line 9 in Tomlet/CommentProviderUtil.cs

View workflow job for this annotation

GitHub Actions / build

'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Type.GetConstructor(Type[])'. The parameter 'provider' of method 'Tomlet.CommentProviderUtil.GetComment(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.

Check warning on line 9 in Tomlet/CommentProviderUtil.cs

View workflow job for this annotation

GitHub Actions / build

'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicParameterlessConstructor' in call to 'System.Type.GetConstructor(Type[])'. The parameter 'provider' of method 'Tomlet.CommentProviderUtil.GetComment(Type)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
if (constructor == null)
{
throw new ArgumentException("Provider must have a parameterless constructor");
}

var instance = (ICommentProvider)constructor.Invoke(null);
return instance.GetComment();
}
}
5 changes: 3 additions & 2 deletions Tomlet/Extensions/GenericExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
Expand Down Expand Up @@ -148,7 +148,8 @@ public static void Deconstruct<TKey, TValue>(this KeyValuePair<TKey, TValue> pai

public static bool IsNullOrWhiteSpace(this string s) => string.IsNullOrEmpty(s) || string.IsNullOrEmpty(s.Trim());

internal static T? GetCustomAttribute<T>(this MemberInfo info) where T : Attribute => info.GetCustomAttributes(false).Where(a => a is T).Cast<T>().FirstOrDefault();
internal static T? GetCustomAttribute<T>(this MemberInfo info) where T : Attribute
=> info.GetCustomAttributes(false).Where(a => typeof(T).IsAssignableFrom(a.GetType())).Cast<T>().FirstOrDefault();

internal static void EnsureLegalChar(this int c, int currentLineNum)
{
Expand Down
6 changes: 6 additions & 0 deletions Tomlet/ICommentProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Tomlet;

public interface ICommentProvider
{
public string GetComment();
}
Loading
Loading