public static OperatorPrecedence GetOperatorPrecedence(this PatternSyntax pattern)
        {
            switch (pattern)
            {
            case ConstantPatternSyntax _:
            case DiscardPatternSyntax _:
            case DeclarationPatternSyntax _:
            case RecursivePatternSyntax _:
            case TypePatternSyntax _:
            case VarPatternSyntax _:
                return(OperatorPrecedence.Primary);

            case UnaryPatternSyntax _:
            case RelationalPatternSyntax _:
                return(OperatorPrecedence.Unary);

            case BinaryPatternSyntax binaryPattern:
                if (binaryPattern.IsKind(SyntaxKind.AndPattern))
                {
                    return(OperatorPrecedence.ConditionalAnd);
                }

                if (binaryPattern.IsKind(SyntaxKind.OrPattern))
                {
                    return(OperatorPrecedence.ConditionalOr);
                }

                break;
            }

            Debug.Fail("Unhandled pattern type");
            return(OperatorPrecedence.None);
        }
        public static async Task <Document> SimplifyBooleanComparisonAsync(
            Document document,
            IsPatternExpressionSyntax isPattern,
            CancellationToken cancellationToken)
        {
            PatternSyntax pattern = isPattern.Pattern;

            bool isNegative;

            if (pattern is ConstantPatternSyntax constantPattern)
            {
                isNegative = constantPattern.Expression.IsKind(SyntaxKind.FalseLiteralExpression);
            }
            else
            {
                var notPattern = (UnaryPatternSyntax)pattern;

                constantPattern = (ConstantPatternSyntax)notPattern.Pattern;

                isNegative = constantPattern.Expression.IsKind(SyntaxKind.TrueLiteralExpression);
            }

            ExpressionSyntax expression    = isPattern.Expression;
            SyntaxTriviaList trailing      = expression.GetTrailingTrivia().EmptyIfWhitespace().AddRange(isPattern.GetTrailingTrivia());
            ExpressionSyntax newExpression = expression.WithTrailingTrivia(trailing);

            if (isNegative)
            {
                newExpression = LogicalNotExpression(newExpression.WithoutTrivia().Parenthesize()).WithTriviaFrom(newExpression);
            }

            return(await document.ReplaceNodeAsync(isPattern, newExpression, cancellationToken).ConfigureAwait(false));
        }
        public static PatternSyntax Parenthesize(
            this PatternSyntax pattern,
            bool includeElasticTrivia    = true,
            bool addSimplifierAnnotation = true
            )
        {
            var withoutTrivia = pattern.WithoutTrivia();
            var parenthesized = includeElasticTrivia
                ? SyntaxFactory.ParenthesizedPattern(withoutTrivia)
                : SyntaxFactory.ParenthesizedPattern(
                SyntaxFactory.Token(
                    SyntaxTriviaList.Empty,
                    SyntaxKind.OpenParenToken,
                    SyntaxTriviaList.Empty
                    ),
                withoutTrivia,
                SyntaxFactory.Token(
                    SyntaxTriviaList.Empty,
                    SyntaxKind.CloseParenToken,
                    SyntaxTriviaList.Empty
                    )
                );

            var result = parenthesized.WithTriviaFrom(pattern);

            return(addSimplifierAnnotation
              ? result.WithAdditionalAnnotations(Simplifier.Annotation)
              : result);
        }
 public MatchArmSyntax(
     PatternSyntax pattern,
     ExpressionBlockSyntax expression)
 {
     Pattern    = pattern;
     Expression = expression;
 }
 public OrPatternSyntax(
     PatternSyntax leftAlternative,
     PatternSyntax rightAlternative)
 {
     LeftAlternative  = leftAlternative;
     RightAlternative = rightAlternative;
 }
        private static void AnalyzeIsPatternExpression(SyntaxNodeAnalysisContext context)
        {
            var isPattern = (IsPatternExpressionSyntax)context.Node;

            PatternSyntax pattern = isPattern.Pattern;

            if (isPattern.Pattern.IsKind(SyntaxKind.NotPattern))
            {
                var notPattern = (UnaryPatternSyntax)isPattern.Pattern;

                pattern = notPattern.Pattern;
            }

            if (pattern is ConstantPatternSyntax constantPattern)
            {
                ExpressionSyntax expression = constantPattern.Expression;

                if (expression.IsKind(SyntaxKind.TrueLiteralExpression, SyntaxKind.FalseLiteralExpression) &&
                    context.SemanticModel.GetTypeSymbol(
                        isPattern.Expression,
                        context.CancellationToken)?
                    .SpecialType == SpecialType.System_Boolean)
                {
                    DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.SimplifyBooleanComparison, isPattern);
                }
            }
        }
Beispiel #7
0
        public static Expression CreatePattern(this Context cx, PatternSyntax syntax, IExpressionParentEntity parent, int child)
        {
            switch (syntax)
            {
            case ConstantPatternSyntax constantPattern:
                return(Expression.Create(cx, constantPattern.Expression, parent, child));

            case DeclarationPatternSyntax declPattern:
                // Creates a single local variable declaration.
            {
                if (declPattern.Designation is VariableDesignationSyntax designation)
                {
                    if (cx.GetModel(syntax).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
                    {
                        var type = Type.Create(cx, symbol.GetAnnotatedType());
                        return(VariableDeclaration.Create(cx, symbol, type, declPattern.Type, cx.Create(syntax.GetLocation()), cx.Create(designation.GetLocation()), false, parent, child));
                    }
                    if (designation is DiscardDesignationSyntax)
                    {
                        return(Expressions.TypeAccess.Create(cx, declPattern.Type, parent, child));
                    }
                    throw new InternalError(designation, "Designation pattern not handled");
                }
                throw new InternalError(declPattern, "Declaration pattern not handled");
            }

            case RecursivePatternSyntax recPattern:
                return(new RecursivePattern(cx, recPattern, parent, child));

            case VarPatternSyntax varPattern:
                switch (varPattern.Designation)
                {
                case ParenthesizedVariableDesignationSyntax parDesignation:
                    return(VariableDeclaration.CreateParenthesized(cx, varPattern, parDesignation, parent, child));

                case SingleVariableDesignationSyntax varDesignation:
                    if (cx.GetModel(syntax).GetDeclaredSymbol(varDesignation) is ILocalSymbol symbol)
                    {
                        var type = Type.Create(cx, symbol.GetAnnotatedType());

                        return(VariableDeclaration.Create(cx, symbol, type, null, cx.Create(syntax.GetLocation()), cx.Create(varDesignation.GetLocation()), false, parent, child));
                    }
                    else
                    {
                        throw new InternalError(varPattern, "Unable to get the declared symbol of the var pattern designation.");
                    }

                default:
                    throw new InternalError("var pattern designation is unhandled");
                }

            case DiscardPatternSyntax dp:
                return(new Discard(cx, dp, parent, child));

            default:
                throw new InternalError(syntax, "Pattern not handled");
            }
        }
 public new void AddChildren()
 {
     base.AddChildren();
     Kind                 = Node.Kind();
     _pattern             = ((CasePatternSwitchLabelSyntax)Node).Pattern;
     _patternIsChanged    = false;
     _whenClause          = ((CasePatternSwitchLabelSyntax)Node).WhenClause;
     _whenClauseIsChanged = false;
 }
Beispiel #9
0
        private void PopulatePattern(PatternSyntax pattern, TypeSyntax optionalType, SyntaxToken varKeyword, VariableDesignationSyntax designation)
        {
            var isVar = optionalType is null;

            if (!(designation is null) && cx.GetModel(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
            {
                var type = Entities.Type.Create(cx, symbol.GetAnnotatedType());
                VariableDeclaration.Create(cx, symbol, type, optionalType, cx.Create(pattern.GetLocation()), cx.Create(designation.GetLocation()), isVar, this, 1);
            }
Beispiel #10
0
        private static Task <Document> ConvertSwitchExpressionToSwitchStatement(
            Document document,
            SwitchExpressionSyntax switchExpression,
            CancellationToken cancellationToken)
        {
            IEnumerable <SwitchSectionSyntax> sections = switchExpression.Arms.Select((arm, i) =>
            {
                SyntaxToken separator = switchExpression.Arms.GetSeparator(i);
                SyntaxToken semicolon = Token(SyntaxKind.SemicolonToken);

                if (!separator.IsMissing)
                {
                    semicolon = semicolon.WithTriviaFrom(separator);
                }

                PatternSyntax pattern = arm.Pattern;

                switch (pattern.Kind())
                {
                case SyntaxKind.ConstantPattern:
                    {
                        CaseSwitchLabelSyntax label = CaseSwitchLabel(
                            Token(SyntaxKind.CaseKeyword).WithLeadingTrivia(pattern.GetLeadingTrivia()),
                            ((ConstantPatternSyntax)pattern).Expression.WithoutLeadingTrivia(),
                            Token(SyntaxKind.ColonToken).WithTriviaFrom(arm.EqualsGreaterThanToken));

                        return(SwitchSection(label, CreateStatement(arm.Expression, semicolon)));
                    }

                case SyntaxKind.DiscardPattern:
                    {
                        DefaultSwitchLabelSyntax label = DefaultSwitchLabel(Token(SyntaxKind.DefaultKeyword), Token(SyntaxKind.ColonToken));

                        return(SwitchSection(label, CreateStatement(arm.Expression, semicolon)));
                    }

                default:
                    {
                        throw new InvalidOperationException();
                    }
                }
            });

            var returnStatement = (ReturnStatementSyntax)switchExpression.Parent;

            SwitchStatementSyntax switchStatement = SwitchStatement(
                switchExpression.SwitchKeyword.WithTriviaFrom(returnStatement.ReturnKeyword),
                OpenParenToken(),
                switchExpression.GoverningExpression,
                CloseParenToken().WithTrailingTrivia(switchExpression.SwitchKeyword.TrailingTrivia),
                switchExpression.OpenBraceToken,
                sections.ToSyntaxList(),
                switchExpression.CloseBraceToken);

            switchStatement = switchStatement.WithFormatterAnnotation();

            return(document.ReplaceNodeAsync(returnStatement, switchStatement, cancellationToken));
Beispiel #11
0
 public new void AddChildren()
 {
     base.AddChildren();
     Kind                 = Node.Kind();
     _expression          = ((IsPatternExpressionSyntax)Node).Expression;
     _expressionIsChanged = false;
     _isKeyword           = ((IsPatternExpressionSyntax)Node).IsKeyword;
     _isKeywordIsChanged  = false;
     _pattern             = ((IsPatternExpressionSyntax)Node).Pattern;
     _patternIsChanged    = false;
 }
        /// <summary>
        /// Here is the grammar being parsed:
        /// ``` antlr
        /// pattern
        ///     : declaration_pattern
        ///     | constant_pattern
        ///     | positional_pattern
        ///     | property_pattern
        ///     | discard_pattern
        ///     ;
        /// declaration_pattern
        ///     : type identifier
        ///     ;
        /// constant_pattern
        ///     : expression
        ///     ;
        /// positional_pattern
        ///     : type? '(' subpatterns? ')' property_subpattern? identifier?
        ///     ;
        /// subpatterns
        ///     : subpattern
        ///     | subpattern ',' subpatterns
        ///     ;
        /// subpattern
        ///     : pattern
        ///     | identifier ':' pattern
        ///     ;
        /// property_subpattern
        ///     : '{' subpatterns? '}'
        ///     ;
        /// property_pattern
        ///     : property_subpattern identifier?
        ///     ;
        /// discard_pattern
        ///     : '_'
        ///     ;
        /// ```
        ///
        /// Priority is the ExpressionSyntax. It might return ExpressionSyntax which might be a constant pattern such as 'case 3:'
        /// All constant expressions are converted to the constant pattern in the switch binder if it is a match statement.
        /// It is used for parsing patterns in the switch cases. It never returns constant pattern, because for a `case` we
        /// need to use a pre-pattern-matching syntax node for a constant case.
        /// </summary>
        /// <param name="whenIsKeyword">prevents the use of "when" for the identifier</param>
        /// <returns></returns>
        private CSharpSyntaxNode ParseExpressionOrPattern(bool whenIsKeyword, bool forSwitchCase, Precedence precedence)
        {
            // handle common error recovery situations during typing
            var tk = this.CurrentToken.Kind;

            switch (tk)
            {
            case SyntaxKind.CommaToken:
            case SyntaxKind.SemicolonToken:
            case SyntaxKind.CloseBraceToken:
            case SyntaxKind.CloseParenToken:
            case SyntaxKind.CloseBracketToken:
            case SyntaxKind.EqualsGreaterThanToken:
                return(this.ParseIdentifierName(ErrorCode.ERR_MissingPattern));
            }

            if (CurrentToken.ContextualKind == SyntaxKind.UnderscoreToken && !forSwitchCase)
            {
                // In a switch case, we parse `_` as an expression.
                return(_syntaxFactory.DiscardPattern(this.EatContextualToken(SyntaxKind.UnderscoreToken)));
            }

            var resetPoint = this.GetResetPoint();

            try
            {
                TypeSyntax type = null;
                if (LooksLikeTypeOfPattern(tk))
                {
                    type = this.ParseType(ParseTypeMode.DefinitePattern);
                    if (type.IsMissing || !CanTokenFollowTypeInPattern())
                    {
                        // either it is not shaped like a type, or it is a constant expression.
                        this.Reset(ref resetPoint);
                        type = null;
                    }
                }

                PatternSyntax p = ParsePatternContinued(type, precedence, whenIsKeyword);
                if (p != null)
                {
                    return((whenIsKeyword && p is ConstantPatternSyntax c) ? c.expression : (CSharpSyntaxNode)p);
                }

                this.Reset(ref resetPoint);
                return(this.ParseSubExpression(precedence));
            }
            finally
            {
                this.Release(ref resetPoint);
            }
        }
Beispiel #13
0
        private void ParseMatch(XElement match, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)
        {
            var parsedInputString = match.Attribute(RewriteTags.Url)?.Value;

            if (parsedInputString == null)
            {
                throw new InvalidUrlRewriteFormatException(match, "Match must have Url Attribute");
            }

            var ignoreCase = ParseBool(match, RewriteTags.IgnoreCase, defaultValue: true);
            var negate     = ParseBool(match, RewriteTags.Negate, defaultValue: false);

            builder.AddUrlMatch(parsedInputString, ignoreCase, negate, patternSyntax);
        }
Beispiel #14
0
        private static Task <Document> UseIsNullPatternInsteadOfComparisonAsync(
            Document document,
            BinaryExpressionSyntax binaryExpression,
            CancellationToken cancellationToken)
        {
            NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(binaryExpression, NullCheckStyles.ComparisonToNull, walkDownParentheses: false);

            ExpressionSyntax expression = nullCheck.Expression;
            ExpressionSyntax nullLiteral;

            if (object.ReferenceEquals(expression, binaryExpression.Left))
            {
                nullLiteral = binaryExpression.Right;
            }
            else
            {
                expression = expression.WithTrailingTrivia(binaryExpression.Left.GetTrailingTrivia());

                nullLiteral = binaryExpression.Left.WithLeadingTrivia(expression.GetLeadingTrivia());
            }

            bool useIsNotNull = !AnalyzerOptions.UseLogicalNegationAndPatternMatchingToCheckForNull.IsEnabled(document, binaryExpression);

            PatternSyntax pattern = ConstantPattern(nullLiteral);

            if (binaryExpression.IsKind(SyntaxKind.NotEqualsExpression) &&
                useIsNotNull)
            {
                pattern = NotPattern(pattern);
            }

            ExpressionSyntax newExpression = IsPatternExpression(
                expression,
                Token(binaryExpression.OperatorToken.LeadingTrivia, SyntaxKind.IsKeyword, binaryExpression.OperatorToken.TrailingTrivia),
                pattern);

            if (binaryExpression.IsKind(SyntaxKind.NotEqualsExpression) &&
                !useIsNotNull)
            {
                newExpression = LogicalNotExpression(ParenthesizedExpression(newExpression.WithoutTrivia()));
            }

            newExpression = newExpression
                            .WithTriviaFrom(binaryExpression)
                            .WithFormatterAnnotation();

            return(document.ReplaceNodeAsync(binaryExpression, newExpression, cancellationToken));
        }
        private static bool RemovalChangesAssociation(
            ParenthesizedPatternSyntax node, PatternSyntax parentPattern)
        {
            var pattern          = node.Pattern;
            var precedence       = pattern.GetOperatorPrecedence();
            var parentPrecedence = parentPattern.GetOperatorPrecedence();

            if (precedence == OperatorPrecedence.None || parentPrecedence == OperatorPrecedence.None)
            {
                // Be conservative if the expression or its parent has no precedence.
                return(true);
            }

            // Association always changes if the expression's precedence is lower that its parent.
            return(precedence < parentPrecedence);
        }
        public static string ToJsonModel(PatternSyntax patternSyntax)
        {
            switch (patternSyntax)
            {
            case PatternSyntax.ECMAScript:
                return("regular_expression");

            case PatternSyntax.Wildcard:
                return("wildcard");

            case PatternSyntax.ExactMatch:
                return("exact_match");

            default:
                throw new ArgumentException(nameof(patternSyntax));
            }
        }
Beispiel #17
0
        internal BoundPattern BindPattern(
            PatternSyntax node,
            TypeSymbol operandType,
            bool hasErrors,
            DiagnosticBag diagnostics)
        {
            switch (node.Kind())
            {
            case SyntaxKind.DeclarationPattern:
                return(BindDeclarationPattern(
                           (DeclarationPatternSyntax)node, operandType, hasErrors, diagnostics));

            case SyntaxKind.ConstantPattern:
                var constantPattern = (ConstantPatternSyntax)node;
                return(BindConstantPattern(
                           constantPattern, operandType, constantPattern.Expression, hasErrors, diagnostics, out bool wasExpression));

            default:
                throw ExceptionUtilities.UnexpectedValue(node.Kind());
            }
        }
Beispiel #18
0
        private void PopulatePattern(PatternSyntax pattern, TypeSyntax optionalType, SyntaxToken varKeyword, VariableDesignationSyntax designation)
        {
            bool isVar = optionalType is null;

            if (!isVar)
            {
                Expressions.TypeAccess.Create(cx, optionalType, this, 1);
            }

            if (!(designation is null) && cx.Model(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
            {
                var type = Type.Create(cx, symbol.Type);

                if (isVar)
                {
                    new Expression(new ExpressionInfo(cx, type, cx.Create(varKeyword.GetLocation()), ExprKind.TYPE_ACCESS, this, 1, false, null));
                }

                VariableDeclaration.Create(cx, symbol, type, cx.Create(pattern.GetLocation()), cx.Create(designation.GetLocation()), isVar, this, 2);
            }
        }
Beispiel #19
0
        internal BoundPattern BindPattern(
            PatternSyntax node,
            TypeSymbol operandType,
            bool hasErrors,
            DiagnosticBag diagnostics,
            bool wasSwitchCase = false)
        {
            switch (node.Kind())
            {
            case SyntaxKind.DeclarationPattern:
                return(BindDeclarationPattern(
                           (DeclarationPatternSyntax)node, operandType, hasErrors, diagnostics));

            case SyntaxKind.ConstantPattern:
                return(BindConstantPattern(
                           (ConstantPatternSyntax)node, operandType, hasErrors, diagnostics, wasSwitchCase));

            default:
                throw ExceptionUtilities.UnexpectedValue(node.Kind());
            }
        }
Beispiel #20
0
        private void PopulatePattern(PatternSyntax pattern, TypeSyntax optionalType, SyntaxToken varKeyword, VariableDesignationSyntax designation)
        {
            var isVar = optionalType is null;

            if (!isVar)
            {
                Expressions.TypeAccess.Create(cx, optionalType, this, 1);
            }

            switch (designation)
            {
            case SingleVariableDesignationSyntax _:
                if (cx.Model(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
                {
                    var type = Type.Create(cx, symbol.Type);

                    if (isVar)
                    {
                        new Expression(new ExpressionInfo(cx, type, cx.Create(varKeyword.GetLocation()), ExprKind.TYPE_ACCESS, this, 1, false, null));
                    }

                    Expressions.VariableDeclaration.Create(cx, symbol, type, cx.Create(pattern.GetLocation()), cx.Create(designation.GetLocation()), isVar, this, 0);
                }
                break;

            case DiscardDesignationSyntax discard:
                new Expressions.Discard(cx, discard, this, 0);
                break;

            case null:
                break;

            case ParenthesizedVariableDesignationSyntax paren:
                Expressions.VariableDeclaration.CreateParenthesized(cx, (VarPatternSyntax)pattern, paren, this, 0);
                break;

            default:
                throw new InternalError(pattern, "Unhandled designation in case statement");
            }
        }
Beispiel #21
0
        internal BoundPattern BindPattern(
            PatternSyntax node,
            BoundExpression operand,
            TypeSymbol operandType,
            bool hasErrors,
            DiagnosticBag diagnostics,
            bool wasSwitchCase = false)
        {
            switch (node.Kind())
            {
                case SyntaxKind.DeclarationPattern:
                    return BindDeclarationPattern(
                        (DeclarationPatternSyntax)node, operand, operandType, hasErrors, diagnostics);

                case SyntaxKind.ConstantPattern:
                    return BindConstantPattern(
                        (ConstantPatternSyntax)node, operand, operandType, hasErrors, diagnostics, wasSwitchCase);

                default:
                    throw ExceptionUtilities.UnexpectedValue(node.Kind());
            }
        }
Beispiel #22
0
    private void ParseConditions(XElement?conditions, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)
    {
        if (conditions == null)
        {
            return;
        }

        var grouping         = ParseEnum(conditions, RewriteTags.LogicalGrouping, LogicalGrouping.MatchAll);
        var trackAllCaptures = ParseBool(conditions, RewriteTags.TrackAllCaptures, defaultValue: false);
        var adds             = conditions.Elements(RewriteTags.Add);

        if (!adds.Any())
        {
            return;
        }

        builder.ConfigureConditionBehavior(grouping, trackAllCaptures);

        foreach (var cond in adds)
        {
            ParseCondition(cond, builder, patternSyntax);
        }
    }
Beispiel #23
0
        public static ITypeSymbol GetMatchedTypeSymbol(
            this PatternSyntax pattern,
            SyntaxNodeAnalysisContext context,
            ITypeSymbol type,
            HashSet <ITypeSymbol> allCases,
            bool isClosed)
        {
            ITypeSymbol symbolUsed;

            switch (pattern)
            {
            case DeclarationPatternSyntax declarationPattern:
                symbolUsed = context.GetDeclarationType(declarationPattern);
                break;

            case DiscardPatternSyntax _:
            case ConstantPatternSyntax constantPattern
                when constantPattern.IsNull():
                // Ignored
                return(null);

            case VarPatternSyntax _:
            case RecursivePatternSyntax _:
            default:
                context.ReportCasePatternNotSupported(pattern);
                return(null);
            }

            if (isClosed && !allCases.Contains(symbolUsed))
            {
                var diagnostic = Diagnostic.Create(ExhaustiveMatchAnalyzer.MatchMustBeOnCaseType,
                                                   pattern.GetLocation(), symbolUsed.GetFullName(), type.GetFullName());
                context.ReportDiagnostic(diagnostic);
            }

            return(symbolUsed);
        }
 // Creates a rule with appropriate default values of the url rewrite rule.
 private IISUrlRewriteRule CreateTestRule(ConditionCollection conditions,
                                          string name  = "",
                                          bool enabled = true,
                                          PatternSyntax patternSyntax = PatternSyntax.ECMAScript,
                                          bool stopProcessing         = false,
                                          string url                = "",
                                          bool ignoreCase           = true,
                                          bool negate               = false,
                                          ActionType actionType     = ActionType.None,
                                          string pattern            = "",
                                          bool appendQueryString    = false,
                                          bool rewrittenUrl         = false,
                                          bool global               = false,
                                          UriMatchPart uriMatchPart = UriMatchPart.Path,
                                          RedirectType redirectType = RedirectType.Permanent
                                          )
 {
     return(new IISUrlRewriteRule(
                name,
                new RegexMatch(new Regex("^OFF$"), negate),
                conditions,
                new RewriteAction(RuleResult.ContinueRules, new InputParser().ParseInputString(url, uriMatchPart), queryStringAppend: false),
                global));
 }
Beispiel #25
0
        private void PopulatePattern(PatternSyntax pattern, TypeSyntax optionalType, VariableDesignationSyntax designation)
        {
            var isVar = optionalType is null;

            switch (designation)
            {
            case SingleVariableDesignationSyntax _:
                if (cx.Model(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
                {
                    var type = Type.Create(cx, symbol.GetAnnotatedType());
                    Expressions.VariableDeclaration.Create(cx, symbol, type, optionalType, cx.Create(pattern.GetLocation()), cx.Create(designation.GetLocation()), isVar, this, 0);
                }
                break;

            case DiscardDesignationSyntax discard:
                if (isVar)
                {
                    new Expressions.Discard(cx, discard, this, 0);
                }
                else
                {
                    Expressions.TypeAccess.Create(cx, optionalType, this, 0);
                }
                break;

            case null:
                break;

            case ParenthesizedVariableDesignationSyntax paren:
                Expressions.VariableDeclaration.CreateParenthesized(cx, (VarPatternSyntax)pattern, paren, this, 0);
                break;

            default:
                throw new InternalError(pattern, "Unhandled designation in case statement");
            }
        }
    public void AddUrlMatch(string input, bool ignoreCase = true, bool negate = false, PatternSyntax patternSyntax = PatternSyntax.ECMAScript)
    {
        switch (patternSyntax)
        {
        case PatternSyntax.ECMAScript:
        {
            if (ignoreCase)
            {
                var regex = new Regex(input, RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase, _regexTimeout);
                _initialMatch = new RegexMatch(regex, negate);
            }
            else
            {
                var regex = new Regex(input, RegexOptions.CultureInvariant | RegexOptions.Compiled, _regexTimeout);
                _initialMatch = new RegexMatch(regex, negate);
            }
            break;
        }

        case PatternSyntax.Wildcard:
            throw new NotSupportedException("Wildcard syntax is not supported");

        case PatternSyntax.ExactMatch:
            _initialMatch = new ExactMatch(ignoreCase, input, negate);
            break;
        }
    }
Beispiel #27
0
        private void ParseCondition(XElement conditionElement, UrlRewriteRuleBuilder builder, PatternSyntax patternSyntax)
        {
            var ignoreCase        = ParseBool(conditionElement, RewriteTags.IgnoreCase, defaultValue: true);
            var negate            = ParseBool(conditionElement, RewriteTags.Negate, defaultValue: false);
            var matchType         = ParseEnum(conditionElement, RewriteTags.MatchType, MatchType.Pattern);
            var parsedInputString = conditionElement.Attribute(RewriteTags.Input)?.Value;

            if (parsedInputString == null)
            {
                throw new InvalidUrlRewriteFormatException(conditionElement, "Conditions must have an input attribute");
            }

            var       parsedPatternString = conditionElement.Attribute(RewriteTags.Pattern)?.Value;
            Condition condition;

            switch (patternSyntax)
            {
            case PatternSyntax.ECMAScript:
            {
                switch (matchType)
                {
                case MatchType.Pattern:
                {
                    if (string.IsNullOrEmpty(parsedPatternString))
                    {
                        throw new FormatException("Match does not have an associated pattern attribute in condition");
                    }
                    condition = new UriMatchCondition(_inputParser, parsedInputString, parsedPatternString, builder.UriMatchPart, ignoreCase, negate);
                    break;
                }

                case MatchType.IsDirectory:
                {
                    condition = new Condition {
                        Input = _inputParser.ParseInputString(parsedInputString, builder.UriMatchPart), Match = new IsDirectoryMatch(negate)
                    };
                    break;
                }

                case MatchType.IsFile:
                {
                    condition = new Condition {
                        Input = _inputParser.ParseInputString(parsedInputString, builder.UriMatchPart), Match = new IsFileMatch(negate)
                    };
                    break;
                }

                default:
                    throw new FormatException("Unrecognized matchType");
                }
                break;
            }

            case PatternSyntax.Wildcard:
                throw new NotSupportedException("Wildcard syntax is not supported");

            case PatternSyntax.ExactMatch:
                if (string.IsNullOrEmpty(parsedPatternString))
                {
                    throw new FormatException("Match does not have an associated pattern attribute in condition");
                }
                condition = new Condition {
                    Input = _inputParser.ParseInputString(parsedInputString, builder.UriMatchPart), Match = new ExactMatch(ignoreCase, parsedPatternString, negate)
                };
                break;

            default:
                throw new FormatException("Unrecognized pattern syntax");
            }

            builder.AddUrlCondition(condition);
        }
Beispiel #28
0
        private static Task <Document> ConvertSwitchExpressionToSwitchStatement(
            Document document,
            SwitchExpressionSyntax switchExpression,
            CancellationToken cancellationToken)
        {
            SeparatedSyntaxList <SwitchExpressionArmSyntax> arms = switchExpression.Arms;

            SyntaxToken[] separators = arms.GetSeparators().ToArray();

            IEnumerable <SwitchSectionSyntax> sections = arms.Select((arm, i) =>
            {
                PatternSyntax pattern       = arm.Pattern;
                ExpressionSyntax expression = arm.Expression;
                SyntaxToken semicolon       = Token(SyntaxKind.SemicolonToken);
                SyntaxToken separator       = default;

                if (i < separators.Length)
                {
                    separator = separators[i];
                }

                if (separator.IsKind(SyntaxKind.None) ||
                    separator.IsMissing)
                {
                    semicolon  = semicolon.WithTrailingTrivia(arm.GetTrailingTrivia());
                    expression = expression.WithoutTrailingTrivia();
                }
                else
                {
                    semicolon = semicolon.WithTriviaFrom(separator);
                }

                SyntaxKind kind         = pattern.Kind();
                SwitchLabelSyntax label = default;

                if (kind == SyntaxKind.ConstantPattern)
                {
                    label = CaseSwitchLabel(
                        Token(SyntaxKind.CaseKeyword).WithLeadingTrivia(pattern.GetLeadingTrivia()),
                        ((ConstantPatternSyntax)pattern).Expression.WithoutLeadingTrivia(),
                        Token(SyntaxKind.ColonToken).WithTriviaFrom(arm.EqualsGreaterThanToken));
                }
                else if (kind == SyntaxKind.DiscardPattern)
                {
                    label = DefaultSwitchLabel(Token(SyntaxKind.DefaultKeyword), Token(SyntaxKind.ColonToken));
                }
                else
                {
                    throw new InvalidOperationException();
                }

                StatementSyntax statement = CreateStatement(expression, semicolon);

                return(SwitchSection(label, statement));
            });

            var returnStatement = (ReturnStatementSyntax)switchExpression.Parent;

            SwitchStatementSyntax switchStatement = SwitchStatement(
                switchExpression.SwitchKeyword.WithTriviaFrom(returnStatement.ReturnKeyword),
                OpenParenToken(),
                switchExpression.GoverningExpression,
                CloseParenToken().WithTrailingTrivia(switchExpression.SwitchKeyword.TrailingTrivia),
                switchExpression.OpenBraceToken,
                sections.ToSyntaxList(),
                switchExpression.CloseBraceToken);

            switchStatement = switchStatement.WithFormatterAnnotation();

            return(document.ReplaceNodeAsync(returnStatement, switchStatement, cancellationToken));
 private IEnumerable<TypeInferenceInfo> GetPatternTypes(PatternSyntax pattern)
 {
     switch (pattern)
     {
         case DeclarationPatternSyntax declarationPattern: return GetTypes(declarationPattern.Type);
         case ConstantPatternSyntax constantPattern: return GetTypes(constantPattern.Expression);
         default: return null;
     }
 }
        private CSharpSyntaxNode ParseTypeOrPatternForIsOperatorCore()
        {
            var        tk         = this.CurrentToken.Kind;
            Precedence precedence = GetPrecedence(SyntaxKind.IsPatternExpression);

            // We will parse a shift-expression ONLY (nothing looser) - i.e. not a relational expression
            // So x is y < z should be parsed as (x is y) < z
            // But x is y << z should be parsed as x is (y << z)
            Debug.Assert(Precedence.Shift == precedence + 1);

            // For totally broken syntax, parse a type for error recovery purposes
            switch (tk)
            {
            case SyntaxKind.IdentifierToken when this.CurrentToken.ContextualKind == SyntaxKind.UnderscoreToken:
            // We permit a type named `_` on the right-hand-side of an is operator, but not inside of a pattern.
            case SyntaxKind.CloseParenToken:
            case SyntaxKind.CloseBracketToken:
            case SyntaxKind.CloseBraceToken:
            case SyntaxKind.SemicolonToken:
            case SyntaxKind.CommaToken:
                // HACK: for error recovery, we prefer a (missing) type.
                return(this.ParseType(ParseTypeMode.AfterIs));

            default:
                // attempt to disambiguate.
                break;
            }

            // If it starts with 'nameof(', skip the 'if' and parse as a constant pattern.
            if (LooksLikeTypeOfPattern(tk))
            {
                var resetPoint = this.GetResetPoint();
                try
                {
                    TypeSyntax type = this.ParseType(ParseTypeMode.AfterIs);

                    if (!type.IsMissing)
                    {
                        PatternSyntax p = ParsePatternContinued(type, precedence, whenIsKeyword: false);
                        if (p != null)
                        {
                            return(p);
                        }
                    }

                    tk = this.CurrentToken.ContextualKind;
                    if ((!IsExpectedBinaryOperator(tk) || GetPrecedence(SyntaxFacts.GetBinaryExpression(tk)) <= precedence) &&
                        // member selection is not formally a binary operator but has higher precedence than relational
                        tk != SyntaxKind.DotToken)
                    {
                        // it is a typical "is Type" operator.
                        // Note that we don't bother checking for primary expressions such as X[e], X(e), X++, and X--
                        // as those are never semantically valid constant expressions for a pattern
                        return(type);
                    }

                    this.Reset(ref resetPoint);
                }
                finally
                {
                    this.Release(ref resetPoint);
                }
            }

            // check to see if it looks like a recursive pattern.
            if (tk == SyntaxKind.OpenParenToken || tk == SyntaxKind.OpenBraceToken)
            {
                var resetPoint = this.GetResetPoint();
                try
                {
                    PatternSyntax p = ParsePatternContinued(type: null, precedence, whenIsKeyword: false);
                    if (p != null)
                    {
                        return(p);
                    }

                    // this can occur when we encounter a misplaced lambda expression.
                    this.Reset(ref resetPoint);
                }
                finally
                {
                    this.Release(ref resetPoint);
                }
            }

            // In places where a pattern is supported, we do not support tuple types
            // due to both syntactic and semantic ambiguities between tuple types and positional patterns.
            // But it still might be a pattern such as (operand is 3) or (operand is nameof(x))
            return(_syntaxFactory.ConstantPattern(this.ParseSubExpressionCore(precedence)));
        }
 private IEnumerable<TypeInferenceInfo> GetPatternTypes(PatternSyntax pattern)
 {
     return pattern.TypeSwitch(
         (DeclarationPatternSyntax declarationPattern) => GetTypes(declarationPattern.Type),
         (ConstantPatternSyntax constantPattern) => GetTypes(constantPattern.Expression));
 }
Beispiel #32
0
 public Source(PatternSyntax patternSyntax, IOperation target) : base(target)
     => PatternSyntax = patternSyntax;
Beispiel #33
0
 public static bool IsNull(this PatternSyntax pattern)
 {
     return(pattern is ConstantPatternSyntax constantPattern &&
            constantPattern.Expression.IsNullLiteral());
 }