diff --git a/Directory.Packages.props b/Directory.Packages.props
index 457763170e..f84f3a8e92 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -4,6 +4,7 @@
For more information what this is see https://github.com/NuGet/Home/wiki/Centrally-managing-NuGet-package-versions
-->
+ 6.0.0
4.2.0
@@ -12,7 +13,7 @@
-
+
@@ -25,10 +26,10 @@
-
-
-
-
+
+
+
+
@@ -46,5 +47,8 @@
+
+
+
diff --git a/src/generators/Silk.NET.SilkTouch.Scraper/ClangScraper.cs b/src/generators/Silk.NET.SilkTouch.Scraper/ClangScraper.cs
index 2cc06cdd70..0c6c918285 100644
--- a/src/generators/Silk.NET.SilkTouch.Scraper/ClangScraper.cs
+++ b/src/generators/Silk.NET.SilkTouch.Scraper/ClangScraper.cs
@@ -9,6 +9,7 @@
using System.Xml;
using ClangSharp;
using ClangSharp.Interop;
+using Microsoft.Extensions.Logging;
using Silk.NET.SilkTouch.Symbols;
namespace Silk.NET.SilkTouch.Scraper;
@@ -18,6 +19,7 @@ namespace Silk.NET.SilkTouch.Scraper;
///
public sealed class ClangScraper
{
+ private readonly ILoggerFactory _loggerFactory;
///
/// Placeholder used in place of library paths
///
@@ -28,6 +30,15 @@ public sealed class ClangScraper
///
public static readonly string LibraryNamespacePlaceholder = "LIBRARY_NAMESPACE";
+ ///
+ /// Creates a ClangScraper given it's dependencies
+ ///
+ /// A logger factory to create loggers from
+ public ClangScraper(ILoggerFactory loggerFactory)
+ {
+ _loggerFactory = loggerFactory;
+ }
+
///
/// Scrapes the given XML document for symbols
///
@@ -42,7 +53,7 @@ public IEnumerable ScrapeXML(XmlDocument document)
return Enumerable.Empty();
}
- var visitor = new XmlVisitor();
+ var visitor = new XmlVisitor(_loggerFactory.CreateLogger());
return visitor.Visit(bindings);
}
@@ -58,6 +69,7 @@ public IEnumerable ScrapeXML(XmlDocument document)
/// Will be thrown when errors during parsing are encountered
public XmlDocument? GenerateXML(string headerFile, string[] includedNames, string[] excludedNames, string[] includeDirectories, string[] definedMacros)
{
+ var logger = _loggerFactory.CreateLogger("ClangScraper.ScrapeXML");
var opts = PInvokeGeneratorConfigurationOptions.None;
opts |= PInvokeGeneratorConfigurationOptions.NoDefaultRemappings;
@@ -105,11 +117,11 @@ Stream OutputStreamFactory(string fileName)
try
{
using (var pinvokeGenerator = new PInvokeGenerator(config, OutputStreamFactory))
- GenerateBindings(pinvokeGenerator, headerFile, commandLineArgs.ToArray(), translationFlags);
+ GenerateBindings(pinvokeGenerator, headerFile, commandLineArgs.ToArray(), translationFlags, logger);
foreach (var (name, stream) in files)
{
- Console.WriteLine(name);
+ logger.LogTrace("Outputting File \"{name}\"", name);
var doc = new XmlDocument();
stream.Position = 0;
doc.Load(stream);
@@ -132,7 +144,8 @@ private static void GenerateBindings
PInvokeGenerator pinvokeGenerator,
string headerFile,
string[] commandLineArgs,
- CXTranslationUnit_Flags translationFlags
+ CXTranslationUnit_Flags translationFlags,
+ ILogger logger
)
{
var result = CXTranslationUnit.TryParse
@@ -168,10 +181,20 @@ out var handle
foreach (var diagnostic in pinvokeGenerator.Diagnostics)
{
- if (diagnostic.Level > DiagnosticLevel.Warning)
- {
- Console.WriteLine(diagnostic.Message);
- }
+ logger.Log
+ (
+ diagnostic.Level switch
+ {
+ DiagnosticLevel.Info => LogLevel.Debug,
+ DiagnosticLevel.Warning => LogLevel.Information,
+ DiagnosticLevel.Error => LogLevel.Warning,
+ _ => LogLevel.Debug
+ },
+ "Clang Diagnostic: {level} at: {location} \"{message}\"",
+ diagnostic.Level,
+ diagnostic.Level,
+ diagnostic.Message
+ );
}
}
finally
diff --git a/src/generators/Silk.NET.SilkTouch.Scraper/XmlVisitor.cs b/src/generators/Silk.NET.SilkTouch.Scraper/XmlVisitor.cs
index 20d9f407ee..8f7d395c52 100644
--- a/src/generators/Silk.NET.SilkTouch.Scraper/XmlVisitor.cs
+++ b/src/generators/Silk.NET.SilkTouch.Scraper/XmlVisitor.cs
@@ -4,15 +4,23 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection.Metadata;
using System.Xml;
+using Microsoft.Extensions.Logging;
using Silk.NET.SilkTouch.Symbols;
+using TypeReference=Silk.NET.SilkTouch.Symbols.TypeReference;
namespace Silk.NET.SilkTouch.Scraper;
internal sealed class XmlVisitor
{
+ private readonly ILogger _logger;
+ public XmlVisitor(ILogger logger) {
+ _logger = logger;
+ }
+
public IEnumerable Visit(XmlNode node)
{
switch (node)
@@ -40,22 +48,77 @@ private IEnumerable VisitField(XmlElement field)
throw new InvalidOperationException("Field requires a name");
}
- // TODO: Appropriately Visit Type.
- var type = new ExternalTypeReference
- (
- null,
- new IdentifierSymbol
- (
- field.ChildNodes.Cast().SingleOrDefault(x => x.Name == "type")?.InnerText ??
- throw new InvalidOperationException("Could not decode Field Type")
- )
- );
+ var typeNode = field.ChildNodes.Cast().SingleOrDefault(x => x.Name == "type") as XmlElement;
+ if (typeNode is null)
+ throw new InvalidOperationException("Field type cannot be null");
+
+ TypeReference? finalType = null;
+ foreach (var type in VisitType(typeNode))
+ {
+ if (type is null)
+ {
+ throw new InvalidOperationException
+ (
+ $"{nameof(XmlVisitor)}.{nameof(VisitType)} has returned null"
+ );
+ }
+
+ if (type is not TypeReference tr)
+ {
+ throw new InvalidOperationException
+ (
+ $"{nameof(XmlVisitor)}.{nameof(VisitType)} has returned something other then a type reference"
+ );
+ }
+
+ if (finalType is not null)
+ {
+ throw new InvalidOperationException
+ ($"{nameof(XmlVisitor)}.{nameof(VisitType)} has returned more then one result");
+ }
+
+ finalType = tr;
+ }
+
+ if (finalType is null)
+ {
+ throw new InvalidOperationException
+ ($"No type could be resolved from {typeNode.OuterXml}");
+ }
return new[]
{
- new FieldSymbol(type, new IdentifierSymbol(name))
+ new FieldSymbol(finalType, new IdentifierSymbol(name))
};
}
+
+ // TODO: Configurable Type maps
+ private static readonly Dictionary _typeMap = new()
+ {
+ ["int"] = new ExternalTypeReference(null, new IdentifierSymbol("int"))
+ };
+
+ private bool TryResolveTypeRef(string text, [NotNullWhen(true)] out TypeReference? reference)
+ {
+ if (_typeMap.TryGetValue(text, out reference))
+ {
+ return true;
+ }
+ else
+ {
+ _logger.LogDebug("Failed to resolve type reference from \"{text}\"", text);
+ return false;
+ }
+ }
+
+ // NOTE: This does not visit types as in class/struct, but visits *references* to types. Like from methods or fields.
+ private IEnumerable VisitType(XmlElement type)
+ {
+ return
+ TryResolveTypeRef(type.InnerText, out var r)
+ ? new[] { r }
+ : Array.Empty();
+ }
private IEnumerable VisitStruct(XmlElement @struct)
{
diff --git a/tests/Silk.NET.SilkTouch.IntegrationTests/Silk.NET.SilkTouch.IntegrationTests.csproj b/tests/Silk.NET.SilkTouch.IntegrationTests/Silk.NET.SilkTouch.IntegrationTests.csproj
index a6d8c8d43e..d9bd64a93c 100644
--- a/tests/Silk.NET.SilkTouch.IntegrationTests/Silk.NET.SilkTouch.IntegrationTests.csproj
+++ b/tests/Silk.NET.SilkTouch.IntegrationTests/Silk.NET.SilkTouch.IntegrationTests.csproj
@@ -20,6 +20,7 @@
+
diff --git a/tests/Silk.NET.SilkTouch.IntegrationTests/StructIntegrationTests.cs b/tests/Silk.NET.SilkTouch.IntegrationTests/StructIntegrationTests.cs
index ce9cfcb13d..5472d9f525 100644
--- a/tests/Silk.NET.SilkTouch.IntegrationTests/StructIntegrationTests.cs
+++ b/tests/Silk.NET.SilkTouch.IntegrationTests/StructIntegrationTests.cs
@@ -152,6 +152,23 @@ struct S
int i;
double d;
};
+};");
+ return Verifier.Verify(result);
+ }
+
+ [Fact,
+ Trait("Category", "Integration"),
+ Trait("Source Language", "C++"),
+ Trait("Target Language", "C#"),
+ Trait("Feature", "Structs"),
+ Trait("Feature", "Fields")]
+ public Task Test8()
+ {
+ var result = TestHelper.GetCSharpOutputFromCpp(@"
+struct a {
+ struct x { struct a *p; /* ... */ };
+
+ struct x *p;
};");
return Verifier.Verify(result);
}
diff --git a/tests/Silk.NET.SilkTouch.IntegrationTests/TestHelper.cs b/tests/Silk.NET.SilkTouch.IntegrationTests/TestHelper.cs
index 30907b7e2d..11faf8bb01 100644
--- a/tests/Silk.NET.SilkTouch.IntegrationTests/TestHelper.cs
+++ b/tests/Silk.NET.SilkTouch.IntegrationTests/TestHelper.cs
@@ -2,9 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Diagnostics;
+using System.Data;
using System.IO;
using System.Linq;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
using Silk.NET.SilkTouch.Emitter;
using Silk.NET.SilkTouch.Scraper;
using Xunit;
@@ -16,10 +18,13 @@ public static class TestHelper
public static string GetCSharpOutputFromCpp(string cpp)
{
var tempFile = Path.GetTempFileName();
+ var serviceProvider = new ServiceCollection()
+ .AddLogging(builder => builder.AddConsole())
+ .BuildServiceProvider();
File.WriteAllText(tempFile, "/* THIS IS A GENERATED FILE, PIPED TO CLANG FOR TESTING BY SILK.NET */" + cpp);
- var scraper = new ClangScraper();
+ var scraper = new ClangScraper(serviceProvider.GetRequiredService());
var xml = scraper.GenerateXML
(tempFile, Array.Empty(), Array.Empty(), Array.Empty(), Array.Empty());
diff --git a/tests/Silk.NET.SilkTouch.Scraper.Tests/BasicXMLTests.cs b/tests/Silk.NET.SilkTouch.Scraper.Tests/BasicXMLTests.cs
index ee46bb7ace..ebb7f8ec67 100644
--- a/tests/Silk.NET.SilkTouch.Scraper.Tests/BasicXMLTests.cs
+++ b/tests/Silk.NET.SilkTouch.Scraper.Tests/BasicXMLTests.cs
@@ -44,7 +44,7 @@ typedef struct {
int32_t f2;
} Test;");
- var scraper = new ClangScraper();
+ var scraper = Helpers.CreateScraper();
var xml = scraper.GenerateXML
(tempFile, Array.Empty(), Array.Empty(), Array.Empty(), Array.Empty());
diff --git a/tests/Silk.NET.SilkTouch.Scraper.Tests/FieldScrapingTests.cs b/tests/Silk.NET.SilkTouch.Scraper.Tests/FieldScrapingTests.cs
index 29d3129782..11e04deb59 100644
--- a/tests/Silk.NET.SilkTouch.Scraper.Tests/FieldScrapingTests.cs
+++ b/tests/Silk.NET.SilkTouch.Scraper.Tests/FieldScrapingTests.cs
@@ -17,7 +17,7 @@ public void FieldSymbol()
var doc = new XmlDocument();
doc.LoadXml(@"int");
- var symbols = new ClangScraper().ScrapeXML(doc);
+ var symbols = Helpers.CreateScraper().ScrapeXML(doc);
var symbol = Assert.Single(symbols);
var field = Assert.IsType(symbol);
@@ -31,7 +31,7 @@ public void CorrectIdentifier()
var doc = new XmlDocument();
doc.LoadXml(@"int");
- var symbols = new ClangScraper().ScrapeXML(doc);
+ var symbols = Helpers.CreateScraper().ScrapeXML(doc);
var symbol = Assert.Single(symbols);
var field = Assert.IsType(symbol);
@@ -46,7 +46,7 @@ public void CorrectType()
var doc = new XmlDocument();
doc.LoadXml(@"int");
- var symbols = new ClangScraper().ScrapeXML(doc);
+ var symbols = Helpers.CreateScraper().ScrapeXML(doc);
var symbol = Assert.Single(symbols);
var field = Assert.IsType(symbol);
diff --git a/tests/Silk.NET.SilkTouch.Scraper.Tests/Helpers.cs b/tests/Silk.NET.SilkTouch.Scraper.Tests/Helpers.cs
new file mode 100644
index 0000000000..4337aff747
--- /dev/null
+++ b/tests/Silk.NET.SilkTouch.Scraper.Tests/Helpers.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Xml;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Silk.NET.SilkTouch.Symbols;
+
+namespace Silk.NET.SilkTouch.Scraper.Tests;
+
+public static class Helpers
+{
+ private static IServiceProvider CreateServiceProvider()
+ {
+ return new ServiceCollection()
+ .AddLogging(builder =>
+ {
+ builder.AddConsole();
+ builder.SetMinimumLevel(LogLevel.Trace);
+ }
+ )
+ .BuildServiceProvider();
+ }
+
+ public static ClangScraper CreateScraper()
+ {
+ var serviceProvider = CreateServiceProvider();
+
+ return new ClangScraper(serviceProvider.GetRequiredService());
+ }
+}
diff --git a/tests/Silk.NET.SilkTouch.Scraper.Tests/IdentityScrapingTests.cs b/tests/Silk.NET.SilkTouch.Scraper.Tests/IdentityScrapingTests.cs
index 8e4307c8f7..f4f1a92789 100644
--- a/tests/Silk.NET.SilkTouch.Scraper.Tests/IdentityScrapingTests.cs
+++ b/tests/Silk.NET.SilkTouch.Scraper.Tests/IdentityScrapingTests.cs
@@ -15,7 +15,7 @@ public void GeneratesNoSymbols()
{
var doc = new XmlDocument();
- var symbols = new ClangScraper().ScrapeXML(doc);
+ var symbols = Helpers.CreateScraper().ScrapeXML(doc);
Assert.Empty(symbols);
}
@@ -29,7 +29,7 @@ public void BindingsGeneratesNoSymbols()
");
- var symbols = new ClangScraper().ScrapeXML(doc);
+ var symbols = Helpers.CreateScraper().ScrapeXML(doc);
Assert.Empty(symbols);
}
diff --git a/tests/Silk.NET.SilkTouch.Scraper.Tests/NamespaceScrapingTests.cs b/tests/Silk.NET.SilkTouch.Scraper.Tests/NamespaceScrapingTests.cs
index 8272af6382..c27deb787c 100644
--- a/tests/Silk.NET.SilkTouch.Scraper.Tests/NamespaceScrapingTests.cs
+++ b/tests/Silk.NET.SilkTouch.Scraper.Tests/NamespaceScrapingTests.cs
@@ -21,7 +21,7 @@ public void NamespaceSymbol()
");
- var symbols = new ClangScraper().ScrapeXML(doc);
+ var symbols = Helpers.CreateScraper().ScrapeXML(doc);
var symbol = Assert.Single(symbols);
var @namespace = Assert.IsType(symbol);
@@ -42,7 +42,7 @@ public void NamespaceMember()
");
- var symbols = new ClangScraper().ScrapeXML(doc);
+ var symbols = Helpers.CreateScraper().ScrapeXML(doc);
var symbol = Assert.Single(symbols);
var @namespace = Assert.IsType(symbol);
@@ -68,7 +68,7 @@ public void MultipleNamespaceMembers()
");
- var symbols = new ClangScraper().ScrapeXML(doc);
+ var symbols = Helpers.CreateScraper().ScrapeXML(doc);
var symbol = Assert.Single(symbols);
var @namespace = Assert.IsType(symbol);
diff --git a/tests/Silk.NET.SilkTouch.Scraper.Tests/Silk.NET.SilkTouch.Scraper.Tests.csproj b/tests/Silk.NET.SilkTouch.Scraper.Tests/Silk.NET.SilkTouch.Scraper.Tests.csproj
index 2dc0e93a11..3ea7a2fb59 100644
--- a/tests/Silk.NET.SilkTouch.Scraper.Tests/Silk.NET.SilkTouch.Scraper.Tests.csproj
+++ b/tests/Silk.NET.SilkTouch.Scraper.Tests/Silk.NET.SilkTouch.Scraper.Tests.csproj
@@ -19,6 +19,7 @@
+
diff --git a/tests/Silk.NET.SilkTouch.Scraper.Tests/StructMemberScrapingTests.cs b/tests/Silk.NET.SilkTouch.Scraper.Tests/StructMemberScrapingTests.cs
index 0179dd2840..44cb47c6a6 100644
--- a/tests/Silk.NET.SilkTouch.Scraper.Tests/StructMemberScrapingTests.cs
+++ b/tests/Silk.NET.SilkTouch.Scraper.Tests/StructMemberScrapingTests.cs
@@ -18,7 +18,7 @@ public void SingleMember()
var doc = new XmlDocument();
doc.LoadXml(@"int");
- var symbols = new ClangScraper().ScrapeXML(doc);
+ var symbols = Helpers.CreateScraper().ScrapeXML(doc);
var symbol = Assert.Single(symbols);
var @struct = Assert.IsType(symbol);
@@ -43,7 +43,7 @@ public void MultipleMembers()
@"intint"
);
- var symbols = new ClangScraper().ScrapeXML(doc);
+ var symbols = Helpers.CreateScraper().ScrapeXML(doc);
var symbol = Assert.Single(symbols);
var @struct = Assert.IsType(symbol);
diff --git a/tests/Silk.NET.SilkTouch.Scraper.Tests/StructScrapingTests.cs b/tests/Silk.NET.SilkTouch.Scraper.Tests/StructScrapingTests.cs
index 94dcaef881..b29d174d7a 100644
--- a/tests/Silk.NET.SilkTouch.Scraper.Tests/StructScrapingTests.cs
+++ b/tests/Silk.NET.SilkTouch.Scraper.Tests/StructScrapingTests.cs
@@ -17,7 +17,7 @@ public void StructSymbol()
var doc = new XmlDocument();
doc.LoadXml(@"");
- var symbols = new ClangScraper().ScrapeXML(doc);
+ var symbols = Helpers.CreateScraper().ScrapeXML(doc);
var symbol = Assert.Single(symbols);
var @struct = Assert.IsType(symbol);
@@ -31,7 +31,7 @@ public void CorrectIdentifier()
var doc = new XmlDocument();
doc.LoadXml(@"");
- var symbols = new ClangScraper().ScrapeXML(doc);
+ var symbols = Helpers.CreateScraper().ScrapeXML(doc);
var symbol = Assert.Single(symbols);
var @struct = Assert.IsType(symbol);