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

Code before:
        /// Converts skippedSyntax node into all its constituent tokens (and their constituent trivias) and adds these
        /// all as trivia on the target token.  For example, given <c>token1-token2</c>, then target will have
        /// <c>leading_trivia1-token1-trailing_trivia1-leading_trivia2-token2-trailing_trivia2-</c> added to it.
        /// <para/>
        /// Also adds the first node-based error (in depth-first preorder) found in the skipped syntax tree to the
        /// target token.
        /// </summary>
        internal SyntaxToken AddSkippedSyntax(SyntaxToken target, GreenNode skippedSyntax, bool trailing)
        {
            var builder = new SyntaxListBuilder(4);

            int currentOffset;
            if (trailing)
            {
                // The normal offset for a node/token is its start (not full start).  So if we're placing the skipped
                // syntax at the end of the trivia, then the offset relative to the node/token start will be adjusted
                // forward by the width of the node/token plus the existing trailing trivia.
                currentOffset = target.Width + target.GetTrailingTriviaWidth();
                builder.Add(target.GetTrailingTrivia());
            }
            else
            {
                // The normal offset for a node/token is its start (not full start). So if we're placing the skipped
                // syntax at the start of the trivia, then the offset relative to the node/token start will be adjusted
                // backward by the width of the existing leading trivia plus the width of the skipped syntax we're
                // tacking on at the front.
                currentOffset = -target.GetLeadingTriviaWidth() - skippedSyntax.FullWidth;
            }

            // the error in we'll attach to the node
            SyntaxDiagnosticInfo diagnostic = null;
            int finalDiagnosticOffset = 0;

            foreach (var node in skippedSyntax.EnumerateNodes())
            {
                if (node is SyntaxToken token)
                {
                    // Strip the leading trivia of the token, and add it to the target's final trivia list.
                    builder.Add(token.GetLeadingTrivia());

                    if (token.Width > 0)
                    {
                        // Then add the token (stripped of its own trivia) to the target's final trivia list.

                        builder.Add(SyntaxFactory.SkippedTokensTrivia(
                            token.TokenWithLeadingTrivia(null).TokenWithTrailingTrivia(null)));
                    }
                    else
                    {
                        // Do not bother adding zero-width tokens to target's final trivia list.  Lots of code (like
                        // GetStructure) does not like it at all. But do keep around any diagnostics that might have

Review comment (suggestion):
all this adjustmnet of diagnostics goes away.  because the diag is always relative to the token's start, it doesn't need to change, even when we strip off the leading trivia of it and move that leading trivia to the target token.

Code after:
        /// Converts skippedSyntax node into all its constituent tokens (and their constituent trivias) and adds these
        /// all as trivia on the target token.  For example, given <c>token1-token2</c>, then target will have
        /// <c>leading_trivia1-token1-trailing_trivia1-leading_trivia2-token2-trailing_trivia2-</c> added to it.
        /// <para/>
        /// 
        /// Also adds the first node-based error, or error on a missing-token, in depth-first preorder, found in the
        /// skipped syntax tree to the target token.  This ensures that we do not lose token/node errors found in
        /// skipped syntax.
        /// 
        /// Note: This behavior could technically lead to buggy behavior.  Specifically, because we only take the first
        /// diagnostic we find, we might miss a more relevant diagnostic later in the tree.  For example, we might
        /// preserve a 'warning' while missing an error.
        /// 
        /// We should either:
        /// 
        /// 1. ensure that we copy over an error if it exists, overwriting any warnings we found along the way.
        /// 
        /// 2. just copy over everything.  This seems saner, as it means not losing anything. But it might be the case
        /// that when we recover from a big error recovery scan, we might report a ton of errors.
        ///
        /// For now, we do neither, and just take the first error/warning we find.  This can/should be revisited later
        /// if we discover it means we're losing important diagnostics.
        /// </summary>
        internal SyntaxToken AddSkippedSyntax(SyntaxToken target, GreenNode skippedSyntax, bool trailing)
        {
            var builder = new SyntaxListBuilder(4);

            int currentOffset;
            if (trailing)
            {
                // The normal offset for a node/token is its start (not full start).  So if we're placing the skipped
                // syntax at the end of the trivia, then the offset relative to the node/token start will be adjusted
                // forward by the width of the node/token plus the existing trailing trivia.
                currentOffset = target.Width + target.GetTrailingTriviaWidth();
                builder.Add(target.GetTrailingTrivia());
            }
            else
            {
                // The normal offset for a node/token is its start (not full start). So if we're placing the skipped
                // syntax at the start of the trivia, then the offset relative to the node/token start will be adjusted
                // backward by the width of the existing leading trivia plus the width of the skipped syntax we're
                // tacking on at the front.
                currentOffset = -target.GetLeadingTriviaWidth() - skippedSyntax.FullWidth;
            }

            // the error in we'll attach to the node
            SyntaxDiagnosticInfo diagnostic = null;
            int finalDiagnosticOffset = 0;

            foreach (var node in skippedSyntax.EnumerateNodes())
            {