Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable creating C# projections based on multiple input winmd's and docs #386

Merged
merged 10 commits into from
Sep 7, 2021
5 changes: 3 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@
<IncludeSymbols Condition=" '$(DebugType)' != 'embedded' ">true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>

<MetadataVersion>10.2.163-preview</MetadataVersion>
<ApiDocsVersion>0.1.4-alpha</ApiDocsVersion>
<MetadataVersion>10.2.185-preview</MetadataVersion>
<!-- <DiaMetadataVersion>0.2.185-preview-g7e1e6a442c</DiaMetadataVersion> -->
<ApiDocsVersion>0.1.6-alpha</ApiDocsVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
4 changes: 3 additions & 1 deletion src/Microsoft.Windows.CsWin32/AnalyzerReleases.Unshipped.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ PInvoke001 | Functionality | Warning | SourceGenerator
PInvoke002 | Functionality | Warning | SourceGenerator
PInvoke003 | Functionality | Warning | SourceGenerator
PInvoke004 | Functionality | Warning | SourceGenerator
PInvoke005 | Functionality | Warning | SourceGenerator
PInvoke005 | Functionality | Warning | SourceGenerator
PInvoke006 | Configuration | Warning | SourceGenerator
PInvoke007 | Functionality | Error | SourceGenerator
43 changes: 40 additions & 3 deletions src/Microsoft.Windows.CsWin32/Docs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ namespace Microsoft.Windows.CsWin32
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Linq;
using MessagePack;
using Microsoft.Windows.SDK.Win32Docs;

internal class Docs
/// <summary>
/// An in-memory representation of API documentation.
/// </summary>
public class Docs
{
private static readonly Dictionary<string, Docs> DocsByPath = new Dictionary<string, Docs>(StringComparer.OrdinalIgnoreCase);

Expand All @@ -22,7 +25,12 @@ private Docs(Dictionary<string, ApiDetails> apisAndDocs)
this.apisAndDocs = apisAndDocs;
}

internal static Docs Get(string docsPath)
/// <summary>
/// Loads docs from a file.
/// </summary>
/// <param name="docsPath">The messagepack docs file to read from.</param>
/// <returns>An instance of <see cref="Docs"/> that accesses the documentation in the file specified by <paramref name="docsPath"/>.</returns>
public static Docs Get(string docsPath)
{
lock (DocsByPath)
{
Expand All @@ -48,6 +56,35 @@ internal static Docs Get(string docsPath)
}
}

/// <summary>
/// Returns a <see cref="Docs"/> instance that contains all the merged documentation from a list of docs.
/// </summary>
/// <param name="docs">The docs to be merged. When API documentation is provided by multiple docs in this list, the first one appearing in this list is taken.</param>
/// <returns>An instance that contains all the docs provided. When <paramref name="docs"/> contains exactly one element, that element is returned.</returns>
public static Docs Merge(IReadOnlyList<Docs> docs)
{
if (docs.Count == 1)
{
// Nothing to merge.
return docs[0];
}

Dictionary<string, ApiDetails> mergedDocs = new(docs.Sum(d => d.apisAndDocs.Count), StringComparer.OrdinalIgnoreCase);
foreach (Docs doc in docs)
{
foreach (KeyValuePair<string, ApiDetails> api in doc.apisAndDocs)
{
// We want a first one wins policy.
if (!mergedDocs.ContainsKey(api.Key))
{
mergedDocs.Add(api.Key, api.Value);
}
}
}

return new Docs(mergedDocs);
}

internal bool TryGetApiDocs(string apiName, [NotNullWhen(true)] out ApiDetails? docs) => this.apisAndDocs.TryGetValue(apiName, out docs);
}
}
211 changes: 165 additions & 46 deletions src/Microsoft.Windows.CsWin32/Generator.cs

Large diffs are not rendered by default.

10 changes: 0 additions & 10 deletions src/Microsoft.Windows.CsWin32/GeneratorOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ public record GeneratorOptions
/// <value>The default value is "PInvoke".</value>
public string? ClassName { get; init; } = "PInvoke";

/// <summary>
/// Gets the namespace for generated code.
/// </summary>
/// <value>The default value is "Windows.Win32". Must be non-empty.</value>
public string Namespace { get; init; } = "Windows.Win32";

/// <summary>
/// Gets a value indicating whether to emit a single source file as opposed to types spread across many files.
/// </summary>
Expand Down Expand Up @@ -57,10 +51,6 @@ public record GeneratorOptions
/// <exception cref="InvalidOperationException">Thrown when some setting is invalid.</exception>
public void Validate()
{
if (string.IsNullOrWhiteSpace(this.Namespace))
{
throw new InvalidOperationException("The namespace must be set.");
}
}

/// <summary>
Expand Down
Loading