/// <summary>
        /// Create a SequencePointList with the raw sequence points from an ArrayBuilder.
        /// A linked list of instances for each syntax tree is created (almost always of length one).
        /// </summary>
        public static SequencePointList Create(ArrayBuilder <RawSequencePoint> seqPointBuilder, ILBuilder builder)
        {
            if (seqPointBuilder.Count == 0)
            {
                return(SequencePointList.s_empty);
            }

            SequencePointList first = null, current = null;
            int totalPoints = seqPointBuilder.Count;
            int last = 0;

            for (int i = 1; i <= totalPoints; ++i)
            {
                if (i == totalPoints || seqPointBuilder[i].SyntaxTree != seqPointBuilder[i - 1].SyntaxTree)
                {
                    // Create a new list
                    SequencePointList next = new SequencePointList(seqPointBuilder[i - 1].SyntaxTree, GetSubArray(seqPointBuilder, last, i - last, builder));
                    last = i;

                    // Link together with any additional.
                    if (current == null)
                    {
                        first = current = next;
                    }
                    else
                    {
                        current._next = next;
                        current       = next;
                    }
                }
            }

            return(first);
        }
Exemple #2
0
        private static ImmutableArray <Cci.SequencePoint> GetSequencePoints(SequencePointList sequencePoints, DebugDocumentProvider debugDocumentProvider)
        {
            if (sequencePoints == null || sequencePoints.IsEmpty)
            {
                return(ImmutableArray <Cci.SequencePoint> .Empty);
            }

            var sequencePointsBuilder = ArrayBuilder <Cci.SequencePoint> .GetInstance();

            sequencePoints.GetSequencePoints(debugDocumentProvider, sequencePointsBuilder);
            return(sequencePointsBuilder.ToImmutableAndFree());
        }
Exemple #3
0
        public MethodBody(
            ImmutableArray <byte> ilBits,
            ushort maxStack,
            Cci.IMethodDefinition parent,
            DebugId methodId,
            ImmutableArray <Cci.ILocalDefinition> locals,
            SequencePointList sequencePoints,
            DebugDocumentProvider debugDocumentProvider,
            ImmutableArray <Cci.ExceptionHandlerRegion> exceptionHandlers,
            ImmutableArray <Cci.LocalScope> localScopes,
            bool hasDynamicLocalVariables,
            Cci.IImportScope importScopeOpt,
            ImmutableArray <LambdaDebugInfo> lambdaDebugInfo,
            ImmutableArray <ClosureDebugInfo> closureDebugInfo,
            string stateMachineTypeNameOpt,
            ImmutableArray <StateMachineHoistedLocalScope> stateMachineHoistedLocalScopes,
            ImmutableArray <EncHoistedLocalInfo> stateMachineHoistedLocalSlots,
            ImmutableArray <Cci.ITypeReference> stateMachineAwaiterSlots,
            StateMachineMoveNextBodyDebugInfo stateMachineMoveNextDebugInfoOpt,
            DynamicAnalysisMethodBodyData dynamicAnalysisDataOpt)
        {
            Debug.Assert(!locals.IsDefault);
            Debug.Assert(!exceptionHandlers.IsDefault);
            Debug.Assert(!localScopes.IsDefault);

            _ilBits                           = ilBits;
            _maxStack                         = maxStack;
            _parent                           = parent;
            _methodId                         = methodId;
            _locals                           = locals;
            _exceptionHandlers                = exceptionHandlers;
            _localScopes                      = localScopes;
            _hasDynamicLocalVariables         = hasDynamicLocalVariables;
            _importScopeOpt                   = importScopeOpt;
            _lambdaDebugInfo                  = lambdaDebugInfo;
            _closureDebugInfo                 = closureDebugInfo;
            _stateMachineTypeNameOpt          = stateMachineTypeNameOpt;
            _stateMachineHoistedLocalScopes   = stateMachineHoistedLocalScopes;
            _stateMachineHoistedLocalSlots    = stateMachineHoistedLocalSlots;
            _stateMachineAwaiterSlots         = stateMachineAwaiterSlots;
            _stateMachineMoveNextDebugInfoOpt = stateMachineMoveNextDebugInfoOpt;
            _dynamicAnalysisDataOpt           = dynamicAnalysisDataOpt;
            _sequencePoints                   = GetSequencePoints(sequencePoints, debugDocumentProvider);
        }
Exemple #4
0
        private void RealizeSequencePoints()
        {
            if (this.SeqPointsOpt != null)
            {
                // we keep track of the latest sequence point location to make sure
                // we don't emit multiple sequence points for the same location
                int lastOffset = -1;

                ArrayBuilder <RawSequencePoint> seqPoints = ArrayBuilder <RawSequencePoint> .GetInstance();

                foreach (var seqPoint in this.SeqPointsOpt)
                {
                    int offset = this.GetILOffsetFromMarker(seqPoint.ILMarker);
                    if (offset >= 0)
                    {
                        // valid IL offset
                        if (lastOffset != offset)
                        {
                            Debug.Assert(lastOffset < offset);
                            // if there are any sequence points, there must
                            // be a sequence point at offset 0.
                            Debug.Assert((lastOffset >= 0) || (offset == 0));
                            // the first sequence point on tree/offset location
                            lastOffset = offset;
                            seqPoints.Add(seqPoint);
                        }
                        else
                        {
                            // override previous sequence point at the same location
                            seqPoints[seqPoints.Count - 1] = seqPoint;
                        }
                    }
                }

                if (seqPoints.Count > 0)
                {
                    this.RealizedSequencePoints = SequencePointList.Create(seqPoints, this);
                }

                seqPoints.Free();
            }
        }
        // Find the document for the first non-hidden sequence point (issue #4370)
        // Returns null if a real sequence point was not found.
        private FileLinePositionSpan?FindFirstRealSequencePoint()
        {
            SequencePointList current = this;

            while (current != null)
            {
                foreach (var offsetAndSpan in current._points)
                {
                    TextSpan span     = offsetAndSpan.Span;
                    bool     isHidden = span == RawSequencePoint.HiddenSequencePointSpan;
                    if (!isHidden)
                    {
                        FileLinePositionSpan fileLinePositionSpan = current._tree.GetMappedLineSpanAndVisibility(span, out isHidden);
                        if (!isHidden)
                        {
                            return(fileLinePositionSpan);
                        }
                    }
                }
                current = current._next;
            }

            return(null);
        }
        /// <summary>
        /// Get all the sequence points, possibly mapping them using #line/ExternalSource directives, and mapping
        /// file names to debug documents with the given mapping function.
        /// </summary>
        /// <param name="documentProvider">Function that maps file paths to CCI debug documents</param>
        /// <param name="builder">where sequence points should be deposited</param>
        public void GetSequencePoints(
            DebugDocumentProvider documentProvider,
            ArrayBuilder <Cci.SequencePoint> builder)
        {
            bool   lastPathIsMapped = false;
            string lastPath         = null;

            Cci.DebugSourceDocument lastDebugDocument = null;

            FileLinePositionSpan?firstReal = FindFirstRealSequencePoint();

            if (!firstReal.HasValue)
            {
                return;
            }
            lastPath          = firstReal.Value.Path;
            lastPathIsMapped  = firstReal.Value.HasMappedPath;
            lastDebugDocument = documentProvider(lastPath, basePath: lastPathIsMapped ? this._tree.FilePath : null);

            SequencePointList current = this;

            while (current != null)
            {
                SyntaxTree currentTree = current._tree;

                foreach (var offsetAndSpan in current._points)
                {
                    TextSpan span = offsetAndSpan.Span;

                    // if it's a hidden sequence point, or a sequence point with syntax that points to a position that is inside
                    // of a hidden region (can be defined with #line hidden (C#) or implicitly by #ExternalSource (VB), make it
                    // a hidden sequence point.

                    bool isHidden = span == RawSequencePoint.HiddenSequencePointSpan;
                    FileLinePositionSpan fileLinePositionSpan = default;
                    if (!isHidden)
                    {
                        fileLinePositionSpan = currentTree.GetMappedLineSpanAndVisibility(span, out isHidden);
                    }

                    if (isHidden)
                    {
                        if (lastPath == null)
                        {
                            lastPath          = currentTree.FilePath;
                            lastDebugDocument = documentProvider(lastPath, basePath: null);
                        }

                        if (lastDebugDocument != null)
                        {
                            builder.Add(new Cci.SequencePoint(
                                            lastDebugDocument,
                                            offset: offsetAndSpan.Offset,
                                            startLine: Cci.SequencePoint.HiddenLine,
                                            startColumn: 0,
                                            endLine: Cci.SequencePoint.HiddenLine,
                                            endColumn: 0));
                        }
                    }
                    else
                    {
                        if (lastPath != fileLinePositionSpan.Path || lastPathIsMapped != fileLinePositionSpan.HasMappedPath)
                        {
                            lastPath          = fileLinePositionSpan.Path;
                            lastPathIsMapped  = fileLinePositionSpan.HasMappedPath;
                            lastDebugDocument = documentProvider(lastPath, basePath: lastPathIsMapped ? currentTree.FilePath : null);
                        }

                        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 StarkPlatform.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: startLine,
                                            startColumn: (ushort)startColumn,
                                            endLine: endLine,
                                            endColumn: (ushort)endColumn
                                            ));
                        }
                    }
                }

                current = current._next;
            }
        }