Skip to content

Commit 6289040

Browse files
committed
Atualiza suporte a múltiplas versões e refatora código
Mudanças no suporte a versões e estrutura de projeto: * Atualização do `Directory.Build.props` para múltiplas versões. - Suporte a `net8.0` e `net9.0` adicionado. - Versão de teste alterada para `net9.0`. - Atualização do `SPPreview` para `-preview-4.0`. Refatoração e adição de novas funcionalidades: * Implementação de novos métodos e classes. - Adição da propriedade estática `Parser` em `PointerParser`. - Refatoração dos métodos `PointerToProperty` e `PropertyToPointer`. - Criação da classe `DefaultPointerParser` para lógica de conversão. - Implementação da interface `IPointerParser`. Aprimoramento de testes e validações: * Melhoria na cobertura de testes e validações. - Novo teste `FindResult_HasInvalidParameter` adicionado. - Atualização de tipos de parâmetros para nullable em `PointerParserTests`. - Modificação da classe `TestEntity` para usar string nullable. - Adição da classe `FooBarContainer` e `FooValidator` em `Models.cs`. Atualizações em arquivos de configuração: * Ajustes em arquivos de configuração e dependências. - Atualização do `RoyalCode.SmartProblems.Tests.csproj` para múltiplos frameworks. - Alteração do `PackageReference` para `Microsoft.EntityFrameworkCore.Sqlite`. - Modificações nos arquivos `libs.targets` e `tests.targets` para caminhos de documentação.
1 parent 8b2b442 commit 6289040

12 files changed

Lines changed: 524 additions & 187 deletions

File tree

src/Directory.Build.props

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project>
22
<PropertyGroup>
3-
<FrmsVer>net8.0</FrmsVer>
4-
<TestVer>net8.0</TestVer>
3+
<FrmsVer>net8.0;net9.0</FrmsVer>
4+
<TestVer>net9.0</TestVer>
55
</PropertyGroup>
66
<PropertyGroup>
77
<LangVersion>latest</LangVersion>
@@ -10,7 +10,7 @@
1010
</PropertyGroup>
1111
<PropertyGroup>
1212
<SPVer>1.0.0</SPVer>
13-
<SPPreview>-preview-3.5</SPPreview>
13+
<SPPreview>-preview-4.0</SPPreview>
1414
</PropertyGroup>
1515
<PropertyGroup>
1616
<FluentValidationVer>12.0.0</FluentValidationVer>
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
using System.Text;
2+
3+
namespace RoyalCode.SmartProblems.Conversions;
4+
5+
internal sealed class DefaultPointerParser : IPointerParser
6+
{
7+
/// <inheritdoc />
8+
public string? PointerToProperty(string? pointer)
9+
{
10+
if (pointer == null)
11+
return null;
12+
13+
int pointerLength = pointer.Length;
14+
if (pointerLength == 0)
15+
return pointer;
16+
17+
int startIndex = 0;
18+
if (pointer[startIndex] == '#')
19+
{
20+
if (pointerLength == 1)
21+
return string.Empty;
22+
23+
startIndex = 1;
24+
}
25+
if (pointer[startIndex] == '/')
26+
{
27+
startIndex++;
28+
}
29+
30+
if (startIndex == pointerLength)
31+
return string.Empty;
32+
33+
StringBuilder propertyBuffer = new(pointerLength);
34+
35+
int slash = 0;
36+
int chars = 0;
37+
bool isDigit = true;
38+
39+
for (int i = startIndex, j = 0; i < pointerLength; i++, j++)
40+
{
41+
char c = pointer[i];
42+
if (c == '/')
43+
{
44+
if (chars is not 0)
45+
{
46+
startIndex = slash is 0 ? startIndex : slash + 1;
47+
if (isDigit)
48+
{
49+
propertyBuffer.Append('[')
50+
.Append(pointer, startIndex, chars)
51+
.Append(']');
52+
}
53+
else
54+
{
55+
if (slash is not 0)
56+
propertyBuffer.Append('.');
57+
58+
propertyBuffer.Append(pointer, startIndex, chars);
59+
}
60+
}
61+
62+
slash = i;
63+
isDigit = true;
64+
chars = 0;
65+
}
66+
else
67+
{
68+
chars++;
69+
isDigit = isDigit && char.IsDigit(c);
70+
}
71+
}
72+
73+
if (chars is not 0)
74+
{
75+
startIndex = slash is 0 ? startIndex : slash + 1;
76+
if (isDigit)
77+
{
78+
propertyBuffer.Append('[')
79+
.Append(pointer, startIndex, chars)
80+
.Append(']');
81+
}
82+
else
83+
{
84+
if (slash is not 0)
85+
propertyBuffer.Append('.');
86+
87+
propertyBuffer.Append(pointer, startIndex, chars);
88+
}
89+
}
90+
91+
return propertyBuffer.ToString();
92+
}
93+
94+
/// <inheritdoc />
95+
public string? PropertyToPointer(string? property)
96+
{
97+
if (property == null)
98+
return null;
99+
100+
int pointerLength = property.Length;
101+
if (pointerLength == 0)
102+
return "#/";
103+
104+
StringBuilder pointerBuffer = new(pointerLength);
105+
pointerBuffer.Append("#/");
106+
107+
bool lastIsSlash = true;
108+
109+
for (int i = 0; i < pointerLength; i++)
110+
{
111+
char c = property[i];
112+
if (c == '.' || c == '[' || c == ']')
113+
{
114+
if (!lastIsSlash)
115+
pointerBuffer.Append('/');
116+
117+
lastIsSlash = true;
118+
}
119+
else
120+
{
121+
pointerBuffer.Append(c);
122+
lastIsSlash = false;
123+
}
124+
}
125+
126+
if (lastIsSlash)
127+
pointerBuffer.Length--;
128+
129+
return pointerBuffer.ToString();
130+
}
131+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+

2+
using System.Diagnostics.CodeAnalysis;
3+
4+
namespace RoyalCode.SmartProblems.Conversions;
5+
6+
/// <summary>
7+
/// Interface to parse JSON pointers to C# properties and vice versa.
8+
/// </summary>
9+
public interface IPointerParser
10+
{
11+
/// <summary>
12+
/// <para>
13+
/// Convert a JSON pointer to a C# property.
14+
/// </para>
15+
/// <para>
16+
/// Some examples:
17+
/// </para>
18+
/// <list type="table">
19+
/// <item>
20+
/// <c>#/foo/0/bar</c> = <c>foo[0].bar</c>
21+
/// </item>
22+
/// </list>
23+
/// </summary>
24+
/// <param name="pointer">The JSON pointer to convert.</param>
25+
/// <returns>The C# property converted.</returns>
26+
string? PointerToProperty([NotNullIfNotNull(nameof(pointer))] string? pointer);
27+
28+
/// <summary>
29+
/// <para>
30+
/// Convert a C# property to a JSON pointer.
31+
/// </para>
32+
/// <para>
33+
/// Some examples:
34+
/// </para>
35+
/// <list type="table">
36+
/// <item>
37+
/// <c>foo[0].bar</c> = <c>#/foo/0/bar</c>
38+
/// </item>
39+
/// </list>
40+
/// </summary>
41+
/// <param name="property">The C# property to convert.</param>
42+
/// <returns>The JSON pointer converted.</returns>
43+
string? PropertyToPointer(string? property);
44+
}
Lines changed: 7 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11

22
using System.Diagnostics.CodeAnalysis;
3-
using System.Text;
43

54
namespace RoyalCode.SmartProblems.Conversions;
65

@@ -9,6 +8,11 @@ namespace RoyalCode.SmartProblems.Conversions;
98
/// </summary>
109
public static class PointerParser
1110
{
11+
/// <summary>
12+
/// Gets or sets the parser used to convert JSON pointers to C# properties and vice versa.
13+
/// </summary>
14+
public static IPointerParser Parser { get; set; } = new DefaultPointerParser();
15+
1216
/// <summary>
1317
/// <para>
1418
/// Convert a JSON pointer to a C# property.
@@ -25,90 +29,7 @@ public static class PointerParser
2529
/// <param name="pointer">The JSON pointer to convert.</param>
2630
/// <returns>The C# property converted.</returns>
2731
public static string? PointerToProperty([NotNullIfNotNull(nameof(pointer))] this string? pointer)
28-
{
29-
if (pointer == null)
30-
return null;
31-
32-
int pointerLength = pointer.Length;
33-
if (pointerLength == 0)
34-
return pointer;
35-
36-
int startIndex = 0;
37-
if (pointer[startIndex] == '#')
38-
{
39-
if (pointerLength == 1)
40-
return string.Empty;
41-
42-
startIndex = 1;
43-
}
44-
if (pointer[startIndex] == '/')
45-
{
46-
startIndex++;
47-
}
48-
49-
if (startIndex == pointerLength)
50-
return string.Empty;
51-
52-
StringBuilder propertyBuffer = new(pointerLength);
53-
54-
int slash = 0;
55-
int chars = 0;
56-
bool isDigit = true;
57-
58-
for (int i = startIndex, j = 0; i < pointerLength; i++, j++)
59-
{
60-
char c = pointer[i];
61-
if (c == '/')
62-
{
63-
if (chars is not 0)
64-
{
65-
startIndex = slash is 0 ? startIndex : slash + 1;
66-
if (isDigit)
67-
{
68-
propertyBuffer.Append('[')
69-
.Append(pointer, startIndex, chars)
70-
.Append(']');
71-
}
72-
else
73-
{
74-
if (slash is not 0)
75-
propertyBuffer.Append('.');
76-
77-
propertyBuffer.Append(pointer, startIndex, chars);
78-
}
79-
}
80-
81-
slash = i;
82-
isDigit = true;
83-
chars = 0;
84-
}
85-
else
86-
{
87-
chars++;
88-
isDigit = isDigit && char.IsDigit(c);
89-
}
90-
}
91-
92-
if (chars is not 0)
93-
{
94-
startIndex = slash is 0 ? startIndex : slash + 1;
95-
if (isDigit)
96-
{
97-
propertyBuffer.Append('[')
98-
.Append(pointer, startIndex, chars)
99-
.Append(']');
100-
}
101-
else
102-
{
103-
if (slash is not 0)
104-
propertyBuffer.Append('.');
105-
106-
propertyBuffer.Append(pointer, startIndex, chars);
107-
}
108-
}
109-
110-
return propertyBuffer.ToString();
111-
}
32+
=> Parser.PointerToProperty(pointer);
11233

11334
/// <summary>
11435
/// <para>
@@ -126,39 +47,5 @@ public static class PointerParser
12647
/// <param name="property">The C# property to convert.</param>
12748
/// <returns>The JSON pointer converted.</returns>
12849
public static string? PropertyToPointer(this string? property)
129-
{
130-
if (property == null)
131-
return null;
132-
133-
int pointerLength = property.Length;
134-
if (pointerLength == 0)
135-
return "#/";
136-
137-
StringBuilder pointerBuffer = new(pointerLength);
138-
pointerBuffer.Append("#/");
139-
140-
bool lastIsSlash = true;
141-
142-
for (int i = 0; i < pointerLength; i++)
143-
{
144-
char c = property[i];
145-
if (c == '.' || c == '[' || c == ']')
146-
{
147-
if (!lastIsSlash)
148-
pointerBuffer.Append('/');
149-
150-
lastIsSlash = true;
151-
}
152-
else
153-
{
154-
pointerBuffer.Append(c);
155-
lastIsSlash = false;
156-
}
157-
}
158-
159-
if (lastIsSlash)
160-
pointerBuffer.Length--;
161-
162-
return pointerBuffer.ToString();
163-
}
50+
=> Parser.PropertyToPointer(property);
16451
}

src/RoyalCode.SmartProblems.Tests/Basics/FindTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,24 @@ public void FindResult_Implicit_Problem()
6363
Assert.Equal("Error 1", problem.Detail);
6464
}
6565

66+
[Fact]
67+
public void FindResult_HasInvalidParameter()
68+
{
69+
// Arrange
70+
FindResult<Foo> result = new();
71+
72+
// Act
73+
var notFound = result.HasInvalidParameter(out var problem, "property");
74+
75+
// Assert
76+
Assert.False(result.Found);
77+
Assert.True(notFound);
78+
Assert.NotNull(problem);
79+
Assert.Equal("The record for 'Foo' was not found", problem.Detail);
80+
Assert.Equal(ProblemCategory.InvalidParameter, problem.Category);
81+
Assert.Equal("property", problem.Property);
82+
}
83+
6684
[Fact]
6785
public void FindResult_Implicit_Result_Entity()
6886
{

src/RoyalCode.SmartProblems.Tests/Conversions/PointerParserTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class PointerParserTests
3333
[InlineData("a/10", "a[10]")]
3434
[InlineData("a/10/b", "a[10].b")]
3535
[InlineData("a/10/b/", "a[10].b")]
36-
public void PointerToProperty(string pointer, string expected)
36+
public void PointerToProperty(string? pointer, string? expected)
3737
{
3838
var property = pointer.PointerToProperty();
3939

@@ -52,7 +52,7 @@ public void PointerToProperty(string pointer, string expected)
5252
[InlineData("[0]", "#/0")]
5353
[InlineData("[0].a", "#/0/a")]
5454
[InlineData("[0].a.b", "#/0/a/b")]
55-
public void PropertyToPointer(string property, string expected)
55+
public void PropertyToPointer(string? property, string? expected)
5656
{
5757
var pointer = property.PropertyToPointer();
5858

0 commit comments

Comments
 (0)