@@ -37,6 +37,7 @@ public class Generator : IDisposable
3737    internal  const  string  UnmanagedInteropSuffix  =  "_unmanaged" ; 
3838
3939    internal  static readonly  SyntaxAnnotation  IsRetValAnnotation  =  new  SyntaxAnnotation ( "RetVal" ) ; 
40+     internal  static readonly  IdentifierNameSyntax  NestedCOMInterfaceName  =  IdentifierName ( "Interface" ) ; 
4041
4142    /// <summary> 
4243    /// A map of .NET interop structs to use, keyed by the native structs that should <em>not</em> be generated. 
@@ -3411,7 +3412,7 @@ private ClassDeclarationSyntax DeclareComInterfaceFriendlyExtensionsClass()
34113412    private  TypeDeclarationSyntax ?  DeclareInterface ( TypeDefinitionHandle  typeDefHandle ,  Context  context ) 
34123413    { 
34133414        TypeDefinition  typeDef  =  this . Reader . GetTypeDefinition ( typeDefHandle ) ; 
3414-         var  baseTypes  =  new   Stack < QualifiedTypeDefinitionHandle > ( ) ; 
3415+         var  baseTypes  =  ImmutableStack . Create < QualifiedTypeDefinitionHandle > ( ) ; 
34153416        ( Generator  Generator ,  InterfaceImplementationHandle  Handle )  baseTypeHandle  =  ( this ,  typeDef . GetInterfaceImplementations ( ) . SingleOrDefault ( ) ) ; 
34163417        while  ( ! baseTypeHandle . Handle . IsNil ) 
34173418        { 
@@ -3421,17 +3422,40 @@ private ClassDeclarationSyntax DeclareComInterfaceFriendlyExtensionsClass()
34213422                throw  new  GenerationFailedException ( "Failed to find base type." ) ; 
34223423            } 
34233424
3424-             baseTypes . Push ( baseTypeDefHandle ) ; 
3425+             baseTypes   =   baseTypes . Push ( baseTypeDefHandle ) ; 
34253426            TypeDefinition  baseType  =  baseTypeDefHandle . Reader . GetTypeDefinition ( baseTypeDefHandle . DefinitionHandle ) ; 
34263427            baseTypeHandle  =  ( baseTypeHandle . Generator ,  baseType . GetInterfaceImplementations ( ) . SingleOrDefault ( ) ) ; 
34273428        } 
34283429
3429-         return  ! context . AllowMarshaling  ||  this . IsNonCOMInterface ( typeDef ) 
3430-             ?  this . DeclareInterfaceAsStruct ( typeDefHandle ,  baseTypes ,  context ) 
3431-             :  this . DeclareInterfaceAsInterface ( typeDef ,  baseTypes ) ; 
3430+         if  ( this . IsNonCOMInterface ( typeDef ) ) 
3431+         { 
3432+             // We cannot declare an interface that is not COM-compliant. 
3433+             return  this . DeclareInterfaceAsStruct ( typeDefHandle ,  baseTypes ,  context ) ; 
3434+         } 
3435+ 
3436+         if  ( context . AllowMarshaling ) 
3437+         { 
3438+             // Marshaling is allowed here, and generally. Just emit the interface. 
3439+             return  this . DeclareInterfaceAsInterface ( typeDef ,  baseTypes ,  context ) ; 
3440+         } 
3441+ 
3442+         // Marshaling of this interface is not allowed here. Emit the struct. 
3443+         TypeDeclarationSyntax  structDecl  =  this . DeclareInterfaceAsStruct ( typeDefHandle ,  baseTypes ,  context ) ; 
3444+         if  ( ! this . options . AllowMarshaling ) 
3445+         { 
3446+             // Marshaling isn't allowed over the entire compilation, so emit the interface nested under the struct so 
3447+             // it can be implemented and enable CCW scenarios. 
3448+             TypeDeclarationSyntax ?  ifaceDecl  =  this . DeclareInterfaceAsInterface ( typeDef ,  baseTypes ,  context ,  interfaceAsSubtype :  true ) ; 
3449+             if  ( ifaceDecl  is  not null ) 
3450+             { 
3451+                 structDecl  =  structDecl . AddMembers ( ifaceDecl ) ; 
3452+             } 
3453+         } 
3454+ 
3455+         return  structDecl ; 
34323456    } 
34333457
3434-     private  TypeDeclarationSyntax  DeclareInterfaceAsStruct ( TypeDefinitionHandle  typeDefHandle ,  Stack < QualifiedTypeDefinitionHandle >  baseTypes ,  Context  context ) 
3458+     private  TypeDeclarationSyntax  DeclareInterfaceAsStruct ( TypeDefinitionHandle  typeDefHandle ,  ImmutableStack < QualifiedTypeDefinitionHandle >  baseTypes ,  Context  context ) 
34353459    { 
34363460        TypeDefinition  typeDef  =  this . Reader . GetTypeDefinition ( typeDefHandle ) ; 
34373461        IdentifierNameSyntax  ifaceName  =  IdentifierName ( this . GetMangledIdentifier ( this . Reader . GetString ( typeDef . Name ) ,  context . AllowMarshaling ,  isManagedType :  true ) ) ; 
@@ -3442,9 +3466,10 @@ private TypeDeclarationSyntax DeclareInterfaceAsStruct(TypeDefinitionHandle type
34423466
34433467        // It is imperative that we generate methods for all base interfaces as well, ahead of any implemented by *this* interface. 
34443468        var  allMethods  =  new  List < QualifiedMethodDefinitionHandle > ( ) ; 
3445-         while  ( baseTypes . Count   >   0 ) 
3469+         while  ( ! baseTypes . IsEmpty ) 
34463470        { 
3447-             QualifiedTypeDefinitionHandle  qualifiedBaseType  =  baseTypes . Pop ( ) ; 
3471+             QualifiedTypeDefinitionHandle  qualifiedBaseType  =  baseTypes . Peek ( ) ; 
3472+             baseTypes  =  baseTypes . Pop ( ) ; 
34483473            TypeDefinition  baseType  =  qualifiedBaseType . Generator . Reader . GetTypeDefinition ( qualifiedBaseType . DefinitionHandle ) ; 
34493474            allMethods . AddRange ( baseType . GetMethods ( ) . Select ( m =>  new  QualifiedMethodDefinitionHandle ( qualifiedBaseType . Generator ,  m ) ) ) ; 
34503475        } 
@@ -3570,15 +3595,17 @@ private TypeDeclarationSyntax DeclareInterfaceAsStruct(TypeDefinitionHandle type
35703595        return  iface ; 
35713596    } 
35723597
3573-     private  TypeDeclarationSyntax ?  DeclareInterfaceAsInterface ( TypeDefinition  typeDef ,  Stack < QualifiedTypeDefinitionHandle >  baseTypes ) 
3598+     private  TypeDeclarationSyntax ?  DeclareInterfaceAsInterface ( TypeDefinition  typeDef ,  ImmutableStack < QualifiedTypeDefinitionHandle >  baseTypes ,   Context   context ,   bool   interfaceAsSubtype   =   false ) 
35743599    { 
35753600        if  ( this . Reader . StringComparer . Equals ( typeDef . Name ,  "IUnknown" )  ||  this . Reader . StringComparer . Equals ( typeDef . Name ,  "IDispatch" ) ) 
35763601        { 
35773602            // We do not generate interfaces for these COM base types. 
35783603            return  null ; 
35793604        } 
35803605
3581-         IdentifierNameSyntax  ifaceName  =  IdentifierName ( this . Reader . GetString ( typeDef . Name ) ) ; 
3606+         IdentifierNameSyntax  ifaceName  =  interfaceAsSubtype 
3607+             ?  NestedCOMInterfaceName 
3608+             :  IdentifierName ( this . Reader . GetString ( typeDef . Name ) ) ; 
35823609        TypeSyntaxSettings  typeSettings  =  this . comSignatureTypeSettings ; 
35833610
35843611        // It is imperative that we generate methods for all base interfaces as well, ahead of any implemented by *this* interface. 
@@ -3587,9 +3614,10 @@ private TypeDeclarationSyntax DeclareInterfaceAsStruct(TypeDefinitionHandle type
35873614        bool  foundIDispatch  =  false ; 
35883615        bool  foundIInspectable  =  false ; 
35893616        var  baseTypeSyntaxList  =  new  List < BaseTypeSyntax > ( ) ; 
3590-         while  ( baseTypes . Count   >   0 ) 
3617+         while  ( ! baseTypes . IsEmpty ) 
35913618        { 
3592-             QualifiedTypeDefinitionHandle  baseTypeHandle  =  baseTypes . Pop ( ) ; 
3619+             QualifiedTypeDefinitionHandle  baseTypeHandle  =  baseTypes . Peek ( ) ; 
3620+             baseTypes  =  baseTypes . Pop ( ) ; 
35933621            TypeDefinition  baseType  =  baseTypeHandle . Reader . GetTypeDefinition ( baseTypeHandle . DefinitionHandle ) ; 
35943622            if  ( ! foundIUnknown ) 
35953623            { 
@@ -3612,8 +3640,16 @@ private TypeDeclarationSyntax DeclareInterfaceAsStruct(TypeDefinitionHandle type
36123640                } 
36133641                else 
36143642                { 
3615-                     baseTypeHandle . Generator . RequestInteropType ( baseTypeHandle . DefinitionHandle ,  this . DefaultContext ) ; 
3616-                     baseTypeSyntaxList . Add ( SimpleBaseType ( new  HandleTypeHandleInfo ( baseTypeHandle . Reader ,  baseTypeHandle . DefinitionHandle ) . ToTypeSyntax ( this . comSignatureTypeSettings ,  null ) . Type ) ) ; 
3643+                     baseTypeHandle . Generator . RequestInteropType ( baseTypeHandle . DefinitionHandle ,  context ) ; 
3644+                     TypeSyntax  baseTypeSyntax  =  new  HandleTypeHandleInfo ( baseTypeHandle . Reader ,  baseTypeHandle . DefinitionHandle ) . ToTypeSyntax ( this . comSignatureTypeSettings ,  null ) . Type ; 
3645+                     if  ( interfaceAsSubtype ) 
3646+                     { 
3647+                         baseTypeSyntax  =  QualifiedName ( 
3648+                             baseTypeSyntax  is  PointerTypeSyntax  baseTypePtr  ?  ( NameSyntax ) baseTypePtr . ElementType  :  ( NameSyntax ) baseTypeSyntax , 
3649+                             NestedCOMInterfaceName ) ; 
3650+                     } 
3651+ 
3652+                     baseTypeSyntaxList . Add ( SimpleBaseType ( baseTypeSyntax ) ) ; 
36173653                    allMethods . AddRange ( baseType . GetMethods ( ) ) ; 
36183654                } 
36193655            } 
@@ -3645,7 +3681,8 @@ private TypeDeclarationSyntax DeclareInterfaceAsStruct(TypeDefinitionHandle type
36453681                TypeSyntax  returnType  =  returnTypeDetails . Type ; 
36463682                AttributeSyntax ?  returnsAttribute  =  MarshalAs ( returnTypeDetails . MarshalAsAttribute ,  returnTypeDetails . NativeArrayInfo ) ; 
36473683
3648-                 bool  preserveSig  =  returnType  is  not QualifiedNameSyntax  {  Right :  {  Identifier :  {  ValueText :  "HRESULT"  }  }  } 
3684+                 bool  preserveSig  =  interfaceAsSubtype 
3685+                     ||  returnType  is  not QualifiedNameSyntax  {  Right :  {  Identifier :  {  ValueText :  "HRESULT"  }  }  } 
36493686                    ||  ( methodDefinition . ImplAttributes  &  MethodImplAttributes . PreserveSig )  ==  MethodImplAttributes . PreserveSig 
36503687                    ||  this . options . ComInterop . PreserveSigMethods . Contains ( $ "{ ifaceName } .{ methodName } ") 
36513688                    ||  this . options . ComInterop . PreserveSigMethods . Contains ( ifaceName . ToString ( ) ) ; 
@@ -3697,7 +3734,7 @@ private TypeDeclarationSyntax DeclareInterfaceAsStruct(TypeDefinitionHandle type
36973734                methodDeclaration  =  this . AddApiDocumentation ( $ "{ ifaceName } .{ methodName } ",  methodDeclaration ) ; 
36983735                members . Add ( methodDeclaration ) ; 
36993736
3700-                 NameSyntax  declaringTypeName  =  HandleTypeHandleInfo . GetNestingQualifiedName ( this ,  this . Reader ,  typeDef ,  hasUnmanagedSuffix :  false ) ; 
3737+                 NameSyntax  declaringTypeName  =  HandleTypeHandleInfo . GetNestingQualifiedName ( this ,  this . Reader ,  typeDef ,  hasUnmanagedSuffix :  false ,   isInterfaceNestedInStruct :   interfaceAsSubtype ) ; 
37013738                friendlyOverloads . AddRange ( 
37023739                    this . DeclareFriendlyOverloads ( methodDefinition ,  methodDeclaration ,  declaringTypeName ,  FriendlyOverloadOf . InterfaceMethod ,  this . injectedPInvokeHelperMethodsToFriendlyOverloadsExtensions ) ) ; 
37033740            } 
0 commit comments