@@ -130,10 +130,22 @@ public class SourceGenerator : ISourceGenerator
130130 "Configuration" ,
131131 DiagnosticSeverity . Warning ,
132132 isEnabledByDefault : true ) ;
133+
134+ public static readonly DiagnosticDescriptor NonUniqueMetadataInputs = new (
135+ InputProjectionErrorId ,
136+ InputProjectionErrorTitle ,
137+ "The metadata projections input into CsWin32 must have unique names. The name \" {0}\" is used more than once." ,
138+ "Configuration" ,
139+ DiagnosticSeverity . Error ,
140+ isEnabledByDefault : true ) ;
133141#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
134142
143+ private const string InputProjectionErrorId = "PInvoke010" ;
144+ private const string InputProjectionErrorTitle = "Input projection error" ;
145+
135146 private const string NativeMethodsTxtAdditionalFileName = "NativeMethods.txt" ;
136147 private const string NativeMethodsJsonAdditionalFileName = "NativeMethods.json" ;
148+
137149 private static readonly char [ ] ZeroWhiteSpace = new char [ ]
138150 {
139151 '\uFEFF ' , // ZERO WIDTH NO-BREAK SPACE (U+FEFF)
@@ -199,7 +211,14 @@ public void Execute(GeneratorExecutionContext context)
199211 }
200212
201213 Docs ? docs = ParseDocs ( context ) ;
202- SuperGenerator superGenerator = SuperGenerator . Combine ( CollectMetadataPaths ( context ) . Select ( path => new Generator ( path , docs , options , compilation , parseOptions ) ) ) ;
214+ Generator [ ] generators = CollectMetadataPaths ( context ) . Select ( path => new Generator ( path , docs , options , compilation , parseOptions ) ) . ToArray ( ) ;
215+ if ( TryFindNonUniqueValue ( generators , g => g . InputAssemblyName , StringComparer . OrdinalIgnoreCase , out ( Generator Item , string Value ) nonUniqueGenerator ) )
216+ {
217+ context . ReportDiagnostic ( Diagnostic . Create ( NonUniqueMetadataInputs , null , nonUniqueGenerator . Value ) ) ;
218+ return ;
219+ }
220+
221+ SuperGenerator superGenerator = SuperGenerator . Combine ( generators ) ;
203222 try
204223 {
205224 foreach ( AdditionalText nativeMethodsTxtFile in nativeMethodsTxtFiles )
@@ -346,6 +365,23 @@ private static string AssembleFullExceptionMessage(Exception ex)
346365 return sb . ToString ( ) ;
347366 }
348367
368+ private static bool TryFindNonUniqueValue < T , TValue > ( IEnumerable < T > sequence , Func < T , TValue > valueSelector , IEqualityComparer < TValue > comparer , out ( T Item , TValue Value ) nonUniqueValue )
369+ {
370+ HashSet < TValue > seenValues = new ( comparer ) ;
371+ nonUniqueValue = default ;
372+ foreach ( T item in sequence )
373+ {
374+ TValue value = valueSelector ( item ) ;
375+ if ( ! seenValues . Add ( value ) )
376+ {
377+ nonUniqueValue = ( item , value ) ;
378+ return true ;
379+ }
380+ }
381+
382+ return false ;
383+ }
384+
349385 private static IReadOnlyList < string > CollectMetadataPaths ( GeneratorExecutionContext context )
350386 {
351387 if ( ! context . AnalyzerConfigOptions . GlobalOptions . TryGetValue ( "build_property.CsWin32InputMetadataPaths" , out string ? delimitedMetadataBasePaths ) ||
0 commit comments