Exemple #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)
                {
                    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
                            // 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, 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);
            }
        }
        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));
            }
        }