예제 #1
0
        private DirectiveTriviaSyntax ParsePragmaDirective(SyntaxToken hash, SyntaxToken pragma, bool isActive)
        {
            if (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));