Example #1
0
        /// <summary>
        /// Creates a separated list of nodes from a sequence of nodes and a sequence of separator tokens.
        /// </summary>
        /// <typeparam name="TNode">The specific type of the element nodes.</typeparam>
        /// <param name="nodes">A sequence of syntax nodes.</param>
        /// <param name="separators">A sequence of token to be interleaved between the nodes. The number of tokens must
        /// be one less than the number of nodes.</param>
        public virtual SeparatedSyntaxList <TNode> SeparatedList <TNode>(IEnumerable <TNode> nodes, IEnumerable <SyntaxToken> separators) where TNode : SyntaxNode
        {
            // Interleave the nodes and the separators.  The number of separators must be equal to or 1 less than the number of nodes or
            // an argument exception is thrown.

            if (nodes != null)
            {
                IEnumerator <TNode> enumerator             = nodes.GetEnumerator();
                SeparatedSyntaxListBuilder <TNode> builder = SeparatedSyntaxListBuilder <TNode> .Create();

                if (separators != null)
                {
                    foreach (SyntaxToken token in separators)
                    {
                        if (!enumerator.MoveNext())
                        {
                            throw new ArgumentException($"{nameof(nodes)} must not be empty.", nameof(nodes));
                        }

                        builder.Add(enumerator.Current);
                        builder.AddSeparator(token);
                    }
                }

                if (enumerator.MoveNext())
                {
                    builder.Add(enumerator.Current);
                    if (enumerator.MoveNext())
                    {
                        throw new ArgumentException($"{nameof(separators)} must have 1 fewer element than {nameof(nodes)}", nameof(separators));
                    }
                }

                return(builder.ToList());
            }

            if (separators != null)
            {
                throw new ArgumentException($"When {nameof(nodes)} is null, {nameof(separators)} must also be null.", nameof(separators));
            }

            return(default(SeparatedSyntaxList <TNode>));
        }
Example #2
0
        /// <summary>
        /// Creates a separated list of nodes from a sequence of nodes, synthesizing comma separators in between.
        /// </summary>
        /// <typeparam name="TNode">The specific type of the element nodes.</typeparam>
        /// <param name="nodes">A sequence of syntax nodes.</param>
        public virtual SeparatedSyntaxList <TNode> SeparatedList <TNode>(IEnumerable <TNode> nodes, SyntaxKind separatorKind) where TNode : SyntaxNode
        {
            if (nodes == null)
            {
                return(default(SeparatedSyntaxList <TNode>));
            }

            var collection = nodes as ICollection <TNode>;

            if (collection != null && collection.Count == 0)
            {
                return(default(SeparatedSyntaxList <TNode>));
            }

            using (var enumerator = nodes.GetEnumerator())
            {
                if (!enumerator.MoveNext())
                {
                    return(default(SeparatedSyntaxList <TNode>));
                }

                var firstNode = enumerator.Current;

                if (!enumerator.MoveNext())
                {
                    return(SingletonSeparatedList <TNode>(firstNode));
                }

                var builder = new SeparatedSyntaxListBuilder <TNode>(collection != null ? collection.Count : 3);

                builder.Add(firstNode);

                var commaToken = Token(separatorKind);

                do
                {
                    builder.AddSeparator(commaToken);
                    builder.Add(enumerator.Current);
                }while (enumerator.MoveNext());

                return(builder.ToList());
            }
        }
Example #3
0
        private DirectiveTriviaSyntax ParsePragmaDirective(SyntaxToken hash, SyntaxToken pragma, bool isActive)
        {
            pragma = CheckFeatureAvailability(pragma, MessageID.IDS_FeaturePragma);

            bool hasError = false;
            if (this.CurrentToken.ContextualKind == SyntaxKind.WarningKeyword)
            {
                var warning = this.EatContextualToken(SyntaxKind.WarningKeyword);
                SyntaxToken style;
                if (this.CurrentToken.Kind == SyntaxKind.DisableKeyword || this.CurrentToken.Kind == SyntaxKind.RestoreKeyword)
                {
                    style = this.EatToken();
                    var ids = new SeparatedSyntaxListBuilder<ExpressionSyntax>(10);
                    while (this.CurrentToken.Kind != SyntaxKind.EndOfDirectiveToken)
                    {
                        SyntaxToken id;
                        ExpressionSyntax idExpression;

                        if (this.CurrentToken.Kind == SyntaxKind.NumericLiteralToken)
                        {
                            // Previous versions of the compiler used to report a warning (CS1691)
                            // whenever an unrecognized warning code was supplied in a #pragma directive
                            // (or via /nowarn /warnaserror flags on the command line).
                            // Going forward, we won't generate any warning in such cases. This will make
                            // maintainance of backwards compatibility easier (we no longer need to worry
                            // about breaking existing projects / command lines if we deprecate / remove
                            // an old warning code).
                            id = this.EatToken();
                            idExpression = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, id);
                        }
                        else if (this.CurrentToken.Kind == SyntaxKind.IdentifierToken)
                        {
                            // Lexing / parsing of identifiers inside #pragma warning directives is identical
                            // to that inside #define directives except that very long identifiers inside #define
                            // are truncated to 128 characters to maintain backwards compatibility with previous
                            // versions of the compiler. (See TruncateIdentifier() below.)
                            // Since support for identifiers inside #pragma warning directivess is new, 
                            // we don't have any backwards compatibility constraints. So we can preserve the
                            // identifier exactly as it appears in source.
                            id = this.EatToken();
                            idExpression = SyntaxFactory.IdentifierName(id);
                        }
                        else
                        {
                            id = this.EatToken(SyntaxKind.NumericLiteralToken, ErrorCode.WRN_IdentifierOrNumericLiteralExpected, reportError: isActive);
                            idExpression = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, id);
                        }

                        hasError = hasError || id.ContainsDiagnostics;
                        ids.Add(idExpression);

                        if (this.CurrentToken.Kind != SyntaxKind.CommaToken)
                        {
                            break;
                        }

                        ids.AddSeparator(this.EatToken());
                    }

                    var end = this.ParseEndOfDirective(hasError || !isActive, afterPragma: true);
                    return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, ids.ToList(), end, isActive);
                }
                else
                {
                    style = this.EatToken(SyntaxKind.DisableKeyword, ErrorCode.WRN_IllegalPPWarning, reportError: isActive);
                    var end = this.ParseEndOfDirective(ignoreErrors: true, afterPragma: true);
                    return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, default(SeparatedSyntaxList<ExpressionSyntax>), end, isActive);
                }
            }
            else if (this.CurrentToken.Kind == SyntaxKind.ChecksumKeyword)
            {
                var checksum = this.EatToken();
                var file = this.EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, reportError: isActive);
                var guid = this.EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, reportError: isActive && !file.IsMissing);
                if (isActive && !guid.IsMissing)
                {
                    Guid tmp;
                    if (!Guid.TryParse(guid.ValueText, out tmp))
                    {
                        guid = this.AddError(guid, ErrorCode.WRN_IllegalPPChecksum);
                    }
                }

                var bytes = this.EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, reportError: isActive && !guid.IsMissing);
                if (isActive && !bytes.IsMissing)
                {
                    if (bytes.ValueText.Length % 2 != 0)
                    {
                        bytes = this.AddError(bytes, ErrorCode.WRN_IllegalPPChecksum);
                    }
                    else
                    {
                        foreach (char c in bytes.ValueText)
                        {
                            if (!SyntaxFacts.IsHexDigit(c))
                            {
                                bytes = this.AddError(bytes, ErrorCode.WRN_IllegalPPChecksum);
                                break;
                            }
                        }
                    }
                }

                hasError = file.ContainsDiagnostics | guid.ContainsDiagnostics | bytes.ContainsDiagnostics;
                var eod = this.ParseEndOfDirective(ignoreErrors: hasError, afterPragma: true);
                return SyntaxFactory.PragmaChecksumDirectiveTrivia(hash, pragma, checksum, file, guid, bytes, eod, isActive);
            }
            else
            {
                var warning = this.EatToken(SyntaxKind.WarningKeyword, ErrorCode.WRN_IllegalPragma, reportError: isActive);
                var style = this.EatToken(SyntaxKind.DisableKeyword, reportError: false);
                var eod = this.ParseEndOfDirective(ignoreErrors: true, afterPragma: true);
                return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, default(SeparatedSyntaxList<ExpressionSyntax>), eod, isActive);
            }
        }
Example #4
0
        private DirectiveTriviaSyntax ParsePragmaDirective(SyntaxToken hash, SyntaxToken pragma, bool isActive)
        {
            pragma = CheckFeatureAvailability(pragma, MessageID.IDS_FeaturePragma);

            bool hasError = false;
            if (this.CurrentToken.ContextualKind == SyntaxKind.WarningKeyword)
            {
                var warning = this.EatContextualToken(SyntaxKind.WarningKeyword);
                SyntaxToken style;
                if (this.CurrentToken.Kind == SyntaxKind.DisableKeyword || this.CurrentToken.Kind == SyntaxKind.RestoreKeyword)
                {
                    style = this.EatToken();
                    var ids = new SeparatedSyntaxListBuilder<ExpressionSyntax>(10);
                    while (this.CurrentToken.Kind != SyntaxKind.EndOfDirectiveToken)
                    {
                        SyntaxToken id;
                        ExpressionSyntax idExpression;

                        if (this.CurrentToken.Kind == SyntaxKind.NumericLiteralToken || this.CurrentToken.Kind == SyntaxKind.StringLiteralToken)
                        {
                            id = this.EatToken();
                            if (isActive)
                            {
                                if (id.Kind == SyntaxKind.NumericLiteralToken)
                                {
                                    int compilerWarningNumber = (int)id.Value;
                                    if (ErrorFacts.GetSeverity((ErrorCode)compilerWarningNumber) != DiagnosticSeverity.Warning)
                                    {
                                        id = this.AddError(id, ErrorCode.WRN_BadWarningNumber, compilerWarningNumber);
                                    }
                                }
                                else
                                {
                                    string value = (string)id.Value;
                                    var messageProvider = MessageProvider.Instance;
                                    if (string.IsNullOrWhiteSpace(value))
                                    {
                                        id = this.AddError(id, ErrorCode.WRN_BadWarningNumber, value);
                                    }
                                    else if (value.StartsWith(messageProvider.CodePrefix))
                                    {
                                        // For diagnostic IDs of the form "CS[0-9]*", verify the error code is that of a warning
                                        int compilerWarningNumber;
                                        if (int.TryParse(value.Substring(messageProvider.CodePrefix.Length), NumberStyles.None, CultureInfo.InvariantCulture, out compilerWarningNumber) &&
                                            (messageProvider.GetIdForErrorCode(compilerWarningNumber) != value ||
                                            ErrorFacts.GetSeverity((ErrorCode)compilerWarningNumber) != DiagnosticSeverity.Warning))
                                        {
                                            id = this.AddError(id, ErrorCode.WRN_BadWarningNumber, value);
                                        }
                                    }
                                }
                            }

                            var expressionKind = id.Kind == SyntaxKind.NumericLiteralToken ? SyntaxKind.NumericLiteralExpression : SyntaxKind.StringLiteralExpression;
                            idExpression = SyntaxFactory.LiteralExpression(expressionKind, id);
                        }
                        else
                        {
                            id = this.EatToken(SyntaxKind.NumericLiteralToken, ErrorCode.WRN_StringOrNumericLiteralExpected, reportError: isActive);
                            idExpression = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, id);
                        }

                        hasError = hasError || id.ContainsDiagnostics;
                        ids.Add(idExpression);

                        if (this.CurrentToken.Kind != SyntaxKind.CommaToken)
                        {
                            break;
                        }

                        ids.AddSeparator(this.EatToken());
                    }

                    var end = this.ParseEndOfDirective(hasError || !isActive, afterPragma: true);
                    return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, ids.ToList(), end, isActive);
                }
                else
                {
                    style = this.EatToken(SyntaxKind.DisableKeyword, ErrorCode.WRN_IllegalPPWarning, reportError: isActive);
                    var end = this.ParseEndOfDirective(ignoreErrors: true, afterPragma: true);
                    return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, default(SeparatedSyntaxList<ExpressionSyntax>), end, isActive);
                }
            }
            else if (this.CurrentToken.Kind == SyntaxKind.ChecksumKeyword)
            {
                var checksum = this.EatToken();
                var file = this.EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, reportError: isActive);
                var guid = this.EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, reportError: isActive && !file.IsMissing);
                if (isActive && !guid.IsMissing)
                {
                    Guid tmp;
                    if (!Guid.TryParse(guid.ValueText, out tmp))
                    {
                        guid = this.AddError(guid, ErrorCode.WRN_IllegalPPChecksum);
                    }
                }

                var bytes = this.EatToken(SyntaxKind.StringLiteralToken, ErrorCode.WRN_IllegalPPChecksum, reportError: isActive && !guid.IsMissing);
                if (isActive && !bytes.IsMissing)
                {
                    if (bytes.ValueText.Length % 2 != 0)
                    {
                        bytes = this.AddError(bytes, ErrorCode.WRN_IllegalPPChecksum);
                    }
                    else
                    {
                        foreach (char c in bytes.ValueText)
                        {
                            if (!SyntaxFacts.IsHexDigit(c))
                            {
                                bytes = this.AddError(bytes, ErrorCode.WRN_IllegalPPChecksum);
                                break;
                            }
                        }
                    }
                }

                hasError = file.ContainsDiagnostics | guid.ContainsDiagnostics | bytes.ContainsDiagnostics;
                var eod = this.ParseEndOfDirective(ignoreErrors: hasError, afterPragma: true);
                return SyntaxFactory.PragmaChecksumDirectiveTrivia(hash, pragma, checksum, file, guid, bytes, eod, isActive);
            }
            else
            {
                var warning = this.EatToken(SyntaxKind.WarningKeyword, ErrorCode.WRN_IllegalPragma, reportError: isActive);
                var style = this.EatToken(SyntaxKind.DisableKeyword, reportError: false);
                var eod = this.ParseEndOfDirective(ignoreErrors: true, afterPragma: true);
                return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, default(SeparatedSyntaxList<ExpressionSyntax>), eod, isActive);
            }
        }
Example #5
0
        private DirectiveTriviaSyntax ParsePragmaDirective(SyntaxToken hash, SyntaxToken pragma, bool isActive)
        {
            pragma = CheckFeatureAvailability(pragma, MessageID.IDS_FeaturePragma);

            bool hasError = false;

            if (this.CurrentToken.ContextualKind == SyntaxKind.WarningKeyword)
            {
                var         warning = this.EatContextualToken(SyntaxKind.WarningKeyword);
                SyntaxToken style;
                if (this.CurrentToken.Kind == SyntaxKind.DisableKeyword || this.CurrentToken.Kind == SyntaxKind.RestoreKeyword ||
                    this.CurrentToken.Kind == SyntaxKind.EnableKeyword || this.CurrentToken.Kind == SyntaxKind.SafeOnlyKeyword)
                {
                    style = this.EatToken();

                    if (isActive && (style.Kind == SyntaxKind.EnableKeyword || style.Kind == SyntaxKind.SafeOnlyKeyword))
                    {
                        style = CheckFeatureAvailability(style, MessageID.IDS_FeaturePragmaWarningEnableOrSafeOnly, forceWarning: true);
                    }

                    if (this.CurrentToken.ContextualKind == SyntaxKind.NullableKeyword)
                    {
                        SyntaxToken nullable = this.EatContextualToken(SyntaxKind.NullableKeyword);
                        var         end      = this.ParseEndOfDirective(hasError || !isActive, afterPragma: true);
                        return(SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, nullableKeyword: nullable, default(SeparatedSyntaxList <ExpressionSyntax>), end, isActive));
                    }
                    else if (style.Kind == SyntaxKind.SafeOnlyKeyword)
                    {
                        SyntaxToken nullable = this.EatToken(SyntaxKind.NullableKeyword, ErrorCode.WRN_IllegalPPWarningSafeOnly, reportError: isActive);
                        var         end      = this.ParseEndOfDirective(ignoreErrors: true, afterPragma: true);
                        return(SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, nullableKeyword: nullable, default(SeparatedSyntaxList <ExpressionSyntax>), end, isActive));
                    }
                    else
                    {
                        var ids = new SeparatedSyntaxListBuilder <ExpressionSyntax>(10);
                        while (this.CurrentToken.Kind != SyntaxKind.EndOfDirectiveToken)
                        {
                            SyntaxToken      id;
                            ExpressionSyntax idExpression;

                            if (this.CurrentToken.Kind == SyntaxKind.NumericLiteralToken)
                            {
                                // Previous versions of the compiler used to report a warning (CS1691)
                                // whenever an unrecognized warning code was supplied in a #pragma directive
                                // (or via /nowarn /warnaserror flags on the command line).
                                // Going forward, we won't generate any warning in such cases. This will make
                                // maintenance of backwards compatibility easier (we no longer need to worry
                                // about breaking existing projects / command lines if we deprecate / remove
                                // an old warning code).
                                id           = this.EatToken();
                                idExpression = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, id);
                            }
                            else if (this.CurrentToken.Kind == SyntaxKind.IdentifierToken)
                            {
                                // Lexing / parsing of identifiers inside #pragma warning directives is identical
                                // to that inside #define directives except that very long identifiers inside #define
                                // are truncated to 128 characters to maintain backwards compatibility with previous
                                // versions of the compiler. (See TruncateIdentifier() below.)
                                // Since support for identifiers inside #pragma warning directives is new,
                                // we don't have any backwards compatibility constraints. So we can preserve the
                                // identifier exactly as it appears in source.
                                id           = this.EatToken();
                                idExpression = SyntaxFactory.IdentifierName(id);
                            }
                            else
                            {
                                id           = this.EatToken(SyntaxKind.NumericLiteralToken, ErrorCode.WRN_IdentifierOrNumericLiteralExpected, reportError: isActive);
                                idExpression = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, id);
                            }

                            hasError = hasError || id.ContainsDiagnostics;
                            ids.Add(idExpression);

                            if (this.CurrentToken.Kind != SyntaxKind.CommaToken)
                            {
                                break;
                            }

                            ids.AddSeparator(this.EatToken());
                        }

                        var end = this.ParseEndOfDirective(hasError || !isActive, afterPragma: true);
                        return(SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, nullableKeyword: default, ids.ToList(), end, isActive));