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); } } }
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; }
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); }
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));
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); } }
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); }
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)); } }
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()); } }
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); } }
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()); } }
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"); } }
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()); } }
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); } }
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)); }
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; } }
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); }
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)); }
public Source(PatternSyntax patternSyntax, IOperation target) : base(target) => PatternSyntax = patternSyntax;
public static bool IsNull(this PatternSyntax pattern) { return(pattern is ConstantPatternSyntax constantPattern && constantPattern.Expression.IsNullLiteral()); }