Repository: dotnet/roslyn
File: src/Compilers/CSharp/Portable/Syntax/SyntaxTreeDiagnosticEnumerator.cs (C#)

Code before:
﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.CSharp
{
    /// <summary>
    /// An enumerator for diagnostic lists.
    /// </summary>
    internal struct SyntaxTreeDiagnosticEnumerator
    {
        private readonly SyntaxTree? _syntaxTree;
        private NodeIterationStack _stack;
        private Diagnostic? _current;

        /// <summary>
        /// Note:during iteration, '_position' is:
        /// <list type="number">
        /// <item>The FullStart of a node when we're on a node.</item>
        /// <item>The FullStart of a trivia when we're on trivia.</item>
        /// <item>The FullStart of a list whne we're on a list.</item>
        /// <item>The *Start* (not FullStart) of a token when we're on a token.</item>
        /// </list>
        ///
        /// The last is because when we hit a token, we will have processed its leading trivia, and will have moved
        /// foward.
        /// <para/>However, the offset for a diagnostic is relative to its FullStart (see <see
        /// cref="SyntaxDiagnosticInfo.Offset"/>). Because of this, the offset can be directly combined with the
        /// position for the first 3, but will need to be adjusted when processing a token itself.
        /// </summary>
        private int _position;
        private const int DefaultStackCapacity = 8;

        internal SyntaxTreeDiagnosticEnumerator(SyntaxTree syntaxTree, GreenNode? node, int position)
        {
            _syntaxTree = null;
            _current = null;
            _position = position;
            if (node != null && node.ContainsDiagnostics)
            {
                _syntaxTree = syntaxTree;
                _stack = new NodeIterationStack(DefaultStackCapacity);
                _stack.PushNodeOrToken(node);
            }
            else
            {

Review comment (suggestion):

```suggestion
        /// <item>The FullStart of a list when we're on a list.</item>
```

Code after:
﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.CSharp
{
    /// <summary>
    /// An enumerator for diagnostic lists.
    /// </summary>
    internal static class SyntaxTreeDiagnosticEnumerator
    {
        private const int DefaultStackCapacity = 8;

        public static IEnumerable<Diagnostic> EnumerateDiagnostics(SyntaxTree syntaxTree, GreenNode root, int position)
        {
            // Note:during iteration, '_position' is:
            // <list type="number">
            // <item>The FullStart of a node when we're on a node.</item>
            // <item>The FullStart of a trivia when we're on trivia.</item>
            // <item>The FullStart of a list when we're on a list.</item>
            // <item>The *Start* (not FullStart) of a token when we're on a token.</item>
            // </list>
            //
            // The last is because when we hit a token, we will have processed its leading trivia, and will have moved
            // forward.
            // <para/>However, the offset for a diagnostic is relative to its FullStart (see <see
            // cref="SyntaxDiagnosticInfo.Offset"/>). Because of this, the offset can be directly combined with the
            // position for the first 3, but will need to be adjusted when processing a token itself.

            Debug.Assert(root.ContainsDiagnostics, "Caller should have checked that the root has diagnostics");

            using var stack = new NodeIterationStack(DefaultStackCapacity);
            stack.PushNodeOrToken(root);

            while (stack.Any())
            {
                var node = stack.Top.Node;

                if (!stack.Top.ProcessedDiagnostics)
                {
                    foreach (SyntaxDiagnosticInfo sdi in node.GetDiagnostics())
                    {
                        // For tokens, we've already seen leading trivia (as we push leading/trailing trivia explicit as
                        // green nodes to process on the stack), so we have to roll back.  For nodes, we have yet to see the