Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f36d2f6

Browse files
authored
Merge branch 'develop/3.0' into default-includes
2 parents a7fdf37 + b3fc926 commit f36d2f6

14 files changed

+186
-39
lines changed

Directory.Packages.props

+9-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
For more information what this is see https://github.com/NuGet/Home/wiki/Centrally-managing-NuGet-package-versions
55
-->
66
<PropertyGroup>
7+
<MsExtensionNugetVersion>6.0.0</MsExtensionNugetVersion>
78
<RoslynPackageVersion>4.2.0</RoslynPackageVersion>
89
</PropertyGroup>
910
<ItemGroup>
@@ -12,7 +13,7 @@
1213
<PackageVersion Include="System.Text.Json" Version="6.0.5"/>
1314
<PackageVersion Include="ClangSharp.PInvokeGenerator" Version="14.0.0-beta2"/>
1415
<PackageVersion Include="Microsoft.Build.Locator" Version="1.4.1"/>
15-
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="6.0.0-preview.6.21352.12"/>
16+
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="$(MsExtensionNugetVersion)"/>
1617
<PackageVersion Include="Microsoft.Build.Framework" Version="16.10.0"/>
1718
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="$(RoslynPackageVersion)"/>
1819
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="$(RoslynPackageVersion)"/>
@@ -25,10 +26,10 @@
2526
<PackageVersion Include="Microsoft.Bcl.HashCode" Version="1.1.0"/>
2627
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.3.1"/>
2728
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="6.0.0"/>
28-
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0"/>
29-
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0"/>
30-
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0"/>
31-
<PackageVersion Include="Microsoft.Extensions.Options" Version="6.0.0"/>
29+
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="$(MsExtensionNugetVersion)"/>
30+
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MsExtensionNugetVersion)"/>
31+
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="$(MsExtensionNugetVersion)"/>
32+
<PackageVersion Include="Microsoft.Extensions.Options" Version="$(MsExtensionNugetVersion)"/>
3233
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="16.8.0"/>
3334
<PackageVersion Include="xunit" Version="2.4.1"/>
3435
<PackageVersion Include="xunit.runner.visualstudio" Version="2.4.3"/>
@@ -46,5 +47,8 @@
4647
<PackageVersion Include="libclang" Version="14.0.0"/>
4748
<PackageVersion Include="libClangSharp" Version="14.0.0-beta1"/>
4849
<PackageVersion Include="Verify.Xunit" Version="16.9.0" />
50+
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="$(MsExtensionNugetVersion)" />
51+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="$(MsExtensionNugetVersion)" />
52+
<PackageVersion Include="Microsoft.Extensions.Logging" Version="$(MsExtensionNugetVersion)" />
4953
</ItemGroup>
5054
</Project>

src/generators/Silk.NET.SilkTouch.Scraper/ClangScraper.cs

+31-8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using ClangSharp;
1212
using ClangSharp.Interop;
1313
using Silk.NET.SilkTouch.Scraper.Subagent;
14+
using Microsoft.Extensions.Logging;
1415
using Silk.NET.SilkTouch.Symbols;
1516

1617
namespace Silk.NET.SilkTouch.Scraper;
@@ -20,6 +21,7 @@ namespace Silk.NET.SilkTouch.Scraper;
2021
/// </summary>
2122
public sealed class ClangScraper
2223
{
24+
private readonly ILoggerFactory _loggerFactory;
2325
/// <summary>
2426
/// Placeholder used in place of library paths
2527
/// </summary>
@@ -30,6 +32,15 @@ public sealed class ClangScraper
3032
/// </summary>
3133
public static readonly string LibraryNamespacePlaceholder = "LIBRARY_NAMESPACE";
3234

35+
/// <summary>
36+
/// Creates a ClangScraper given it's dependencies
37+
/// </summary>
38+
/// <param name="loggerFactory">A logger factory to create loggers from</param>
39+
public ClangScraper(ILoggerFactory loggerFactory)
40+
{
41+
_loggerFactory = loggerFactory;
42+
}
43+
3344
/// <summary>
3445
/// Scrapes the given XML document for symbols
3546
/// </summary>
@@ -44,7 +55,7 @@ public IEnumerable<Symbol> ScrapeXML(XmlDocument document)
4455
return Enumerable.Empty<Symbol>();
4556
}
4657

47-
var visitor = new XmlVisitor();
58+
var visitor = new XmlVisitor(_loggerFactory.CreateLogger<XmlVisitor>());
4859
return visitor.Visit(bindings);
4960
}
5061

@@ -105,6 +116,7 @@ public IEnumerable<string> ResolveStandardIncludes()
105116
/// <exception cref="InvalidOperationException">Will be thrown when errors during parsing are encountered</exception>
106117
public XmlDocument? GenerateXML(string headerFile, string[] includedNames, string[] excludedNames, string[] includeDirectories, string[] definedMacros)
107118
{
119+
var logger = _loggerFactory.CreateLogger("ClangScraper.ScrapeXML");
108120
var opts = PInvokeGeneratorConfigurationOptions.None;
109121
opts |= PInvokeGeneratorConfigurationOptions.NoDefaultRemappings;
110122

@@ -158,11 +170,11 @@ Stream OutputStreamFactory(string fileName)
158170
try
159171
{
160172
using (var pinvokeGenerator = new PInvokeGenerator(config, OutputStreamFactory))
161-
GenerateBindings(pinvokeGenerator, headerFile, commandLineArgs.ToArray(), translationFlags);
173+
GenerateBindings(pinvokeGenerator, headerFile, commandLineArgs.ToArray(), translationFlags, logger);
162174

163175
foreach (var (name, stream) in files)
164176
{
165-
Console.WriteLine(name);
177+
logger.LogTrace("Outputting File \"{name}\"", name);
166178
var doc = new XmlDocument();
167179
stream.Position = 0;
168180
doc.Load(stream);
@@ -185,7 +197,8 @@ private static void GenerateBindings
185197
PInvokeGenerator pinvokeGenerator,
186198
string headerFile,
187199
string[] commandLineArgs,
188-
CXTranslationUnit_Flags translationFlags
200+
CXTranslationUnit_Flags translationFlags,
201+
ILogger logger
189202
)
190203
{
191204
var result = CXTranslationUnit.TryParse
@@ -221,10 +234,20 @@ out var handle
221234

222235
foreach (var diagnostic in pinvokeGenerator.Diagnostics)
223236
{
224-
if (diagnostic.Level > DiagnosticLevel.Warning)
225-
{
226-
Console.WriteLine(diagnostic.Message);
227-
}
237+
logger.Log
238+
(
239+
diagnostic.Level switch
240+
{
241+
DiagnosticLevel.Info => LogLevel.Debug,
242+
DiagnosticLevel.Warning => LogLevel.Information,
243+
DiagnosticLevel.Error => LogLevel.Warning,
244+
_ => LogLevel.Debug
245+
},
246+
"Clang Diagnostic: {level} at: {location} \"{message}\"",
247+
diagnostic.Level,
248+
diagnostic.Level,
249+
diagnostic.Message
250+
);
228251
}
229252
}
230253
finally

src/generators/Silk.NET.SilkTouch.Scraper/XmlVisitor.cs

+74-11
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,23 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Collections.Immutable;
7+
using System.Diagnostics.CodeAnalysis;
78
using System.Linq;
89
using System.Reflection.Metadata;
910
using System.Xml;
11+
using Microsoft.Extensions.Logging;
1012
using Silk.NET.SilkTouch.Symbols;
13+
using TypeReference=Silk.NET.SilkTouch.Symbols.TypeReference;
1114

1215
namespace Silk.NET.SilkTouch.Scraper;
1316

1417
internal sealed class XmlVisitor
1518
{
19+
private readonly ILogger _logger;
20+
public XmlVisitor(ILogger logger) {
21+
_logger = logger;
22+
}
23+
1624
public IEnumerable<Symbol> Visit(XmlNode node)
1725
{
1826
switch (node)
@@ -40,22 +48,77 @@ private IEnumerable<Symbol> VisitField(XmlElement field)
4048
throw new InvalidOperationException("Field requires a name");
4149
}
4250

43-
// TODO: Appropriately Visit Type.
44-
var type = new ExternalTypeReference
45-
(
46-
null,
47-
new IdentifierSymbol
48-
(
49-
field.ChildNodes.Cast<XmlNode>().SingleOrDefault(x => x.Name == "type")?.InnerText ??
50-
throw new InvalidOperationException("Could not decode Field Type")
51-
)
52-
);
51+
var typeNode = field.ChildNodes.Cast<XmlNode>().SingleOrDefault(x => x.Name == "type") as XmlElement;
52+
if (typeNode is null)
53+
throw new InvalidOperationException("Field type cannot be null");
54+
55+
TypeReference? finalType = null;
56+
foreach (var type in VisitType(typeNode))
57+
{
58+
if (type is null)
59+
{
60+
throw new InvalidOperationException
61+
(
62+
$"{nameof(XmlVisitor)}.{nameof(VisitType)} has returned null"
63+
);
64+
}
65+
66+
if (type is not TypeReference tr)
67+
{
68+
throw new InvalidOperationException
69+
(
70+
$"{nameof(XmlVisitor)}.{nameof(VisitType)} has returned something other then a type reference"
71+
);
72+
}
73+
74+
if (finalType is not null)
75+
{
76+
throw new InvalidOperationException
77+
($"{nameof(XmlVisitor)}.{nameof(VisitType)} has returned more then one result");
78+
}
79+
80+
finalType = tr;
81+
}
82+
83+
if (finalType is null)
84+
{
85+
throw new InvalidOperationException
86+
($"No type could be resolved from {typeNode.OuterXml}");
87+
}
5388

5489
return new[]
5590
{
56-
new FieldSymbol(type, new IdentifierSymbol(name))
91+
new FieldSymbol(finalType, new IdentifierSymbol(name))
5792
};
5893
}
94+
95+
// TODO: Configurable Type maps
96+
private static readonly Dictionary<string, TypeReference> _typeMap = new()
97+
{
98+
["int"] = new ExternalTypeReference(null, new IdentifierSymbol("int"))
99+
};
100+
101+
private bool TryResolveTypeRef(string text, [NotNullWhen(true)] out TypeReference? reference)
102+
{
103+
if (_typeMap.TryGetValue(text, out reference))
104+
{
105+
return true;
106+
}
107+
else
108+
{
109+
_logger.LogDebug("Failed to resolve type reference from \"{text}\"", text);
110+
return false;
111+
}
112+
}
113+
114+
// NOTE: This does not visit types as in class/struct, but visits *references* to types. Like from methods or fields.
115+
private IEnumerable<Symbol> VisitType(XmlElement type)
116+
{
117+
return
118+
TryResolveTypeRef(type.InnerText, out var r)
119+
? new[] { r }
120+
: Array.Empty<Symbol>();
121+
}
59122

60123
private IEnumerable<Symbol> VisitStruct(XmlElement @struct)
61124
{

tests/Silk.NET.SilkTouch.IntegrationTests/Silk.NET.SilkTouch.IntegrationTests.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
<PackageReference Include="libclang" />
2121
<PackageReference Include="libClangSharp" />
2222
<PackageReference Include="Verify.Xunit" />
23+
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
2324
</ItemGroup>
2425

2526
<ItemGroup>

tests/Silk.NET.SilkTouch.IntegrationTests/StructIntegrationTests.cs

+17
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,23 @@ struct S
152152
int i;
153153
double d;
154154
};
155+
};");
156+
return Verifier.Verify(result);
157+
}
158+
159+
[Fact,
160+
Trait("Category", "Integration"),
161+
Trait("Source Language", "C++"),
162+
Trait("Target Language", "C#"),
163+
Trait("Feature", "Structs"),
164+
Trait("Feature", "Fields")]
165+
public Task Test8()
166+
{
167+
var result = TestHelper.GetCSharpOutputFromCpp(@"
168+
struct a {
169+
struct x { struct a *p; /* ... */ };
170+
171+
struct x *p;
155172
};");
156173
return Verifier.Verify(result);
157174
}

tests/Silk.NET.SilkTouch.IntegrationTests/TestHelper.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
5-
using System.Diagnostics;
5+
using System.Data;
66
using System.IO;
77
using System.Linq;
8+
using Microsoft.Extensions.DependencyInjection;
9+
using Microsoft.Extensions.Logging;
810
using Silk.NET.SilkTouch.Emitter;
911
using Silk.NET.SilkTouch.Scraper;
1012
using Xunit;
@@ -16,10 +18,13 @@ public static class TestHelper
1618
public static string GetCSharpOutputFromCpp(string cpp)
1719
{
1820
var tempFile = Path.GetTempFileName();
21+
var serviceProvider = new ServiceCollection()
22+
.AddLogging(builder => builder.AddConsole())
23+
.BuildServiceProvider();
1924

2025
File.WriteAllText(tempFile, "/* THIS IS A GENERATED FILE, PIPED TO CLANG FOR TESTING BY SILK.NET */" + cpp);
2126

22-
var scraper = new ClangScraper();
27+
var scraper = new ClangScraper(serviceProvider.GetRequiredService<ILoggerFactory>());
2328
var defaultIncludes = scraper.ResolveStandardIncludes().ToArray();
2429
var xml = scraper.GenerateXML
2530
(tempFile, defaultIncludes, Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>());

tests/Silk.NET.SilkTouch.Scraper.Tests/BasicXMLTests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ typedef struct {
4444
int32_t f2;
4545
} Test;");
4646

47-
var scraper = new ClangScraper();
47+
var scraper = Helpers.CreateScraper();
4848
var defaultIncludes = scraper.ResolveStandardIncludes().ToArray();
4949
var xml = scraper.GenerateXML
5050
(tempFile, defaultIncludes, Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>());

tests/Silk.NET.SilkTouch.Scraper.Tests/FieldScrapingTests.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public void FieldSymbol()
1717
var doc = new XmlDocument();
1818
doc.LoadXml(@"<field name=""f2""><type native=""int32_t"">int</type></field>");
1919

20-
var symbols = new ClangScraper().ScrapeXML(doc);
20+
var symbols = Helpers.CreateScraper().ScrapeXML(doc);
2121

2222
var symbol = Assert.Single(symbols);
2323
var field = Assert.IsType<FieldSymbol>(symbol);
@@ -31,7 +31,7 @@ public void CorrectIdentifier()
3131
var doc = new XmlDocument();
3232
doc.LoadXml(@"<field name=""f2""><type native=""int32_t"">int</type></field>");
3333

34-
var symbols = new ClangScraper().ScrapeXML(doc);
34+
var symbols = Helpers.CreateScraper().ScrapeXML(doc);
3535

3636
var symbol = Assert.Single(symbols);
3737
var field = Assert.IsType<FieldSymbol>(symbol);
@@ -46,7 +46,7 @@ public void CorrectType()
4646
var doc = new XmlDocument();
4747
doc.LoadXml(@"<field name=""f2""><type native=""int32_t"">int</type></field>");
4848

49-
var symbols = new ClangScraper().ScrapeXML(doc);
49+
var symbols = Helpers.CreateScraper().ScrapeXML(doc);
5050

5151
var symbol = Assert.Single(symbols);
5252
var field = Assert.IsType<FieldSymbol>(symbol);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
using System;
5+
using System.Collections.Generic;
6+
using System.Xml;
7+
using Microsoft.Extensions.DependencyInjection;
8+
using Microsoft.Extensions.Logging;
9+
using Silk.NET.SilkTouch.Symbols;
10+
11+
namespace Silk.NET.SilkTouch.Scraper.Tests;
12+
13+
public static class Helpers
14+
{
15+
private static IServiceProvider CreateServiceProvider()
16+
{
17+
return new ServiceCollection()
18+
.AddLogging(builder =>
19+
{
20+
builder.AddConsole();
21+
builder.SetMinimumLevel(LogLevel.Trace);
22+
}
23+
)
24+
.BuildServiceProvider();
25+
}
26+
27+
public static ClangScraper CreateScraper()
28+
{
29+
var serviceProvider = CreateServiceProvider();
30+
31+
return new ClangScraper(serviceProvider.GetRequiredService<ILoggerFactory>());
32+
}
33+
}

tests/Silk.NET.SilkTouch.Scraper.Tests/IdentityScrapingTests.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public void GeneratesNoSymbols()
1515
{
1616
var doc = new XmlDocument();
1717

18-
var symbols = new ClangScraper().ScrapeXML(doc);
18+
var symbols = Helpers.CreateScraper().ScrapeXML(doc);
1919

2020
Assert.Empty(symbols);
2121
}
@@ -29,7 +29,7 @@ public void BindingsGeneratesNoSymbols()
2929
</bindings>
3030
");
3131

32-
var symbols = new ClangScraper().ScrapeXML(doc);
32+
var symbols = Helpers.CreateScraper().ScrapeXML(doc);
3333

3434
Assert.Empty(symbols);
3535
}

0 commit comments

Comments
 (0)