Skip to content

Commit bd95e97

Browse files
committed
Relation code generation WIP
1 parent 85f6b58 commit bd95e97

10 files changed

+363
-64
lines changed

BTDB.SourceGenerator.Test/GeneratorTestsBase.cs

+3-4
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@ protected static Task VerifySourceGenerator(string sourceCode)
1616
var driver = CSharpGeneratorDriver.Create([generator.AsSourceGenerator()],
1717
driverOptions: new GeneratorDriverOptions(default, trackIncrementalGeneratorSteps: true));
1818
var compilation = CSharpCompilation.Create("test",
19-
new[] { CSharpSyntaxTree.ParseText(sourceCode) },
20-
new[]
21-
{
19+
[CSharpSyntaxTree.ParseText(sourceCode)],
20+
[
2221
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
2322
MetadataReference.CreateFromFile(typeof(GenerateAttribute).Assembly.Location)
24-
}, new(OutputKind.ConsoleApplication, allowUnsafe: true));
23+
], new(OutputKind.ConsoleApplication, allowUnsafe: true));
2524
var runResult = driver.RunGenerators(compilation);
2625
// Update the compilation and rerun the generator
2726
compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText("// dummy"));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//HintName: TestNamespace.IPersonTable.g.cs
2+
// <auto-generated/>
3+
#pragma warning disable 612,618
4+
#nullable enable
5+
using System;
6+
using System.Runtime.CompilerServices;
7+
// Name: IPersonTable
8+
// Field: ParentId int
9+
// PrimaryIndex: 1
10+
// Field: PersonId int
11+
// PrimaryIndex: 2
12+
// Field: Name string reference
13+
14+
namespace TestNamespace;
15+
[CompilerGenerated]
16+
static file class IPersonTableRegistration
17+
{
18+
[ModuleInitializer]
19+
internal static unsafe void Register4BTDB()
20+
{
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//HintName: TestNamespace.Person.g.cs
2+
// <auto-generated/>
3+
#pragma warning disable 612,618
4+
using System;
5+
using System.Runtime.CompilerServices;
6+
7+
namespace TestNamespace;
8+
9+
[CompilerGenerated]
10+
static file class PersonRegistration
11+
{
12+
[UnsafeAccessor(UnsafeAccessorKind.Constructor)]
13+
extern static global::TestNamespace.Person Creator();
14+
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "<ParentId>k__BackingField")]
15+
extern static ref int Field1(global::TestNamespace.Person @this);
16+
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "<PersonId>k__BackingField")]
17+
extern static ref int Field2(global::TestNamespace.Person @this);
18+
[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "<Name>k__BackingField")]
19+
extern static ref string Field3(global::TestNamespace.Person @this);
20+
[ModuleInitializer]
21+
internal static unsafe void Register4BTDB()
22+
{
23+
global::BTDB.IOC.IContainer.RegisterFactory(typeof(global::TestNamespace.Person), (container, ctx) =>
24+
{
25+
return (container2, ctx2) =>
26+
{
27+
var res = new global::TestNamespace.Person();
28+
return res;
29+
};
30+
});
31+
var metadata = new global::BTDB.Serialization.ClassMetadata();
32+
metadata.Name = "Person";
33+
metadata.Type = typeof(global::TestNamespace.Person);
34+
metadata.Namespace = "TestNamespace";
35+
metadata.Implements = [];
36+
metadata.Creator = &Creator;
37+
var dummy = Unsafe.As<global::TestNamespace.Person>(metadata);
38+
metadata.Fields = new global::BTDB.Serialization.FieldMetadata[]
39+
{
40+
new global::BTDB.Serialization.FieldMetadata
41+
{
42+
Name = "ParentId",
43+
Type = typeof(int),
44+
ByteOffset = global::BTDB.Serialization.RawData.CalcOffset(dummy, ref Field1(dummy)),
45+
},
46+
new global::BTDB.Serialization.FieldMetadata
47+
{
48+
Name = "PersonId",
49+
Type = typeof(int),
50+
ByteOffset = global::BTDB.Serialization.RawData.CalcOffset(dummy, ref Field2(dummy)),
51+
},
52+
new global::BTDB.Serialization.FieldMetadata
53+
{
54+
Name = "Name",
55+
Type = typeof(string),
56+
ByteOffset = global::BTDB.Serialization.RawData.CalcOffset(dummy, ref Field3(dummy)),
57+
},
58+
};
59+
global::BTDB.Serialization.ReflectionMetadata.Register(metadata);
60+
}
61+
}
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.Threading.Tasks;
2+
using Xunit;
3+
4+
namespace BTDB.SourceGenerator.Tests;
5+
6+
public class RelationTests : GeneratorTestsBase
7+
{
8+
[Fact]
9+
public Task VerifyBasicRelation()
10+
{
11+
// language=cs
12+
return VerifySourceGenerator("""
13+
using BTDB.ODBLayer;
14+
15+
namespace TestNamespace;
16+
17+
public class Person
18+
{
19+
[PrimaryKey(1)] public int ParentId { get; set; }
20+
[PrimaryKey(2)] public int PersonId { get; set; }
21+
public string Name { get; set; } = null!;
22+
}
23+
24+
public interface IPersonTable : ICovariantRelation<Person>
25+
{
26+
}
27+
""");
28+
}
29+
}

BTDB.SourceGenerator/BTDB.SourceGenerator.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<PackageId>BTDB.SourceGenerator</PackageId>
1313
<Version>32.17.0</Version>
1414
<Authors>Boris Letocha</Authors>
15-
<PackageProjectUrl>http://github.com/Bobris/BTDB</PackageProjectUrl>
15+
<PackageProjectUrl>https://github.com/Bobris/BTDB</PackageProjectUrl>
1616
<PackageLicenseExpression>MIT</PackageLicenseExpression>
1717
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
1818
<PackageReadmeFile>README.md</PackageReadmeFile>
@@ -31,6 +31,6 @@
3131
<PrivateAssets>all</PrivateAssets>
3232
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
3333
</PackageReference>
34-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.11.0" PrivateAssets="all"/>
34+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" PrivateAssets="all"/>
3535
</ItemGroup>
3636
</Project>

BTDB.SourceGenerator/Extensions.cs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using Microsoft.CodeAnalysis;
3+
4+
namespace BTDB.SourceGenerator;
5+
6+
public static class Extensions
7+
{
8+
public static bool InNamespace(this ISymbol symbol, params ReadOnlySpan<string> namespaces)
9+
{
10+
if (symbol.ContainingNamespace is null) return false;
11+
var cs = symbol.ContainingNamespace;
12+
while (true)
13+
{
14+
switch (cs.IsGlobalNamespace)
15+
{
16+
case true when namespaces.Length == 0:
17+
return true;
18+
case true when namespaces.Length > 0:
19+
case false when namespaces.Length == 0:
20+
return false;
21+
}
22+
23+
if (cs.Name != namespaces[namespaces.Length - 1]) return false;
24+
cs = cs.ContainingNamespace;
25+
namespaces = namespaces.Slice(0, namespaces.Length - 1);
26+
}
27+
}
28+
29+
public static bool InBTDBNamespace(this ISymbol symbol) => symbol.InNamespace("BTDB");
30+
public static bool InODBLayerNamespace(this ISymbol symbol) => symbol.InNamespace("BTDB", "ODBLayer");
31+
}

0 commit comments

Comments
 (0)