Skip to content

Commit 9299def

Browse files
committed
Merge branch 'main' into include
# Conflicts: # test/GqlPlus.ComponentTestBase/Samples/git-details.txt
2 parents 382afde + f6f1ea5 commit 9299def

File tree

508 files changed

+19072
-1307
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

508 files changed

+19072
-1307
lines changed

GqlPlus.sln

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GqlPlus.Abstractions.ClassT
7878
EndProject
7979
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GqlPlus.TestGenerators", "test\GqlPlus.TestGenerators\GqlPlus.TestGenerators.csproj", "{B061A811-3DBB-4E5A-AD96-91F0A74FE3C2}"
8080
EndProject
81-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GqlPlus.TestGeneratorsTests", "test\GqlPlus.TestGeneratorsTests\GqlPlus.TestGeneratorsTests.csproj", "{BB113C8C-1B2C-4815-A4DF-051F9237AF0E}"
81+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GqlPlus.TestGenerators.Tests", "test\GqlPlus.TestGenerators.Tests\GqlPlus.TestGenerators.Tests.csproj", "{BB113C8C-1B2C-4815-A4DF-051F9237AF0E}"
8282
EndProject
8383
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GqlPlus.PolyFill", "src\GqlPlus.PolyFill\GqlPlus.PolyFill.csproj", "{44D55F97-4EBA-48C8-A72C-7FBC12A44719}"
8484
EndProject

coverage.runsettings

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
<ModulePaths>
1212
<Include>
1313
<ModulePath>.*\\GqlPlus\.Abstractions\.dll$</ModulePath>
14-
<ModulePath>.*\\GqlPlus\.Generators\.dll$</ModulePath>
14+
<ModulePath>.*\\GqlPlus\.Converter\.Json\.dll$</ModulePath>
15+
<ModulePath>.*\\GqlPlus\.Converter\.Yaml\.dll$</ModulePath>
1516
<ModulePath>.*\\GqlPlus\.Modeller\.dll$</ModulePath>
1617
<ModulePath>.*\\GqlPlus\.Parser\.dll$</ModulePath>
1718
<ModulePath>.*\\GqlPlus\.Verifier\.dll$</ModulePath>

src/GqlPlus.Abstractions/GeneralHelpers.cs

+23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System.Diagnostics.CodeAnalysis;
2+
using System.Reflection;
23
using System.Runtime.CompilerServices;
4+
using GqlPlus.Structures;
35

46
namespace GqlPlus;
57

@@ -8,6 +10,27 @@ public static class GeneralHelpers
810
public static TResult[] ArrayOf<TResult>(this IEnumerable<object>? items)
911
=> [.. items?.OfType<TResult>() ?? []];
1012

13+
public static string[]? FlagNames<TEnum>(this TEnum flagValue)
14+
where TEnum : Enum
15+
{
16+
Type type = typeof(TEnum);
17+
if (!type.GetCustomAttributes<FlagsAttribute>().Any()) {
18+
return null;
19+
}
20+
21+
int flags = (int)(object)flagValue;
22+
List<string> result = [];
23+
24+
foreach (object? value in Enum.GetValues(type)) {
25+
int flag = (int)value;
26+
if (flag.IsSingleFlag() && (flags & flag) == flag) {
27+
result.Add(Enum.GetName(type, flag));
28+
}
29+
}
30+
31+
return [.. result];
32+
}
33+
1134
public static string Joined(this IEnumerable<string?>? items, string by = " ")
1235
=> string.Join(by,
1336
items?.Where(i => !string.IsNullOrWhiteSpace(i))

src/GqlPlus.Abstractions/GqlPlus.Abstractions.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
<ItemGroup>
44
<PackageReference Include="Microsoft.Bcl.HashCode" Version="6.0.0" />
5-
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.3" />
6-
<PackageReference Include="System.Collections.Immutable" Version="9.0.3" />
5+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.4" />
6+
<PackageReference Include="System.Collections.Immutable" Version="9.0.4" />
77
</ItemGroup>
88

99
<ItemGroup>

src/GqlPlus.Abstractions/Structures/StructureHelper.cs

+3
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ public static Structured RenderEnum<TEnum>(this TEnum value)
5555
internal static bool BothValued<T>([NotNullWhen(true)] this T? left, [NotNullWhen(true)] T? right)
5656
=> left is not null && right is not null;
5757

58+
internal static bool BothAny<T>([NotNullWhen(true)] this IEnumerable<T>? left, [NotNullWhen(true)] IEnumerable<T>? right)
59+
=> left.BothValued(right) && left.Any() && right.Any();
60+
5861
public static bool IsSingleFlag(this int flag)
5962
{
6063
while (flag > 0) {

src/GqlPlus.Abstractions/Structures/StructureValue.cs

+10-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
namespace GqlPlus.Structures;
22

3-
#pragma warning disable CA1036 // Override methods on comparable types
4-
public sealed record class StructureValue
3+
// #pragma warning disable CA1036 // Override methods on comparable types
4+
public sealed class StructureValue
55
: IComparable<StructureValue>
66
, IEquatable<StructureValue>
77
{
@@ -39,6 +39,7 @@ public int CompareTo(StructureValue? other)
3939
: -1
4040
: -1;
4141

42+
public override bool Equals(object obj) => Equals(obj as StructureValue);
4243
public bool Equals(StructureValue? other)
4344
=> string.Equals(Tag, other?.Tag, StringComparison.Ordinal) && (Boolean.BothValued(other?.Boolean) ? Boolean.Value == other.Boolean
4445
: Number.BothValued(other?.Number) ? Number.Value == other.Number
@@ -51,20 +52,11 @@ public override int GetHashCode()
5152
Identifier?.GetHashCode() ?? 0,
5253
Text?.GetHashCode() ?? 0);
5354

54-
public string AsString
55-
{
56-
get {
57-
if (Identifier is not null) {
58-
return Identifier;
59-
} else if (Boolean is not null) {
60-
return Boolean.Value.TrueFalse();
61-
} else if (Number is not null) {
62-
return $"{Number}";
63-
} else if (Text is not null) {
64-
return Text;
65-
}
66-
67-
return string.Empty;
68-
}
69-
}
55+
public string AsString => this switch {
56+
{ Boolean: not null } => Boolean.Value.TrueFalse(),
57+
{ Identifier: not null } => Identifier,
58+
{ Number: not null } => $"{Number}",
59+
{ Text: not null } => Text,
60+
_ => string.Empty,
61+
};
7062
}

src/GqlPlus.Abstractions/Structures/Structured.cs

+14-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Diagnostics.CodeAnalysis;
2-
using System.Reflection;
32

43
namespace GqlPlus.Structures;
54

@@ -89,20 +88,16 @@ public Structured AddIf(bool optional, Func<Structured, Structured>? onTrue = nu
8988
public Structured AddSet<TEnum>(string key, TEnum set, string? tag = null, bool flow = true)
9089
where TEnum : Enum
9190
{
92-
Type type = typeof(TEnum);
91+
string[]? flags = set.FlagNames();
9392

94-
if (type.GetCustomAttributes<FlagsAttribute>().Any()) {
95-
int flags = (int)(object)set;
93+
if (flags is not null) {
9694
Dict result = [];
9795

98-
foreach (object? value in Enum.GetValues(type)) {
99-
int flag = (int)value;
100-
if (flag.IsSingleFlag() && (flags & flag) == flag) {
101-
result.Add(new(Enum.GetName(type, value)), new("_"));
102-
}
96+
foreach (string flag in flags) {
97+
result.Add(new(flag), new("_"));
10398
}
10499

105-
return Add(key, new(result, $"_Set({tag ?? type.TypeTag()})", flow: flow));
100+
return Add(key, new(result, $"_Set({tag ?? typeof(TEnum).TypeTag()})", flow: flow));
106101
}
107102

108103
return this;
@@ -111,16 +106,13 @@ public Structured AddSet<TEnum>(string key, TEnum set, string? tag = null, bool
111106
public bool Equals(Structured? other)
112107
=> string.Equals(Tag, other?.Tag, StringComparison.Ordinal)
113108
&& (Value.BothValued(other?.Value) ? Value.Equals(other.Value)
114-
: List.BothValued(other?.List) ? List.SequenceEqual(other.List)
115-
: Map.BothValued(other?.Map) && Map.Equals(other.Map));
109+
: List.BothAny(other?.List) ? List.SequenceEqual(other.List)
110+
: Map.BothAny(other?.Map) && Map.Equals(other.Map));
116111

117112
public override bool Equals(object? obj)
118113
=> Equals(obj as Structured);
119114
public override int GetHashCode()
120-
=> HashCode.Combine(Tag,
121-
Value?.GetHashCode() ?? 0,
122-
List?.GetHashCode() ?? 0,
123-
Map?.GetHashCode() ?? 0);
115+
=> HashCode.Combine(Tag, Value?.GetHashCode() ?? 0, List.GetHashCode(), Map.GetHashCode());
124116
}
125117

126118
#pragma warning disable CA1034 // Nested types should not be visible
@@ -134,10 +126,16 @@ internal sealed class Dict
134126
internal Dict() : base() { }
135127
internal Dict(IDictionary<TValue, TObject> dictionary)
136128
: base(dictionary) { }
129+
130+
public bool Equals(IDict other)
131+
=> other is not null
132+
&& Keys.OrderedEqual(other.Keys)
133+
&& Keys.All(k => this[k].Equals(other[k]));
137134
}
138135

139136
public interface IDict
140137
: IDictionary<TValue, TObject>
138+
, IEquatable<IDict>
141139
{ }
142140

143141
public TValue? Value { get; }

src/GqlPlus.Converter.Json/Convert/RenderJsonConverter.cs

-4
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@ internal abstract class RenderJsonConverter<T>
55
{
66
protected void WriteValue(Utf8JsonWriter writer, StructureValue value)
77
{
8-
if (value is null || value.IsEmpty) {
9-
return;
10-
}
11-
128
if (value.Identifier is not null) {
139
writer.WriteStringValue(value.Identifier);
1410
} else if (value.Boolean is not null) {

src/GqlPlus.Converter.Json/Convert/RenderStructureJsonConverter.cs

+25-16
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,45 @@
1-
namespace GqlPlus.Convert;
1+
using System.Diagnostics.CodeAnalysis;
2+
3+
namespace GqlPlus.Convert;
24
internal class RenderStructureJsonConverter
35
: RenderJsonConverter<Structured>
46
{
57
internal static RenderValueJsonConverter ValueConverter { get; } = new();
68

9+
[ExcludeFromCodeCoverage]
710
public override Structured? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => throw new NotImplementedException();
811
public override void Write(Utf8JsonWriter writer, Structured value, JsonSerializerOptions options)
912
{
10-
if (value is null || value.IsEmpty) {
11-
return;
12-
}
13-
1413
bool plain = string.IsNullOrWhiteSpace(value.Tag);
1514

1615
if (value.List.Count > 0) {
1716
WriteList(writer, value.List, options);
1817
return;
19-
} else if (value.Map.Count > 0) {
20-
Structured first = value.Map.First().Value;
21-
if (value.Map.Count == 1 && !plain && string.IsNullOrWhiteSpace(first.Tag) && first.Value is not null) {
22-
StartTaggedValue(writer, value.Tag);
23-
WriteValue(writer, first.Value);
24-
writer.WriteEndObject();
25-
} else {
26-
WriteMap(writer, value.Map, value.Tag, options);
27-
}
28-
} else if (value.Value is not null) {
18+
}
19+
20+
if (value.Map.Count > 0) {
21+
WriteMap(writer, value, options, plain);
22+
return;
23+
}
24+
25+
if (value.Value is not null) {
2926
ValueConverter.Write(writer, value.Value, options);
3027
}
3128
}
3229

33-
private void WriteMap(Utf8JsonWriter writer, Structured<StructureValue, Structured>.IDict map, string tag, JsonSerializerOptions options)
30+
private void WriteMap(Utf8JsonWriter writer, Structured value, JsonSerializerOptions options, bool plain)
31+
{
32+
Structured first = value.Map.First().Value;
33+
if (value.Map.Count == 1 && !plain && string.IsNullOrWhiteSpace(first.Tag) && first.Value is not null) {
34+
StartTaggedValue(writer, value.Tag);
35+
WriteValue(writer, first.Value);
36+
writer.WriteEndObject();
37+
} else {
38+
WriteFullMap(writer, value.Map, value.Tag, options);
39+
}
40+
}
41+
42+
private void WriteFullMap(Utf8JsonWriter writer, Structured<StructureValue, Structured>.IDict map, string tag, JsonSerializerOptions options)
3443
{
3544
writer.WriteStartObject();
3645

src/GqlPlus.Converter.Json/Convert/RenderValueJsonConverter.cs

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
namespace GqlPlus.Convert;
1+
using System.Diagnostics.CodeAnalysis;
2+
3+
namespace GqlPlus.Convert;
24

35
internal class RenderValueJsonConverter
46
: RenderJsonConverter<StructureValue>
57
{
8+
[ExcludeFromCodeCoverage]
69
public override StructureValue? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => throw new NotImplementedException();
710
public override void Write(Utf8JsonWriter writer, StructureValue value, JsonSerializerOptions options)
811
{
9-
if (value is null || value.IsEmpty) {
10-
return;
11-
}
12-
1312
if (string.IsNullOrWhiteSpace(value.Tag)) {
1413
WriteValue(writer, value);
1514
return;

src/GqlPlus.Converter.Json/GqlPlus.Converter.Json.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<ItemGroup>
4-
<PackageReference Include="System.Text.Json" Version="9.0.3" />
4+
<PackageReference Include="System.Text.Json" Version="9.0.4" />
55
</ItemGroup>
66

77
<ItemGroup>

src/GqlPlus.Converter.Yaml/Convert/RenderYaml.cs

-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,4 @@ static RenderYaml()
3232

3333
public static string ToYaml(this Structured model, bool wrapped)
3434
=> (wrapped ? YamlWrapped : YamlFull).Serialize(model);
35-
36-
public static string YamlJoin(this IEnumerable<string> list, string start, string end)
37-
=> start + string.Join(", ", list ?? []) + end;
3835
}

src/GqlPlus.Converter.Yaml/Convert/RenderYamlTypeConverter.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using YamlDotNet.Core.Events;
1+
using System.Diagnostics.CodeAnalysis;
2+
using YamlDotNet.Core.Events;
23

34
namespace GqlPlus.Convert;
45

@@ -24,8 +25,11 @@ internal class RenderYamlTypeConverter
2425
{
2526
public bool Accepts(Type type) => type == typeof(Structured);
2627

28+
[ExcludeFromCodeCoverage]
2729
public object? ReadYaml(IParser parser, Type type) => throw new NotImplementedException();
30+
[ExcludeFromCodeCoverage]
2831
public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) => throw new NotImplementedException();
32+
2933
public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
3034
{
3135
if (value is Structured model) {

src/GqlPlus.Modeller/Convert/RenderLines.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Text;
2-
using GqlPlus.Ast;
32

43
namespace GqlPlus.Convert;
54

@@ -142,7 +141,7 @@ private static void WriteMap(StringBuilder sb, string tag, Structured<StructureV
142141
}
143142
}
144143

145-
private static char[] s_special = ['{', '}', '[', ']', '&', '*', '#', '?', '|', '-', '<', '>', '=', '!', '%', '@', ':', '`', ','];
144+
private static readonly char[] s_special = ['{', '}', '[', ']', '&', '*', '#', '?', '|', '-', '<', '>', '=', '!', '%', '@', ':', '`', ','];
146145

147146
private static void WriteValue(StringBuilder sb, StructureValue value, string suffix, int indent)
148147
{

src/GqlPlus.Parser/GqlPlus.Parser.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<ItemGroup>
44
<PackageReference Include="Microsoft.Bcl.HashCode" Version="6.0.0" />
5-
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.3" />
5+
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.4" />
66
</ItemGroup>
77

88
<ItemGroup>

src/GqlPlus.Parser/Merging/Globals/MergeCategories.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ internal class MergeCategories(
77
ILoggerFactory logger
88
) : AstAliasedMerger<IGqlpSchemaCategory>(logger)
99
{
10-
public override ITokenMessages CanMerge(IEnumerable<IGqlpSchemaCategory> items)
11-
=> base.CanMerge(items)
12-
.Add(items.CanMergeStruct(item => item.CategoryOption));
10+
protected override ITokenMessages CanMergeGroup(IGrouping<string, IGqlpSchemaCategory> group)
11+
=> base.CanMergeGroup(group)
12+
.Add(group.CanMergeStruct(item => item.CategoryOption));
1313

1414
protected override string ItemMatchName => "Output~Modifiers~Option";
1515
protected override string ItemMatchKey(IGqlpSchemaCategory item)

src/GqlPlus.Parser/Merging/Objects/MergeOutputFields.cs

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using GqlPlus.Abstractions.Schema;
2-
using GqlPlus.Ast;
32
using GqlPlus.Ast.Schema.Objects;
43

54
namespace GqlPlus.Merging.Objects;

src/GqlPlus.Verifier/Verifying/Schema/UsageContext.cs

-4
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,6 @@ internal static TContext CheckType<TContext, TObjBase>(this TContext context, TO
110110
where TContext : UsageContext
111111
where TObjBase : IGqlpObjType
112112
{
113-
if (type is null) {
114-
return context;
115-
}
116-
117113
string typeName = (type.IsTypeParam ? "$" : "") + type.Name;
118114
if (context.GetType(typeName, out IGqlpDescribed? value)) {
119115
CheckTypeArgs(AddCheckError, type, check, value);

test/Directory.Build.targets

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
<ItemGroup Condition="$(IsTestProject) == true">
1111
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
12-
<PackageReference Include="xunit.v3" Version="2.0.0" />
12+
<PackageReference Include="xunit.v3" Version="2.0.1" />
1313
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
1414
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1515
<PrivateAssets>all</PrivateAssets>

0 commit comments

Comments
 (0)