@@ -275,7 +275,7 @@ let generatePortablePdb fixupSPs showTimes (info:PdbData) =
275275
276276 let mutable lastLocalVariableHandle = Unchecked.defaultof< LocalVariableHandle>
277277 metadata.SetCapacity( TableIndex.MethodDebugInformation, info.Methods.Length)
278- info.Methods |> Array.iteri ( fun _i minfo ->
278+ info.Methods |> Array.iter ( fun minfo ->
279279 let docHandle , sequencePointBlob =
280280 let sps =
281281 match minfo.SequencePoints with
@@ -284,107 +284,122 @@ let generatePortablePdb fixupSPs showTimes (info:PdbData) =
284284 match minfo.Range with
285285 | None -> Array.empty< PdbSequencePoint>
286286 | Some (_,_) -> minfo.SequencePoints
287-
288- let getDocumentHandle d =
289- if docs.Length = 0 || d < 0 || d > docs.Length then
287+
288+ let getDocumentHandle d =
289+ if docs.Length = 0 || d < 0 || d > docs.Length then
290290 Unchecked.defaultof< DocumentHandle>
291291 else
292292 match documentIndex.TryGetValue( docs.[ d]. File) with
293293 | false , _ -> Unchecked.defaultof< DocumentHandle>
294294 | true , f -> f
295295
296- // Return a document that the entire method body is declared within.
297- // If part of the method body is in another document returns nil handle.
298- let tryGetSingleDocumentIndex =
299- let mutable singleDocumentIndex = 0
300- for i in 0 .. sps.Length - 1 do
301- let index = sps.[ i]. Document
302- if index <> singleDocumentIndex then
303- singleDocumentIndex <- index
304- singleDocumentIndex
305-
306- // Filter out feefee (Hidden) sequence points
307- let sps = sps |> Array.filter( fun sp -> sp.Line <> 0xfeefee && sp.EndLine <> 0xfeefee )
308-
309296 if sps.Length = 0 then
310297 Unchecked.defaultof< DocumentHandle>, Unchecked.defaultof< BlobHandle>
311298 else
312- let mutable previousNonHiddenStartLine = - 1
313- let mutable previousNonHiddenStartColumn = - 1
314- let mutable previousDocumentIndex = - 1
315- let mutable singleDocumentIndex = tryGetSingleDocumentIndex
316- let mutable currentDocumentIndex = previousDocumentIndex
299+ // Return a document that the entire method body is declared within.
300+ // If part of the method body is in another document returns nil handle.
301+ let tryGetSingleDocumentIndex =
302+ let mutable singleDocumentIndex = sps.[ 0 ]. Document
303+ for i in 1 .. sps.Length - 1 do
304+ if sps.[ i]. Document <> singleDocumentIndex then
305+ singleDocumentIndex <- - 1
306+ singleDocumentIndex
317307
318308 let builder = new BlobBuilder()
309+
319310 builder.WriteCompressedInteger( minfo.LocalSignatureToken)
320311
321- for i in 0 .. ( sps.Length - 1 ) do
322- if previousDocumentIndex <> currentDocumentIndex then
323- // optional document in header or document record:
324- if previousDocumentIndex <> - 1 then
325- // optional document in header or document record
326- builder.WriteCompressedInteger( 0 )
327- builder.WriteCompressedInteger( currentDocumentIndex)
328- previousDocumentIndex <- currentDocumentIndex
329-
330- // delta IL offset:
331- if i > 0 then
332- builder.WriteCompressedInteger( sps.[ i]. Offset - sps.[ i - 1 ]. Offset)
333- else
334- builder.WriteCompressedInteger( sps.[ i]. Offset)
312+ // Initial document: When sp's spread over more than one document we put the initial document here.
313+ let singleDocumentIndex = tryGetSingleDocumentIndex
335314
336- let deltaLines = sps.[ i]. EndLine - sps.[ i]. Line
337- let deltaColumns = sps.[ i]. EndColumn - sps.[ i]. Column
338- builder.WriteCompressedInteger( deltaLines)
315+ if singleDocumentIndex = - 1 then
316+ builder.WriteCompressedInteger( MetadataTokens.GetRowNumber( DocumentHandle.op_ Implicit( getDocumentHandle ( sps.[ 0 ]. Document))) )
339317
340- if deltaLines = 0 then
341- builder.WriteCompressedInteger( deltaColumns)
342- else
343- builder.WriteCompressedSignedInteger( deltaColumns)
318+ let mutable previousNonHiddenStartLine = - 1
319+ let mutable previousNonHiddenStartColumn = 0
344320
345- // delta Start Lines & Columns:
346- if previousNonHiddenStartLine < 0 then
347- builder.WriteCompressedInteger( sps.[ i]. Line)
348- builder.WriteCompressedInteger( sps.[ i]. Column)
349- else
350- builder.WriteCompressedSignedInteger( sps.[ i]. Line - previousNonHiddenStartLine)
351- builder.WriteCompressedSignedInteger( sps.[ i]. Column - previousNonHiddenStartColumn)
321+ for i in 0 .. ( sps.Length - 1 ) do
352322
353- previousNonHiddenStartLine <- sps.[ i]. Line
354- previousNonHiddenStartColumn <- sps.[ i]. Column
323+ if singleDocumentIndex <> - 1 && sps.[ i]. Document <> singleDocumentIndex then
324+ builder.WriteCompressedInteger( 0 )
325+ builder.WriteCompressedInteger( MetadataTokens.GetRowNumber( DocumentHandle.op_ Implicit( getDocumentHandle ( sps.[ i]. Document))) )
326+ else
327+ // Sequence-point-record
328+ let offsetDelta =
329+ if i > 0 then sps.[ i]. Offset - sps.[ i - 1 ]. Offset // delta from previous offset
330+ else sps.[ i]. Offset // delta IL offset
331+
332+ if i < 1 || offsetDelta <> 0 then // ILOffset must not be 0
333+ builder.WriteCompressedInteger( offsetDelta)
334+
335+ if sps.[ i]. Line = 0xfeefee && sps.[ i]. EndLine = 0xfeefee then // Hidden-sequence-point-record
336+ builder.WriteCompressedInteger( 0 )
337+ builder.WriteCompressedInteger( 0 )
338+ else // Non-hidden-sequence-point-record
339+ let deltaLines = sps.[ i]. EndLine - sps.[ i]. Line // lines
340+ builder.WriteCompressedInteger( deltaLines)
341+
342+ let deltaColumns = sps.[ i]. EndColumn - sps.[ i]. Column // Columns
343+ if deltaLines = 0 then
344+ builder.WriteCompressedInteger( deltaColumns)
345+ else
346+ builder.WriteCompressedSignedInteger( deltaColumns)
347+
348+ if previousNonHiddenStartLine < 0 then // delta Start Line & Column:
349+ builder.WriteCompressedInteger( sps.[ i]. Line)
350+ builder.WriteCompressedInteger( sps.[ i]. Column)
351+ else
352+ builder.WriteCompressedSignedInteger( sps.[ i]. Line - previousNonHiddenStartLine)
353+ builder.WriteCompressedSignedInteger( sps.[ i]. Column - previousNonHiddenStartColumn)
354+
355+ previousNonHiddenStartLine <- sps.[ i]. Line
356+ previousNonHiddenStartColumn <- sps.[ i]. Column
355357
356358 getDocumentHandle singleDocumentIndex, metadata.GetOrAddBlob( builder)
357359
360+ metadata.AddMethodDebugInformation( docHandle, sequencePointBlob) |> ignore
361+
358362 // Write the scopes
359363 let nextHandle handle = MetadataTokens.LocalVariableHandle( MetadataTokens.GetRowNumber( LocalVariableHandle.op_ Implicit( handle)) + 1 )
360- let rec writePdbScope scope =
361- if scope.Children.Length = 0 then
362- metadata.AddLocalScope( MetadataTokens.MethodDefinitionHandle( minfo.MethToken),
363- Unchecked.defaultof< ImportScopeHandle>,
364- nextHandle lastLocalVariableHandle,
365- Unchecked.defaultof< LocalConstantHandle>,
366- 0 ,
367- scope.EndOffset - scope.StartOffset) |> ignore
368- else
369- metadata.AddLocalScope( MetadataTokens.MethodDefinitionHandle( minfo.MethToken),
370- Unchecked.defaultof< ImportScopeHandle>,
371- nextHandle lastLocalVariableHandle,
372- Unchecked.defaultof< LocalConstantHandle>,
373- scope.StartOffset,
374- scope.EndOffset - scope.StartOffset) |> ignore
375-
376- for localVariable in scope.Locals do
377- lastLocalVariableHandle <- metadata.AddLocalVariable( LocalVariableAttributes.None, localVariable.Index, metadata.GetOrAddString( localVariable.Name))
378-
379- scope.Children |> Array.iter ( writePdbScope)
380-
381- writePdbScope minfo.RootScope
382- metadata.AddMethodDebugInformation( docHandle, sequencePointBlob) |> ignore)
364+ let writeMethodScope scope =
365+ let scopeSorter ( scope1 : PdbMethodScope ) ( scope2 : PdbMethodScope ) =
366+ if scope1.StartOffset > scope2.StartOffset then 1
367+ elif scope1.StartOffset < scope2.StartOffset then - 1
368+ elif ( scope1.EndOffset - scope1.StartOffset) > ( scope2.EndOffset - scope2.StartOffset) then - 1
369+ elif ( scope1.EndOffset - scope1.StartOffset) < ( scope2.EndOffset - scope2.StartOffset) then 1
370+ else 0
371+
372+ let collectScopes scope =
373+ let list = new List< PdbMethodScope>()
374+ let rec toList scope =
375+ list.Add scope
376+ scope.Children |> Seq.iter( fun s -> toList s)
377+ toList scope
378+ list.ToArray() |> Array.sortWith< PdbMethodScope> scopeSorter
379+
380+ collectScopes scope |> Seq.iter( fun s ->
381+ if s.Children.Length = 0 then
382+ metadata.AddLocalScope( MetadataTokens.MethodDefinitionHandle( minfo.MethToken),
383+ Unchecked.defaultof< ImportScopeHandle>,
384+ nextHandle lastLocalVariableHandle,
385+ Unchecked.defaultof< LocalConstantHandle>,
386+ 0 , s.EndOffset - s.StartOffset ) |> ignore
387+ else
388+ metadata.AddLocalScope( MetadataTokens.MethodDefinitionHandle( minfo.MethToken),
389+ Unchecked.defaultof< ImportScopeHandle>,
390+ nextHandle lastLocalVariableHandle,
391+ Unchecked.defaultof< LocalConstantHandle>,
392+ s.StartOffset, s.EndOffset - s.StartOffset) |> ignore
393+
394+ for localVariable in s.Locals do
395+ lastLocalVariableHandle <- metadata.AddLocalVariable( LocalVariableAttributes.None, localVariable.Index, metadata.GetOrAddString( localVariable.Name))
396+ )
397+ writeMethodScope minfo.RootScope )
383398
384399 let entryPoint =
385- match info.EntryPoint with
400+ match info.EntryPoint with
386401 | None -> MetadataTokens.MethodDefinitionHandle( 0 )
387- | Some x -> MetadataTokens.MethodDefinitionHandle( x)
402+ | Some x -> MetadataTokens.MethodDefinitionHandle( x)
388403
389404 let serializer = PortablePdbBuilder( metadata, externalRowCounts, entryPoint, null )
390405 let blobBuilder = new BlobBuilder()
0 commit comments