diff --git a/src/generators/Silk.NET.SilkTouch.Symbols/PointerTypeReference.cs b/src/generators/Silk.NET.SilkTouch.Symbols/PointerTypeReference.cs
new file mode 100644
index 0000000000..144927da2d
--- /dev/null
+++ b/src/generators/Silk.NET.SilkTouch.Symbols/PointerTypeReference.cs
@@ -0,0 +1,10 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Silk.NET.SilkTouch.Symbols;
+
+///
+/// A representing a pointer type
+///
+/// A reference to the pointed to type
+public sealed record PointerTypeReference(TypeReference Underlying) : TypeReference;
diff --git a/src/generators/Silk.NET.SilkTouch.Symbols/SymbolVisitor.cs b/src/generators/Silk.NET.SilkTouch.Symbols/SymbolVisitor.cs
index 4b02981e1a..fc33285300 100644
--- a/src/generators/Silk.NET.SilkTouch.Symbols/SymbolVisitor.cs
+++ b/src/generators/Silk.NET.SilkTouch.Symbols/SymbolVisitor.cs
@@ -60,7 +60,7 @@ protected virtual MemberSymbol VisitMember(MemberSymbol memberSymbol)
/// The field symbol to visit
/// The rewritten symbol
///
- /// The order in which the parts of the struct are visited is kept as an implementation detail. Do not rely on this order.
+ /// The order in which the parts are visited is kept as an implementation detail. Do not rely on this order.
///
protected virtual FieldSymbol VisitField(FieldSymbol fieldSymbol)
{
@@ -73,7 +73,7 @@ protected virtual FieldSymbol VisitField(FieldSymbol fieldSymbol)
/// The type reference to visit
/// The rewritten symbol
///
- /// The order in which the parts of the struct are visited is kept as an implementation detail. Do not rely on this order.
+ /// The order in which the parts are visited is kept as an implementation detail. Do not rely on this order.
///
///
/// By default visiting will throw. Visitors involved in type resolution should override this method directly.
@@ -83,16 +83,30 @@ protected virtual TypeReference VisitTypeReference(TypeReference typeReference)
if (typeReference is ExternalTypeReference etr) return VisitExternalTypeReference(etr);
if (typeReference is InternalTypeReference itr) return VisitInternalTypeReference(itr);
if (typeReference is UnresolvedTypeReference utr) UnresolvedTypeReference.ThrowInvalidSymbol();
+ if (typeReference is PointerTypeReference ptr) return VisitPointerTypeReference(ptr);
return ThrowUnknownSymbol(typeReference);
}
+ ///
+ /// Visit a . Will call the appropriate methods to visit the different parts of the symbol.
+ ///
+ /// The pointer type reference to visit
+ /// The rewritten symbol
+ ///
+ /// The order in which the parts are visited is kept as an implementation detail. Do not rely on this order.
+ ///
+ protected virtual PointerTypeReference VisitPointerTypeReference(PointerTypeReference pointerTypeReference)
+ {
+ return new PointerTypeReference(VisitTypeReference(pointerTypeReference.Underlying));
+ }
+
///
/// Visit a . Will call the appropriate methods to visit the different parts of the symbol.
///
/// The type reference to visit
/// The rewritten symbol
///
- /// The order in which the parts of the struct are visited is kept as an implementation detail. Do not rely on this order.
+ /// The order in which the parts are visited is kept as an implementation detail. Do not rely on this order.
///
protected virtual InternalTypeReference VisitInternalTypeReference(InternalTypeReference typeReference)
{
@@ -105,7 +119,7 @@ protected virtual InternalTypeReference VisitInternalTypeReference(InternalTypeR
/// The type reference to visit
/// The rewritten symbol
///
- /// The order in which the parts of the struct are visited is kept as an implementation detail. Do not rely on this order.
+ /// The order in which the parts are visited is kept as an implementation detail. Do not rely on this order.
///
protected virtual ExternalTypeReference VisitExternalTypeReference(ExternalTypeReference typeReference)
{
@@ -155,7 +169,7 @@ protected virtual TypeSymbol VisitType(TypeSymbol typeSymbol)
/// The rewritten symbol
///
///
- /// The order in which the parts of the struct are visited is kept as an implementation detail. Do not rely on this order.
+ /// The order in which the parts are visited is kept as an implementation detail. Do not rely on this order.
///
protected virtual StructSymbol VisitStruct(StructSymbol structSymbol)
{
diff --git a/src/generators/Silk.NET.SilkTouch.TypeResolution/PointerTypeResolver.cs b/src/generators/Silk.NET.SilkTouch.TypeResolution/PointerTypeResolver.cs
new file mode 100644
index 0000000000..15750815f9
--- /dev/null
+++ b/src/generators/Silk.NET.SilkTouch.TypeResolution/PointerTypeResolver.cs
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Silk.NET.SilkTouch.Symbols;
+
+namespace Silk.NET.SilkTouch.TypeResolution;
+
+///
+/// Resolves s with Text like "a*", "a.b.c*" to a with the underlying set to an with text = "a", "a.b.c", etc.
+///
+///
+///
+///
+/// Input Tree
+/// Output Tree
+///
+///
+/// -
+/// (Text = "a.b.c*")
+/// (Underlying = (Text = "a.b.c"))
+///
+///
+/// -
+/// (Text = "int*")
+/// (Underlying = (Text = "int"))
+///
+///
+/// -
+/// (Text = "a")
+/// (Text = "a")
+///
+///
+///
+public sealed class PointerTypeResolver : SimpleTypeResolverBase
+{
+
+ ///
+ public PointerTypeResolver(TypeStore typeStore) : base(typeStore)
+ {
+ }
+
+ ///
+ protected override bool TryResolve(UnresolvedTypeReference utr, out TypeReference? resolved)
+ {
+ if (utr.Text.Length > 1 && utr.Text[utr.Text.Length - 1] == '*')
+ {
+ resolved = new PointerTypeReference(new UnresolvedTypeReference(utr.Text.Substring(0, utr.Text.Length - 1)));
+ return true;
+ }
+ resolved = null;
+ return false;
+ }
+}
diff --git a/src/generators/Silk.NET.SilkTouch.TypeResolution/SimpleTypeResolverBase.cs b/src/generators/Silk.NET.SilkTouch.TypeResolution/SimpleTypeResolverBase.cs
new file mode 100644
index 0000000000..41abafb00c
--- /dev/null
+++ b/src/generators/Silk.NET.SilkTouch.TypeResolution/SimpleTypeResolverBase.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Silk.NET.SilkTouch.Symbols;
+
+namespace Silk.NET.SilkTouch.TypeResolution;
+
+///
+/// A base to simplify creation of basic type resolvers that only need simple text matching.
+///
+public abstract class SimpleTypeResolverBase : SymbolVisitor
+{
+ ///
+ protected SimpleTypeResolverBase(TypeStore typeStore) : base(typeStore)
+ {
+ }
+
+ ///
+ protected override TypeReference VisitTypeReference(TypeReference typeSymbol)
+ {
+ if (typeSymbol is UnresolvedTypeReference utr)
+ {
+ return TryResolve(utr, out var result) ? result! : utr;
+ }
+ return base.VisitTypeReference(typeSymbol);
+ }
+
+ ///
+ /// Resolve an
+ ///
+ /// THe unresolved reference to attempt to resolve
+ /// The resolved reference. May not be null if true is returned.
+ /// Whether resolution was successful
+ ///
+ /// This method is free to return a partial resolution, and still return true.
+ /// Partial resolutions are such that do not have a at the root,
+ /// but have somewhere in the tree.
+ ///
+ protected abstract bool TryResolve(UnresolvedTypeReference utr, out TypeReference? resolved);
+}
diff --git a/tests/Silk.NET.SilkTouch.Symbols.Tests/SymbolVisitorTests/PointerTypeReferenceTests.cs b/tests/Silk.NET.SilkTouch.Symbols.Tests/SymbolVisitorTests/PointerTypeReferenceTests.cs
new file mode 100644
index 0000000000..54ffad42c1
--- /dev/null
+++ b/tests/Silk.NET.SilkTouch.Symbols.Tests/SymbolVisitorTests/PointerTypeReferenceTests.cs
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Moq;
+using Moq.Protected;
+using Xunit;
+
+namespace Silk.NET.SilkTouch.Symbols.Tests.SymbolVisitorTests;
+
+public class PointerTypeReferenceTests
+{
+ [Fact, Trait("Category", "Type Resolution")]
+ public void RefIsVisitedAsSelf()
+ {
+ var symbol = new PointerTypeReference(new InternalTypeReference(TypeId.CreateNew()));
+
+ var visitor = new Mock { CallBase = true };
+
+ visitor.Object.Visit(symbol);
+
+ visitor.Protected()
+ .Verify
+ ("VisitPointerTypeReference", Times.Once(), ItExpr.IsAny());
+ }
+
+ [Fact, Trait("Category", "Type Resolution")]
+ public void RefIsVisitedAsRef()
+ {
+ var symbol = new PointerTypeReference(new InternalTypeReference(TypeId.CreateNew()));
+
+ var visitor = new Mock { CallBase = true };
+
+ visitor.Object.Visit(symbol);
+
+ visitor.Protected()
+ .Verify
+ ("VisitTypeReference", Times.Once(), ItExpr.Is(x => ReferenceEquals(x, symbol)));
+ }
+
+ [Fact, Trait("Category", "Type Resolution")]
+ public void RefUnderlyingIsVisitedAsRef()
+ {
+ var underlying = new InternalTypeReference(TypeId.CreateNew());
+ var symbol = new PointerTypeReference(underlying);
+
+ var visitor = new Mock { CallBase = true };
+
+ visitor.Object.Visit(symbol);
+
+ visitor.Protected()
+ .Verify
+ ("VisitTypeReference", Times.Once(), ItExpr.Is(x => ReferenceEquals(x, underlying)));
+ }
+}
diff --git a/tests/Silk.NET.SilkTouch.TestFramework/SilkTouchTestFramework.cs b/tests/Silk.NET.SilkTouch.TestFramework/SilkTouchTestFramework.cs
index bd3657748a..2873d4fc51 100644
--- a/tests/Silk.NET.SilkTouch.TestFramework/SilkTouchTestFramework.cs
+++ b/tests/Silk.NET.SilkTouch.TestFramework/SilkTouchTestFramework.cs
@@ -73,7 +73,7 @@ ITestFrameworkDiscoveryOptions discoveryOptions
foreach (var (name, value) in traits)
{
if (name is "Category" &&
- value is not "Integration" and not "Scraper" and not "Symbols" and not "Emitter" and not "TypeStore")
+ value is not "Integration" and not "Scraper" and not "Symbols" and not "Emitter" and not "TypeStore" and not "Type Resolution")
{
return this.ReportDiscoveredTestCase
(
diff --git a/tests/Silk.NET.SilkTouch.TypeResolution.Tests/PointerResolverTests.cs b/tests/Silk.NET.SilkTouch.TypeResolution.Tests/PointerResolverTests.cs
new file mode 100644
index 0000000000..1d014f79cd
--- /dev/null
+++ b/tests/Silk.NET.SilkTouch.TypeResolution.Tests/PointerResolverTests.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Silk.NET.SilkTouch.Symbols;
+using Xunit;
+
+namespace Silk.NET.SilkTouch.TypeResolution.Tests;
+
+public sealed class PointerResolverTests
+{
+ [Theory, Trait("Category", "Type Resolution"),
+ InlineData("a*"),
+ InlineData("a.b.c*"),
+ InlineData("int*")
+ ]
+ public void ShouldResolve(string text)
+ {
+ var symbol = new UnresolvedTypeReference(text);
+ var output = new PointerTypeResolver(new TypeStore());
+
+ var finalSymbol = output.Visit(symbol);
+ Assert.IsType(finalSymbol);
+ }
+
+ [Theory, Trait("Category", "Type Resolution"),
+ InlineData(""),
+ InlineData("a"),
+ InlineData("*"),
+ InlineData("a.b.c"),
+ InlineData("longType"),
+ InlineData("int"),
+ InlineData("using")
+ ]
+ public void ShouldNotResolve(string text)
+ {
+ var symbol = new UnresolvedTypeReference(text);
+ var output = new PointerTypeResolver(new TypeStore());
+
+ var finalSymbol = output.Visit(symbol);
+ Assert.IsNotType(finalSymbol);
+ }
+}