diff --git a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs index 075a00c5bfea622974bd92930c3ced812d0b5245..d7f9b63e09b9e9da92523f50454ea82ca4ccb3c5 100644 --- a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs +++ b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs @@ -526,6 +526,130 @@ public void CustomDebugEntryPoint_Errors() Diagnostic(ErrorCode.ERR_DebugEntryPointNotSourceMethodDefinition)); } + [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] + [WorkItem(768862, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/768862")] + public void TestLargeLineDelta() + { + var verbatim = string.Join("\r\n", Enumerable.Repeat("x", 1000)); + + var source = $@" +class C {{ public static void Main() => System.Console.WriteLine(@""{verbatim}""); }} +"; + var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); + c.VerifyPdb("C.Main", @" + + + + + + + + + + + + + + + + + +", format: DebugInformationFormat.PortablePdb); + + // Native PDBs only support spans with line delta <= 127 (7 bit) + // https://github.com/Microsoft/microsoft-pdb/blob/master/include/cvinfo.h#L4621 + c.VerifyPdb("C.Main", @" + + + + + + + + + + + + + + + + + +", format: DebugInformationFormat.Pdb); + } + + [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] + [WorkItem(20118, "https://github.com/dotnet/roslyn/issues/20118")] + public void TestLargeStartAndEndColumn_SameLine() + { + var spaces = new string(' ', 0x10000); + + var source = $@" +class C +{{ + public static void Main() => + {spaces}System.Console.WriteLine(""{spaces}""); +}} +"; + var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); + c.VerifyPdb("C.Main", @" + + + + + + + + + + + + + + + + + +"); + } + + [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] + [WorkItem(20118, "https://github.com/dotnet/roslyn/issues/20118")] + public void TestLargeStartAndEndColumn_DifferentLine() + { + var spaces = new string(' ', 0x10000); + + var source = $@" +class C +{{ + public static void Main() => + {spaces}System.Console.WriteLine( + ""{spaces}""); +}} +"; + var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.DebugDll); + c.VerifyPdb("C.Main", @" + + + + + + + + + + + + + + + + + +"); + } + #endregion #region Method Bodies diff --git a/src/Compilers/Core/Portable/CodeGen/RawSequencePoint.cs b/src/Compilers/Core/Portable/CodeGen/RawSequencePoint.cs index e3aaa789f7f03d8d701c9c9d84ee32e06663c9f1..9a34a653a47195b5017122edba951082f48395fd 100644 --- a/src/Compilers/Core/Portable/CodeGen/RawSequencePoint.cs +++ b/src/Compilers/Core/Portable/CodeGen/RawSequencePoint.cs @@ -9,7 +9,7 @@ namespace Microsoft.CodeAnalysis.CodeGen /// Represents a sequence point before translation by #line/ExternalSource directives. /// [DebuggerDisplay("{GetDebuggerDisplay(),nq}")] - internal struct RawSequencePoint + internal readonly struct RawSequencePoint { internal readonly SyntaxTree SyntaxTree; internal readonly int ILMarker; diff --git a/src/Compilers/Core/Portable/CodeGen/SequencePointList.cs b/src/Compilers/Core/Portable/CodeGen/SequencePointList.cs index da5dc27fb631e0695e0c26bdcee421bcbd38b8b0..a0189f3b9aea8d16e117f902f1c2ec8c2db2aa4e 100644 --- a/src/Compilers/Core/Portable/CodeGen/SequencePointList.cs +++ b/src/Compilers/Core/Portable/CodeGen/SequencePointList.cs @@ -1,15 +1,9 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; -using System.Collections.Immutable; using System.Diagnostics; -using System.Linq; -using System.Text; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; -using Roslyn.Utilities; -using Cci = Microsoft.Cci; namespace Microsoft.CodeAnalysis.CodeGen { @@ -22,8 +16,6 @@ namespace Microsoft.CodeAnalysis.CodeGen /// internal class SequencePointList { - internal const int HiddenSequencePointLine = 0xFEEFEE; - private readonly SyntaxTree _tree; private readonly OffsetAndSpan[] _points; private SequencePointList _next; // Linked list of all points. @@ -142,7 +134,7 @@ private static OffsetAndSpan[] GetSubArray(ArrayBuilder seqPoi // a hidden sequence point. bool isHidden = span == RawSequencePoint.HiddenSequencePointSpan; - FileLinePositionSpan fileLinePositionSpan = default(FileLinePositionSpan); + FileLinePositionSpan fileLinePositionSpan = default; if (!isHidden) { fileLinePositionSpan = currentTree.GetMappedLineSpanAndVisibility(span, out isHidden); @@ -161,9 +153,9 @@ private static OffsetAndSpan[] GetSubArray(ArrayBuilder seqPoi builder.Add(new Cci.SequencePoint( lastDebugDocument, offset: offsetAndSpan.Offset, - startLine: HiddenSequencePointLine, + startLine: Cci.SequencePoint.HiddenLine, startColumn: 0, - endLine: HiddenSequencePointLine, + endLine: Cci.SequencePoint.HiddenLine, endColumn: 0)); } } @@ -178,13 +170,34 @@ private static OffsetAndSpan[] GetSubArray(ArrayBuilder seqPoi if (lastDebugDocument != null) { + int startLine = (fileLinePositionSpan.StartLinePosition.Line == -1) ? 0 : fileLinePositionSpan.StartLinePosition.Line + 1; + int endLine = (fileLinePositionSpan.EndLinePosition.Line == -1) ? 0 : fileLinePositionSpan.EndLinePosition.Line + 1; + int startColumn = fileLinePositionSpan.StartLinePosition.Character + 1; + int endColumn = fileLinePositionSpan.EndLinePosition.Character + 1; + + // Trim column number if necessary. + // Column must be in range [0, 0xffff) and end column must be greater than start column if on the same line. + // The Portable PDB specifies 0x10000, but System.Reflection.Metadata reader has an off-by-one error. + // Windows PDBs allow the same range. + const int MaxColumn = ushort.MaxValue - 1; + + if (startColumn > MaxColumn) + { + startColumn = (startLine == endLine) ? MaxColumn - 1 : MaxColumn; + } + + if (endColumn > MaxColumn) + { + endColumn = MaxColumn; + } + builder.Add(new Cci.SequencePoint( lastDebugDocument, offset: offsetAndSpan.Offset, - startLine: (fileLinePositionSpan.StartLinePosition.Line == -1) ? 0 : fileLinePositionSpan.StartLinePosition.Line + 1, - startColumn: fileLinePositionSpan.StartLinePosition.Character + 1, - endLine: (fileLinePositionSpan.EndLinePosition.Line == -1) ? 0 : fileLinePositionSpan.EndLinePosition.Line + 1, - endColumn: fileLinePositionSpan.EndLinePosition.Character + 1 + startLine: startLine, + startColumn: (ushort)startColumn, + endLine: endLine, + endColumn: (ushort)endColumn )); } } diff --git a/src/Compilers/Core/Portable/PEWriter/SequencePoint.cs b/src/Compilers/Core/Portable/PEWriter/SequencePoint.cs index c6d566dd6dcc4eaca98f8c697db35b37916f3854..7b065b01bb35a86fa3998a8ac81a7609877cdc05 100644 --- a/src/Compilers/Core/Portable/PEWriter/SequencePoint.cs +++ b/src/Compilers/Core/Portable/PEWriter/SequencePoint.cs @@ -8,22 +8,24 @@ namespace Microsoft.Cci { [SuppressMessage("Performance", "CA1067", Justification = "Equality not actually implemented")] [DebuggerDisplay("{" + nameof(GetDebuggerDisplay) + "(),nq}")] - internal struct SequencePoint + internal readonly struct SequencePoint { + public const int HiddenLine = 0xfeefee; + public readonly int Offset; public readonly int StartLine; - public readonly int StartColumn; public readonly int EndLine; - public readonly int EndColumn; + public readonly ushort StartColumn; + public readonly ushort EndColumn; public readonly DebugSourceDocument Document; public SequencePoint( DebugSourceDocument document, int offset, int startLine, - int startColumn, + ushort startColumn, int endLine, - int endColumn) + ushort endColumn) { Debug.Assert(document != null); @@ -35,7 +37,7 @@ internal struct SequencePoint Document = document; } - public bool IsHidden => StartLine == 0xfeefee; + public bool IsHidden => StartLine == HiddenLine; public override int GetHashCode() { diff --git a/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs b/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs index 46c907486a1200eb5635e75727990f8c44b5f796..5499ed4ecf117ef52ffe31d778215355c8e00869 100644 --- a/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs +++ b/src/ExpressionEvaluator/Core/Test/ExpressionCompiler/ExpressionCompilerTestHelpers.cs @@ -758,7 +758,7 @@ internal static uint GetOffset(int methodToken, ISymUnmanagedReader symReader, i { var sequencePoints = symMethod.GetSequencePoints(); ilOffset = atLineNumber < 0 - ? sequencePoints.Where(sp => sp.StartLine != SequencePointList.HiddenSequencePointLine).Select(sp => sp.Offset).FirstOrDefault() + ? sequencePoints.Where(sp => sp.StartLine != Cci.SequencePoint.HiddenLine).Select(sp => sp.Offset).FirstOrDefault() : sequencePoints.First(sp => sp.StartLine == atLineNumber).Offset; } }