diff --git a/src/Compilers/CSharp/Test/Emit/PDB/CheckSumTest.cs b/src/Compilers/CSharp/Test/Emit/PDB/CheckSumTest.cs
index b6fc2670df011..7afd473af8a6e 100644
--- a/src/Compilers/CSharp/Test/Emit/PDB/CheckSumTest.cs
+++ b/src/Compilers/CSharp/Test/Emit/PDB/CheckSumTest.cs
@@ -232,6 +232,7 @@ static void Main()
+
@@ -286,7 +287,7 @@ void M()
");
}
- [Fact]
+ [ConditionalFact(typeof(WindowsOnly))]
public void NoResolver()
{
var comp = CSharpCompilation.Create(
@@ -305,6 +306,7 @@ class C { void M() { } }
+
diff --git a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs
index 1c9e77910f56c..057305e027ace 100644
--- a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs
@@ -10511,6 +10511,7 @@ public async void M1()
@"
+
@@ -10577,6 +10578,7 @@ partial class C
+
@@ -11037,5 +11039,76 @@ public void InvalidCharacterInPdbPath()
Diagnostic(ErrorCode.FTL_InvalidInputFileName).WithArguments("test\\?.pdb").WithLocation(1, 1));
}
}
+
+ [Fact]
+ [WorkItem(38954, "https://github.com/dotnet/roslyn/issues/38954")]
+ public void FilesOneWithNoMethodBody()
+ {
+ string source1 = WithWindowsLineBreaks(@"
+using System;
+
+class C
+{
+ public static void Main()
+ {
+ Console.WriteLine();
+ }
+}
+");
+ string source2 = WithWindowsLineBreaks(@"
+// no code
+");
+
+ var tree1 = Parse(source1, "f:/build/goo.cs");
+ var tree2 = Parse(source2, "f:/build/nocode.cs");
+ var c = CreateCompilation(new[] { tree1, tree2 }, options: TestOptions.DebugDll);
+
+ c.VerifyPdb(@"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+");
+ }
+
+ [Fact]
+ [WorkItem(38954, "https://github.com/dotnet/roslyn/issues/38954")]
+ public void SingleFileWithNoMethodBody()
+ {
+ string source = WithWindowsLineBreaks(@"
+// no code
+");
+
+ var tree = Parse(source, "f:/build/nocode.cs");
+ var c = CreateCompilation(new[] { tree }, options: TestOptions.DebugDll);
+
+ c.VerifyPdb(@"
+
+
+
+
+
+
+");
+ }
}
}
diff --git a/src/Compilers/Core/Portable/Compilation/Compilation.cs b/src/Compilers/Core/Portable/Compilation/Compilation.cs
index 6e49054c93979..04e878455375d 100644
--- a/src/Compilers/Core/Portable/Compilation/Compilation.cs
+++ b/src/Compilers/Core/Portable/Compilation/Compilation.cs
@@ -2068,8 +2068,6 @@ internal bool CreateDebugDocuments(DebugDocumentsBuilder documentsBuilder, IEnum
// takes priority over the syntax tree pass, which will not embed.
if (!embeddedTexts.IsEmpty())
{
- var embeddedDocuments = ArrayBuilder.GetInstance();
-
foreach (var text in embeddedTexts)
{
Debug.Assert(!string.IsNullOrEmpty(text.FilePath));
@@ -2083,11 +2081,8 @@ internal bool CreateDebugDocuments(DebugDocumentsBuilder documentsBuilder, IEnum
() => text.GetDebugSourceInfo());
documentsBuilder.AddDebugDocument(document);
- embeddedDocuments.Add(document);
}
}
-
- documentsBuilder.EmbeddedDocuments = embeddedDocuments.ToImmutableAndFree();
}
// Add debug documents for all trees with distinct paths.
diff --git a/src/Compilers/Core/Portable/Emit/DebugDocumentsBuilder.cs b/src/Compilers/Core/Portable/Emit/DebugDocumentsBuilder.cs
index 96d42c1181cde..70b5bee1bc1f9 100644
--- a/src/Compilers/Core/Portable/Emit/DebugDocumentsBuilder.cs
+++ b/src/Compilers/Core/Portable/Emit/DebugDocumentsBuilder.cs
@@ -3,8 +3,7 @@
using Roslyn.Utilities;
using System;
using System.Collections.Concurrent;
-using System.Collections.Immutable;
-using System.Diagnostics;
+using System.Collections.Generic;
namespace Microsoft.CodeAnalysis.Emit
{
@@ -19,7 +18,6 @@ internal sealed class DebugDocumentsBuilder
private readonly ConcurrentDictionary _debugDocuments;
private readonly ConcurrentCache<(string, string), string> _normalizedPathsCache;
private readonly SourceReferenceResolver _resolverOpt;
- private ImmutableArray _embeddedDocuments;
public DebugDocumentsBuilder(SourceReferenceResolver resolverOpt, bool isDocumentNameCaseSensitive)
{
@@ -31,13 +29,6 @@ public DebugDocumentsBuilder(SourceReferenceResolver resolverOpt, bool isDocumen
StringComparer.OrdinalIgnoreCase);
_normalizedPathsCache = new ConcurrentCache<(string, string), string>(16);
- _embeddedDocuments = ImmutableArray.Empty;
- }
-
- internal ImmutableArray EmbeddedDocuments
- {
- get { return _embeddedDocuments; }
- set { Debug.Assert(value != null); _embeddedDocuments = value; }
}
internal int DebugDocumentCount => _debugDocuments.Count;
@@ -47,6 +38,9 @@ internal void AddDebugDocument(Cci.DebugSourceDocument document)
_debugDocuments.Add(document.Location, document);
}
+ internal IReadOnlyDictionary DebugDocuments
+ => _debugDocuments;
+
internal Cci.DebugSourceDocument TryGetDebugDocument(string path, string basePath)
{
return TryGetDebugDocumentForNormalizedPath(NormalizeDebugDocumentPath(path, basePath));
diff --git a/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs b/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs
index abd0a16ff0623..b316c2e506fa2 100644
--- a/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs
+++ b/src/Compilers/Core/Portable/NativePdbWriter/PdbWriter.cs
@@ -5,11 +5,10 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
+using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using System.Runtime.InteropServices;
using System.Security.Cryptography;
-using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.PooledObjects;
@@ -572,6 +571,11 @@ private int GetDocumentIndex(DebugSourceDocument document)
return documentIndex;
}
+ return AddDocumentIndex(document);
+ }
+
+ private int AddDocumentIndex(DebugSourceDocument document)
+ {
Guid algorithmId;
ReadOnlySpan checksum;
ReadOnlySpan embeddedSource;
@@ -597,7 +601,7 @@ private int GetDocumentIndex(DebugSourceDocument document)
embeddedSource = null;
}
- documentIndex = _symWriter.DefineDocument(
+ int documentIndex = _symWriter.DefineDocument(
document.Location,
document.Language,
document.LanguageVendor,
@@ -742,18 +746,19 @@ public void EmbedSourceLink(Stream stream)
}
///
- /// Write document entries for any embedded text document that does not yet have an entry.
+ /// Write document entries for all debug documents that do not yet have an entry.
///
///
/// This is done after serializing method debug info to ensure that we embed all requested
/// text even if there are no corresponding sequence points.
///
- public void WriteRemainingEmbeddedDocuments(IEnumerable embeddedDocuments)
+ public void WriteRemainingDebugDocuments(IReadOnlyDictionary documents)
{
- foreach (var document in embeddedDocuments)
+ foreach (var kvp in documents
+ .Where(kvp => !_documentIndex.ContainsKey(kvp.Value))
+ .OrderBy(kvp => kvp.Key))
{
- Debug.Assert(!document.GetSourceInfo().EmbeddedTextBlob.IsDefault);
- GetDocumentIndex(document);
+ AddDocumentIndex(kvp.Value);
}
}
}
diff --git a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.PortablePdb.cs b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.PortablePdb.cs
index c24f59a87e41e..bb52611ff267b 100644
--- a/src/Compilers/Core/Portable/PEWriter/MetadataWriter.PortablePdb.cs
+++ b/src/Compilers/Core/Portable/PEWriter/MetadataWriter.PortablePdb.cs
@@ -727,44 +727,52 @@ private void SerializeDeltaLinesAndColumns(BlobBuilder writer, SequencePoint seq
private DocumentHandle GetOrAddDocument(DebugSourceDocument document, Dictionary index)
{
- DocumentHandle documentHandle;
- if (!index.TryGetValue(document, out documentHandle))
+ if (index.TryGetValue(document, out var documentHandle))
{
- DebugSourceInfo info = document.GetSourceInfo();
+ return documentHandle;
+ }
- documentHandle = _debugMetadataOpt.AddDocument(
- name: _debugMetadataOpt.GetOrAddDocumentName(document.Location),
- hashAlgorithm: info.Checksum.IsDefault ? default(GuidHandle) : _debugMetadataOpt.GetOrAddGuid(info.ChecksumAlgorithmId),
- hash: info.Checksum.IsDefault ? default(BlobHandle) : _debugMetadataOpt.GetOrAddBlob(info.Checksum),
- language: _debugMetadataOpt.GetOrAddGuid(document.Language));
+ return AddDocument(document, index);
+ }
- index.Add(document, documentHandle);
+ private DocumentHandle AddDocument(DebugSourceDocument document, Dictionary index)
+ {
+ DocumentHandle documentHandle;
+ DebugSourceInfo info = document.GetSourceInfo();
- if (info.EmbeddedTextBlob != null)
- {
- _debugMetadataOpt.AddCustomDebugInformation(
- parent: documentHandle,
- kind: _debugMetadataOpt.GetOrAddGuid(PortableCustomDebugInfoKinds.EmbeddedSource),
- value: _debugMetadataOpt.GetOrAddBlob(info.EmbeddedTextBlob));
- }
+ documentHandle = _debugMetadataOpt.AddDocument(
+ name: _debugMetadataOpt.GetOrAddDocumentName(document.Location),
+ hashAlgorithm: info.Checksum.IsDefault ? default(GuidHandle) : _debugMetadataOpt.GetOrAddGuid(info.ChecksumAlgorithmId),
+ hash: info.Checksum.IsDefault ? default(BlobHandle) : _debugMetadataOpt.GetOrAddBlob(info.Checksum),
+ language: _debugMetadataOpt.GetOrAddGuid(document.Language));
+
+ index.Add(document, documentHandle);
+
+ if (info.EmbeddedTextBlob != null)
+ {
+ _debugMetadataOpt.AddCustomDebugInformation(
+ parent: documentHandle,
+ kind: _debugMetadataOpt.GetOrAddGuid(PortableCustomDebugInfoKinds.EmbeddedSource),
+ value: _debugMetadataOpt.GetOrAddBlob(info.EmbeddedTextBlob));
}
return documentHandle;
}
///
- /// Add document entries for any embedded text document that does not yet have an entry.
+ /// Add document entries for all debug documents that do not yet have an entry.
///
///
/// This is done after serializing method debug info to ensure that we embed all requested
/// text even if there are no corresponding sequence points.
///
- public void AddRemainingEmbeddedDocuments(IEnumerable documents)
+ public void AddRemainingDebugDocuments(IReadOnlyDictionary documents)
{
- foreach (var document in documents)
+ foreach (var kvp in documents
+ .Where(kvp => !_documentIndex.ContainsKey(kvp.Value))
+ .OrderBy(kvp => kvp.Key))
{
- Debug.Assert(document.GetSourceInfo().EmbeddedTextBlob != null);
- GetOrAddDocument(document, _documentIndex);
+ AddDocument(kvp.Value, _documentIndex);
}
}
diff --git a/src/Compilers/Core/Portable/PEWriter/PeWriter.cs b/src/Compilers/Core/Portable/PEWriter/PeWriter.cs
index 225bb1439835d..7d47c15c803f0 100644
--- a/src/Compilers/Core/Portable/PEWriter/PeWriter.cs
+++ b/src/Compilers/Core/Portable/PEWriter/PeWriter.cs
@@ -103,7 +103,7 @@ internal static bool WritePeToStream(
#endif
}
- nativePdbWriterOpt.WriteRemainingEmbeddedDocuments(mdWriter.Module.DebugDocumentsBuilder.EmbeddedDocuments);
+ nativePdbWriterOpt.WriteRemainingDebugDocuments(mdWriter.Module.DebugDocumentsBuilder.DebugDocuments);
}
Stream peStream = getPeStream();
@@ -151,7 +151,7 @@ internal static bool WritePeToStream(
BlobBuilder portablePdbToEmbed = null;
if (mdWriter.EmitPortableDebugMetadata)
{
- mdWriter.AddRemainingEmbeddedDocuments(mdWriter.Module.DebugDocumentsBuilder.EmbeddedDocuments);
+ mdWriter.AddRemainingDebugDocuments(mdWriter.Module.DebugDocumentsBuilder.DebugDocuments);
// The algorithm must be specified for deterministic builds (checked earlier).
Debug.Assert(!isDeterministic || context.Module.PdbChecksumAlgorithm.Name != null);
diff --git a/src/Compilers/VisualBasic/Test/Emit/PDB/ChecksumTests.vb b/src/Compilers/VisualBasic/Test/Emit/PDB/ChecksumTests.vb
index aae0339291564..6ad4992c88f1a 100644
--- a/src/Compilers/VisualBasic/Test/Emit/PDB/ChecksumTests.vb
+++ b/src/Compilers/VisualBasic/Test/Emit/PDB/ChecksumTests.vb
@@ -248,6 +248,7 @@ End Class
+
@@ -312,6 +313,7 @@ End Class
+
@@ -363,6 +365,7 @@ End Class
+
diff --git a/src/Compilers/VisualBasic/Test/Emit/PDB/PDBExternalSourceDirectiveTests.vb b/src/Compilers/VisualBasic/Test/Emit/PDB/PDBExternalSourceDirectiveTests.vb
index 21dfb7a05ff10..3b42eea4ddf97 100644
--- a/src/Compilers/VisualBasic/Test/Emit/PDB/PDBExternalSourceDirectiveTests.vb
+++ b/src/Compilers/VisualBasic/Test/Emit/PDB/PDBExternalSourceDirectiveTests.vb
@@ -46,6 +46,7 @@ End Class
+
@@ -120,6 +121,7 @@ End Class
+
@@ -359,6 +361,9 @@ End Class
' Care about the fact that there are no sequence points or referenced files
compilation.VerifyPdb(
+
+
+
@@ -418,6 +423,9 @@ End Class
' Care about the fact that no files are referenced
compilation.VerifyPdb(
+
+
+
@@ -503,6 +511,9 @@ End Class
+
+
+
@@ -704,6 +715,7 @@ End Module
+
@@ -757,6 +769,7 @@ End Class
+
diff --git a/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb b/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb
index 93cc3be4d0658..63cbb709ed30e 100644
--- a/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb
+++ b/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb
@@ -4614,5 +4614,70 @@ End Class"
result.Diagnostics.Verify(Diagnostic(ERRID.FTL_InvalidInputFileName).WithArguments("test\\?.pdb").WithLocation(1, 1))
End Using
End Sub
+
+
+
+ Public Sub FilesOneWithNoMethodBody()
+ Dim source1 =
+"Imports System
+
+Class C
+ Public Shared Sub Main()
+ Console.WriteLine()
+ End Sub
+End Class
+"
+ Dim source2 =
+"
+' no code
+"
+
+ Dim tree1 = Parse(source1, "f:/build/goo.vb")
+ Dim tree2 = Parse(source2, "f:/build/nocode.vb")
+ Dim c = CreateCompilation({tree1, tree2}, options:=TestOptions.DebugDll)
+
+ c.VerifyPdb("
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+")
+ End Sub
+
+
+
+ Public Sub SingleFileWithNoMethodBody()
+ Dim source =
+"
+' no code
+"
+
+ Dim tree = Parse(source, "f:/build/nocode.vb")
+ Dim c = CreateCompilation({tree}, options:=TestOptions.DebugDll)
+
+ c.VerifyPdb("
+
+
+
+
+
+
+")
+ End Sub
End Class
End Namespace
diff --git a/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs b/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs
index c4220f77c9179..e0c2984de4af1 100644
--- a/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs
+++ b/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs
@@ -972,7 +972,7 @@ public async Task BreakMode_RudeEdits_DocumentOutOfSync()
}, _telemetryLog);
}
- [Fact]
+ [Fact(Skip = "https://github.com/dotnet/roslyn/issues/39271")]
public async Task BreakMode_RudeEdits_DocumentWithoutSequencePoints()
{
var source1 = "abstract class C { public abstract void M(); }";