Skip to content

Commit e0ce57b

Browse files
committed
Add Struct Symbols
1 parent 7f74101 commit e0ce57b

File tree

7 files changed

+169
-2
lines changed

7 files changed

+169
-2
lines changed

Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,6 @@
3939
<PackageVersion Include="Statiq.Yaml" Version="1.0.0-beta.48" />
4040
<PackageVersion Include="Humanizer.Core" Version="2.14.1" />
4141
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.1.0" />
42+
<PackageVersion Include="Moq" Version="4.17.2" />
4243
</ItemGroup>
4344
</Project>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Silk.NET.SilkTouch.Symbols;
5+
6+
/// <summary>
7+
/// An Identifier. Generally used to identify another symbol
8+
/// </summary>
9+
/// <seealso cref="TypeSymbol"/>
10+
public sealed class IdentifierSymbol : Symbol
11+
{
12+
/// <summary>
13+
/// Create an <see cref="IdentifierSymbol"/> from a string
14+
/// </summary>
15+
/// <param name="value">The identifier as a string</param>
16+
public IdentifierSymbol(string value)
17+
{
18+
Value = value;
19+
}
20+
21+
/// <summary>
22+
/// The Value of this Identifier as a String
23+
/// </summary>
24+
public string Value { get; }
25+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Silk.NET.SilkTouch.Symbols;
5+
6+
/// <summary>
7+
/// A <see cref="TypeSymbol"/> representing a <c>struct</c>.
8+
/// </summary>
9+
/// <remarks>
10+
/// In this context, a Struct means a type that represents the layout of a continuous block of memory.
11+
/// </remarks>
12+
// /// Each meaningful place in this memory called a field (see <see cref="FieldSymbol"/>) is accessible via this type.
13+
// /// Fields are allowed to overlap.
14+
// /// Additionally it may contain one or multiple <see cref="MethodSymbol"/> that are called with an instance of this type as their first argument.
15+
public sealed class StructSymbol : TypeSymbol
16+
{
17+
/// <summary>
18+
/// Creates a struct symbol given it's identifier
19+
/// </summary>
20+
/// <param name="identifier">The identifier of the struct</param>
21+
public StructSymbol(IdentifierSymbol identifier)
22+
{
23+
Identifier = identifier;
24+
}
25+
26+
/// <summary>
27+
/// The identifier of this struct
28+
/// </summary>
29+
public override IdentifierSymbol Identifier { get; }
30+
}

src/generators/Silk.NET.SilkTouch.Symbols/SymbolVisitor.cs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,56 @@ namespace Silk.NET.SilkTouch.Symbols;
99
public abstract class SymbolVisitor
1010
{
1111
/// <summary>
12-
/// Visit a Symbol. This will call the appropriate method based on the actual type of the <paramref name="symbol"/>
12+
/// Visit a <see cref="Symbol"/>. This will call the appropriate method based on the actual type of the <paramref name="symbol"/>
1313
/// </summary>
1414
/// <param name="symbol">The symbol to visit</param>
1515
/// <returns>The rewritten symbol. May be equal to the original symbol of no rewriting has taken place.</returns>
1616
public virtual Symbol Visit(Symbol symbol)
1717
{
18-
return symbol;
18+
if (symbol is TypeSymbol ts) return VisitType(ts);
19+
20+
return ThrowUnknownSymbol(nameof(Symbol), symbol);
21+
}
22+
23+
/// <summary>
24+
/// Visit a <see cref="TypeSymbol"/>. This will call the appropriate method based on the actual type of the <paramref name="typeSymbol"/>
25+
/// </summary>
26+
/// <param name="typeSymbol">The type symbol to visit</param>
27+
/// <returns>The rewritten symbol. May or may not be a <see cref="TypeSymbol"/></returns>
28+
/// <seealso cref="VisitStruct"/>
29+
protected virtual Symbol VisitType(TypeSymbol typeSymbol)
30+
{
31+
if (typeSymbol is StructSymbol @struct) return VisitStruct(@struct);
32+
33+
return ThrowUnknownSymbol(nameof(TypeSymbol), typeSymbol);
34+
}
35+
36+
/// <summary>
37+
/// Visit a <see cref="StructSymbol"/>. Will call the appropriate methods to visit the different parts of the struct.
38+
/// </summary>
39+
/// <param name="structSymbol">The struct symbol to visit</param>
40+
/// <returns>The rewritten symbol. May or may not be a <see cref="StructSymbol"/></returns>
41+
/// <seealso cref="VisitType"/>
42+
/// <remarks>
43+
/// The order in which the parts of the struct are visited is kept as an implementation detail. Do not rely on this order.
44+
/// </remarks>
45+
protected virtual Symbol VisitStruct(StructSymbol structSymbol)
46+
{
47+
return new StructSymbol(VisitIdentifier(structSymbol.Identifier));
48+
}
49+
50+
/// <summary>
51+
/// Visit an <see cref="IdentifierSymbol"/>.
52+
/// </summary>
53+
/// <param name="identifierSymbol">The Identifier to Visit</param>
54+
/// <returns>The rewritten symbol</returns>
55+
protected virtual IdentifierSymbol VisitIdentifier(IdentifierSymbol identifierSymbol)
56+
{
57+
return identifierSymbol;
58+
}
59+
60+
private static Symbol ThrowUnknownSymbol(string type, Symbol symbol)
61+
{
62+
throw new NotImplementedException($"Unknown symbol of type {symbol.GetType().FullName} subclass of {type}");
1963
}
2064
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Silk.NET.SilkTouch.Symbols;
5+
6+
/// <summary>
7+
/// A generic <see cref="Symbol"/> representing a named type.
8+
/// </summary>
9+
/// <seealso cref="StructSymbol"/>
10+
public abstract class TypeSymbol : Symbol
11+
{
12+
/// <summary>
13+
/// The identifier of this type
14+
/// </summary>
15+
public abstract IdentifierSymbol Identifier { get; }
16+
}

tests/Silk.NET.SilkTouch.Symbols.Tests/Silk.NET.SilkTouch.Symbols.Tests.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1515
<PrivateAssets>all</PrivateAssets>
1616
</PackageReference>
17+
<PackageReference Include="Moq" />
18+
</ItemGroup>
19+
20+
<ItemGroup>
21+
<ProjectReference Include="..\..\src\generators\Silk.NET.SilkTouch.Symbols\Silk.NET.SilkTouch.Symbols.csproj" />
1722
</ItemGroup>
1823

1924
</Project>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,56 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using Moq;
5+
using Moq.Protected;
46
using Xunit;
57

68
namespace Silk.NET.SilkTouch.Symbols.Tests;
79

810
public sealed class SymbolVisitorTests
911
{
12+
[Fact]
13+
public void StructSymbolIsVisitedAsType()
14+
{
15+
var symbol = new StructSymbol(new IdentifierSymbol(""));
16+
var visitor = new Mock<SymbolVisitor>
17+
{
18+
CallBase = true
19+
};
20+
21+
visitor.Object.Visit(symbol);
22+
23+
visitor.Protected()
24+
.Verify<Symbol>("VisitType", Times.Once(), ItExpr.IsAny<TypeSymbol>());
25+
}
26+
27+
[Fact]
28+
public void StructSymbolIsVisitedAsStruct()
29+
{
30+
var symbol = new StructSymbol(new IdentifierSymbol(""));
31+
var visitor = new Mock<SymbolVisitor>
32+
{
33+
CallBase = true
34+
};
35+
36+
visitor.Object.Visit(symbol);
37+
38+
visitor.Protected()
39+
.Verify<Symbol>("VisitStruct", Times.Once(), ItExpr.IsAny<StructSymbol>());
40+
}
41+
42+
[Fact]
43+
public void StructIdentifierIsVisitedAsIdentifier()
44+
{
45+
var symbol = new StructSymbol(new IdentifierSymbol(""));
46+
var visitor = new Mock<SymbolVisitor>
47+
{
48+
CallBase = true
49+
};
50+
51+
visitor.Object.Visit(symbol);
52+
53+
visitor.Protected()
54+
.Verify<Symbol>("VisitIdentifier", Times.Once(), ItExpr.IsAny<IdentifierSymbol>());
55+
}
1056
}

0 commit comments

Comments
 (0)