@@ -117,20 +117,13 @@ public bool EmbeddedPortablePdbHasLocalSource(string module, out string firstNot
117117 using ( MetadataReaderProvider embeddedMetadataProvider = peReader . ReadEmbeddedPortablePdbDebugDirectoryData ( entry ) )
118118 {
119119 MetadataReader metadataReader = embeddedMetadataProvider . GetMetadataReader ( ) ;
120- foreach ( DocumentHandle docHandle in metadataReader . Documents )
120+
121+ var matchingResult = MatchDocumentsWithSources ( metadataReader ) ;
122+
123+ if ( ! matchingResult . allDocumentsMatch )
121124 {
122- Document document = metadataReader . GetDocument ( docHandle ) ;
123- string docName = _sourceRootTranslator . ResolveFilePath ( metadataReader . GetString ( document . Name ) ) ;
124-
125- // We verify all docs and return false if not all are present in local
126- // We could have false negative if doc is not a source
127- // Btw check for all possible extension could be weak approach
128- // We exlude from the check the autogenerated source file(i.e. source generators)
129- if ( ! _fileSystem . Exists ( docName ) && ! docName . EndsWith ( ".g.cs" ) )
130- {
131- firstNotFoundDocument = docName ;
132- return false ;
133- }
125+ firstNotFoundDocument = matchingResult . notFoundDocument ;
126+ return false ;
134127 }
135128 }
136129 }
@@ -165,20 +158,13 @@ public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDoc
165158 _logger . LogWarning ( $ "{ nameof ( BadImageFormatException ) } during MetadataReaderProvider.FromPortablePdbStream in InstrumentationHelper.PortablePdbHasLocalSource, unable to check if module has got local source.") ;
166159 return true ;
167160 }
168- foreach ( DocumentHandle docHandle in metadataReader . Documents )
161+
162+ var matchingResult = MatchDocumentsWithSources ( metadataReader ) ;
163+
164+ if ( ! matchingResult . allDocumentsMatch )
169165 {
170- Document document = metadataReader . GetDocument ( docHandle ) ;
171- string docName = _sourceRootTranslator . ResolveFilePath ( metadataReader . GetString ( document . Name ) ) ;
172-
173- // We verify all docs and return false if not all are present in local
174- // We could have false negative if doc is not a source
175- // Btw check for all possible extension could be weak approach
176- // We exlude from the check the autogenerated source file(i.e. source generators)
177- if ( ! _fileSystem . Exists ( docName ) && ! docName . EndsWith ( ".g.cs" ) )
178- {
179- firstNotFoundDocument = docName ;
180- return false ;
181- }
166+ firstNotFoundDocument = matchingResult . notFoundDocument ;
167+ return false ;
182168 }
183169 }
184170 }
@@ -187,6 +173,27 @@ public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDoc
187173 return true ;
188174 }
189175
176+ private ( bool allDocumentsMatch , string notFoundDocument ) MatchDocumentsWithSources ( MetadataReader metadataReader )
177+ {
178+ foreach ( DocumentHandle docHandle in metadataReader . Documents )
179+ {
180+ Document document = metadataReader . GetDocument ( docHandle ) ;
181+ string docName = _sourceRootTranslator . ResolveFilePath ( metadataReader . GetString ( document . Name ) ) ;
182+ Guid languageGuid = metadataReader . GetGuid ( document . Language ) ;
183+ // We verify all docs and return false if not all are present in local
184+ // We could have false negative if doc is not a source
185+ // Btw check for all possible extension could be weak approach
186+ // We exlude from the check the autogenerated source file(i.e. source generators)
187+ // We exclude special F# construct https://github.com/coverlet-coverage/coverlet/issues/1145
188+ if ( ! _fileSystem . Exists ( docName ) && ! docName . EndsWith ( ".g.cs" ) &&
189+ ! IsUnknownModuleInFSharpAssembly ( languageGuid , docName ) )
190+ {
191+ return ( false , docName ) ;
192+ }
193+ }
194+ return ( true , string . Empty ) ;
195+ }
196+
190197 public void BackupOriginalModule ( string module , string identifier )
191198 {
192199 var backupPath = GetBackupPath ( module , identifier ) ;
@@ -443,5 +450,12 @@ private bool IsAssembly(string filePath)
443450 return false ;
444451 }
445452 }
453+
454+ private bool IsUnknownModuleInFSharpAssembly ( Guid languageGuid , string docName )
455+ {
456+ // https://github.com/dotnet/runtime/blob/main/docs/design/specs/PortablePdb-Metadata.md#document-table-0x30
457+ return languageGuid . Equals ( new Guid ( "ab4f38c9-b6e6-43ba-be3b-58080b2ccce3" ) )
458+ && docName . EndsWith ( "unknown" ) ;
459+ }
446460 }
447461}
0 commit comments