Example #1
0
        private SyntaxToken ParseEndOfDirective(bool ignoreErrors, bool afterPragma = false, bool afterLineNumber = false, bool afterReference = false)
        {
            var skippedTokens = new SyntaxListBuilder <SyntaxToken>();

            // Consume all extranous tokens as leading SkippedTokens trivia.
            if (this.CurrentToken.Kind != SyntaxKind.EndOfDirectiveToken &&
                this.CurrentToken.Kind != SyntaxKind.EndOfFileToken)
            {
                skippedTokens = new SyntaxListBuilder <SyntaxToken>(10);

                if (!ignoreErrors)
                {
                    ErrorCode errorCode = ErrorCode.ERR_EndOfPPLineExpected;
                    if (afterPragma)
                    {
                        errorCode = ErrorCode.WRN_EndOfPPLineExpected;
                    }
                    else if (afterLineNumber)
                    {
                        errorCode = ErrorCode.ERR_MissingPPFile;
                    }
                    else if (afterReference)
                    {
                        errorCode = ErrorCode.ERR_ExpectedPPFile;
                    }

                    skippedTokens.Add(this.AddError(this.EatToken().WithoutDiagnosticsGreen(), errorCode));
                }

                while (this.CurrentToken.Kind != SyntaxKind.EndOfDirectiveToken &&
                       this.CurrentToken.Kind != SyntaxKind.EndOfFileToken)
                {
                    skippedTokens.Add(this.EatToken().WithoutDiagnosticsGreen());
                }
            }

            // attach text from extraneous tokens as trivia to EndOfDirective token
            SyntaxToken endOfDirective = this.CurrentToken.Kind == SyntaxKind.EndOfDirectiveToken
                                         ? this.EatToken()
                                         : SyntaxFactory.Token(SyntaxKind.EndOfDirectiveToken);

            if (!skippedTokens.IsNull)
            {
                endOfDirective = endOfDirective.WithLeadingTrivia(SyntaxFactory.SkippedTokensTrivia(skippedTokens.ToList()));
            }

            return(endOfDirective);
        }
Example #2
0
        public override CSharpSyntaxNode VisitToken(SyntaxToken token)
        {
            var leading  = this.VisitList(token.LeadingTrivia);
            var trailing = this.VisitList(token.TrailingTrivia);

            if (leading != token.LeadingTrivia || trailing != token.TrailingTrivia)
            {
                if (leading != token.LeadingTrivia)
                {
                    token = token.WithLeadingTrivia(leading.Node);
                }

                if (trailing != token.TrailingTrivia)
                {
                    token = token.WithTrailingTrivia(trailing.Node);
                }
            }

            return(token);
        }
Example #3
0
        /// <summary>
        /// Converts skippedSyntax node into tokens and adds these as trivia on the target token.
        /// Also adds the first error (in depth-first preorder) found in the skipped syntax tree to the target token.
        /// </summary>
        internal SyntaxToken AddSkippedSyntax(SyntaxToken target, CSharpSyntaxNode skippedSyntax, bool trailing)
        {
            var builder = new SyntaxListBuilder(4);

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

            // the position of the error within the skipedSyntax node full tree
            int diagnosticOffset = 0;

            int currentOffset = 0;

            foreach (var node in skippedSyntax.EnumerateNodes())
            {
                SyntaxToken token = node as SyntaxToken;
                if (token != null)
                {
                    builder.Add(token.GetLeadingTrivia());

                    if (token.Width > 0)
                    {
                        // separate trivia from the tokens
                        SyntaxToken tk = token.WithLeadingTrivia(null).WithTrailingTrivia(null);

                        // adjust relative offsets of diagnostics attached to the token:
                        int leadingWidth = token.GetLeadingTriviaWidth();
                        if (leadingWidth > 0)
                        {
                            var tokenDiagnostics = tk.GetDiagnostics();
                            for (int i = 0; i < tokenDiagnostics.Length; i++)
                            {
                                var d = (SyntaxDiagnosticInfo)tokenDiagnostics[i];
                                tokenDiagnostics[i] = new SyntaxDiagnosticInfo(d.Offset - leadingWidth, d.Width, (ErrorCode)d.Code, d.Arguments);
                            }
                        }

                        builder.Add(SyntaxFactory.SkippedTokensTrivia(tk));
                    }
                    else
                    {
                        // do not create zero-width structured trivia, GetStructure doesn't work well for them
                        var existing = (SyntaxDiagnosticInfo)token.GetDiagnostics().FirstOrDefault();
                        if (existing != null)
                        {
                            diagnostic       = existing;
                            diagnosticOffset = currentOffset;
                        }
                    }
                    builder.Add(token.GetTrailingTrivia());

                    currentOffset += token.FullWidth;
                }
                else if (node.ContainsDiagnostics && diagnostic == null)
                {
                    // only propagate the first error to reduce noise:
                    var existing = (SyntaxDiagnosticInfo)node.GetDiagnostics().FirstOrDefault();
                    if (existing != null)
                    {
                        diagnostic       = existing;
                        diagnosticOffset = currentOffset;
                    }
                }
            }

            int triviaWidth = currentOffset;
            var trivia      = builder.ToListNode();

            // total width of everything preceding the added trivia
            int triviaOffset;

            if (trailing)
            {
                var trailingTrivia = target.GetTrailingTrivia();
                triviaOffset = target.FullWidth; //added trivia is full width (before addition)
                target       = target.WithTrailingTrivia(SyntaxList.Concat(trailingTrivia, trivia));
            }
            else
            {
                // Since we're adding triviaWidth before the token, we have to add that much to
                // the offset of each of its diagnostics.
                if (triviaWidth > 0)
                {
                    var targetDiagnostics = target.GetDiagnostics();
                    for (int i = 0; i < targetDiagnostics.Length; i++)
                    {
                        var d = (SyntaxDiagnosticInfo)targetDiagnostics[i];
                        targetDiagnostics[i] = new SyntaxDiagnosticInfo(d.Offset + triviaWidth, d.Width, (ErrorCode)d.Code, d.Arguments);
                    }
                }

                var leadingTrivia = target.GetLeadingTrivia();
                target       = target.WithLeadingTrivia(SyntaxList.Concat(trivia, leadingTrivia));
                triviaOffset = 0; //added trivia is first, so offset is zero
            }

            if (diagnostic != null)
            {
                int newOffset = triviaOffset + diagnosticOffset + diagnostic.Offset;

                target = WithAdditionalDiagnostics(target,
                                                   new SyntaxDiagnosticInfo(newOffset, diagnostic.Width, (ErrorCode)diagnostic.Code, diagnostic.Arguments)
                                                   );
            }

            return(target);
        }