@@ -1303,21 +1303,38 @@ Symbol GetType(string type, bool isGeneric = false, int genericIndex = -1, bool
13031303
13041304 private IEnumerable < INamedTypeSymbol > GetInterfaces ( INamedTypeSymbol symbol , bool includeInterfacesWithoutMappings = false )
13051305 {
1306- HashSet < INamedTypeSymbol > interfaces = new HashSet < INamedTypeSymbol > ( ) ;
1307- foreach ( var @interface in symbol . Interfaces )
1306+ HashSet < INamedTypeSymbol > interfaces = new ( ) ;
1307+
1308+ // Gather all interfaces that are publicly accessible. We specifically need to exclude interfaces
1309+ // that are not public, as eg. those might be used for additional cloaked WinRT/COM interfaces.
1310+ // Ignoring them here makes sure that they're not processed to be part of the .winmd file.
1311+ void GatherPubliclyAccessibleInterfaces ( ITypeSymbol symbol )
13081312 {
1309- interfaces . Add ( @interface ) ;
1310- interfaces . UnionWith ( @interface . AllInterfaces ) ;
1313+ foreach ( var @interface in symbol . Interfaces )
1314+ {
1315+ if ( @interface . IsPubliclyAccessible ( ) )
1316+ {
1317+ _ = interfaces . Add ( @interface ) ;
1318+ }
1319+
1320+ // We're not using AllInterfaces on purpose: we only want to gather all interfaces but not
1321+ // from the base type. That's handled below to skip types that are already WinRT projections.
1322+ foreach ( var @interface2 in @interface . AllInterfaces )
1323+ {
1324+ if ( @interface2 . IsPubliclyAccessible ( ) )
1325+ {
1326+ _ = interfaces . Add ( @interface2 ) ;
1327+ }
1328+ }
1329+ }
13111330 }
13121331
1332+ GatherPubliclyAccessibleInterfaces ( symbol ) ;
1333+
13131334 var baseType = symbol . BaseType ;
13141335 while ( baseType != null && ! IsWinRTType ( baseType ) )
13151336 {
1316- interfaces . UnionWith ( baseType . Interfaces ) ;
1317- foreach ( var @interface in baseType . Interfaces )
1318- {
1319- interfaces . UnionWith ( @interface . AllInterfaces ) ;
1320- }
1337+ GatherPubliclyAccessibleInterfaces ( baseType ) ;
13211338
13221339 baseType = baseType . BaseType ;
13231340 }
@@ -2010,6 +2027,13 @@ void AddComponentType(INamedTypeSymbol type, Action visitTypeDeclaration = null)
20102027 }
20112028 else
20122029 {
2030+ // Special case: skip members that are explicitly implementing internal interfaces.
2031+ // This allows implementing classic COM internal interfaces with non-WinRT signatures.
2032+ if ( member . IsExplicitInterfaceImplementationOfInternalInterfaces ( ) )
2033+ {
2034+ continue ;
2035+ }
2036+
20132037 if ( member is IMethodSymbol method &&
20142038 ( method . MethodKind == MethodKind . Ordinary ||
20152039 method . MethodKind == MethodKind . ExplicitInterfaceImplementation ||
@@ -2736,12 +2760,19 @@ public void FinalizeGeneration()
27362760 }
27372761 }
27382762
2739- public bool IsPublic ( ISymbol type )
2763+ public bool IsPublic ( ISymbol symbol )
27402764 {
2741- return type . DeclaredAccessibility == Accessibility . Public ||
2742- type is IMethodSymbol method && ! method . ExplicitInterfaceImplementations . IsDefaultOrEmpty ||
2743- type is IPropertySymbol property && ! property . ExplicitInterfaceImplementations . IsDefaultOrEmpty ||
2744- type is IEventSymbol @event && ! @event . ExplicitInterfaceImplementations . IsDefaultOrEmpty ;
2765+ // Check that the type has either public accessibility, or is an explicit interface implementation
2766+ if ( symbol . DeclaredAccessibility == Accessibility . Public ||
2767+ symbol is IMethodSymbol method && ! method . ExplicitInterfaceImplementations . IsDefaultOrEmpty ||
2768+ symbol is IPropertySymbol property && ! property . ExplicitInterfaceImplementations . IsDefaultOrEmpty ||
2769+ symbol is IEventSymbol @event && ! @event . ExplicitInterfaceImplementations . IsDefaultOrEmpty )
2770+ {
2771+ // If we have a containing type, we also check that it's publicly accessible
2772+ return symbol . ContainingType is not { } containingType || containingType . IsPubliclyAccessible ( ) ;
2773+ }
2774+
2775+ return false ;
27452776 }
27462777
27472778 public void GetNamespaceAndTypename ( string qualifiedName , out string @namespace , out string typename )
0 commit comments