Skip to content

Commit

Permalink
[ComInterfaceGenerator] Interface inheritance follow up (#85117)
Browse files Browse the repository at this point in the history
This commit creates types to model the Com interfaces and the methods in the com interfaces. The new types with suffix "Info" are meant to be the first step of the pipeline that can be created with just an ISymbol and SyntaxNode. The types suffixed with "Context" are meant to contain all info necessary for generating the code, and they may require multiple "Info"s to be created (e.g. need info about the base interface or other methods in the interface). There is also a type that represents the Com interface and all the methods that are required to generate the code necessary for Com.
  • Loading branch information
jtschuster authored May 16, 2023
1 parent 115a475 commit ff92d4e
Show file tree
Hide file tree
Showing 37 changed files with 1,226 additions and 406 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

namespace Microsoft.Interop
{
/// <summary>
/// Provides the info necessary for copying an attribute from user code to generated code.
/// </summary>
internal sealed record AttributeInfo(ManagedTypeInfo Type, SequenceEqualImmutableArray<string> Arguments)
{
internal static AttributeInfo From(AttributeData attribute)
{
var type = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(attribute.AttributeClass);
var args = attribute.ConstructorArguments.Select(ca => ca.ToCSharpString());
return new(type, args.ToSequenceEqualImmutableArray());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;

namespace Microsoft.Interop
{
public sealed partial class ComInterfaceGenerator
{
/// <summary>
/// Represents an interface and all of the methods that need to be generated for it (methods declared on the interface and methods inherited from base interfaces).
/// </summary>
private sealed record ComInterfaceAndMethodsContext(ComInterfaceContext Interface, SequenceEqualImmutableArray<ComMethodContext> Methods)
{
// Change Calc all methods to return an ordered list of all the methods and the data in comInterfaceandMethodsContext
// Have a step that runs CalculateMethodStub on each of them.
// Call GroupMethodsByInterfaceForGeneration

/// <summary>
/// COM methods that are declared on the attributed interface declaration.
/// </summary>
public IEnumerable<ComMethodContext> DeclaredMethods => Methods.Where(m => !m.IsInheritedMethod);

/// <summary>
/// COM methods that are declared on an interface the interface inherits from.
/// </summary>
public IEnumerable<ComMethodContext> ShadowingMethods => Methods.Where(m => m.IsInheritedMethod);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;

namespace Microsoft.Interop
{
public sealed partial class ComInterfaceGenerator
{
private sealed record ComInterfaceContext(ComInterfaceInfo Info, ComInterfaceContext? Base)
{
/// <summary>
/// Takes a list of ComInterfaceInfo, and creates a list of ComInterfaceContext.
/// </summary>
public static ImmutableArray<ComInterfaceContext> GetContexts(ImmutableArray<ComInterfaceInfo> data, CancellationToken _)
{
Dictionary<string, ComInterfaceInfo> symbolToInterfaceInfoMap = new();
var accumulator = ImmutableArray.CreateBuilder<ComInterfaceContext>(data.Length);
foreach (var iface in data)
{
symbolToInterfaceInfoMap.Add(iface.ThisInterfaceKey, iface);
}
Dictionary<string, ComInterfaceContext> symbolToContextMap = new();

foreach (var iface in data)
{
accumulator.Add(AddContext(iface));
}
return accumulator.MoveToImmutable();

ComInterfaceContext AddContext(ComInterfaceInfo iface)
{
if (symbolToContextMap.TryGetValue(iface.ThisInterfaceKey, out var cachedValue))
{
return cachedValue;
}

if (iface.BaseInterfaceKey is null)
{
var baselessCtx = new ComInterfaceContext(iface, null);
symbolToContextMap[iface.ThisInterfaceKey] = baselessCtx;
return baselessCtx;
}

if (!symbolToContextMap.TryGetValue(iface.BaseInterfaceKey, out var baseContext))
{
baseContext = AddContext(symbolToInterfaceInfoMap[iface.BaseInterfaceKey]);
}
var ctx = new ComInterfaceContext(iface, baseContext);
symbolToContextMap[iface.ThisInterfaceKey] = ctx;
return ctx;
}
}
}
}
}
Loading

0 comments on commit ff92d4e

Please sign in to comment.