public static void AnalyzeSwitchSection(SyntaxNodeAnalysisContext context)
        {
            var switchSection = (SwitchSectionSyntax)context.Node;

            SyntaxList <SwitchLabelSyntax> labels = switchSection.Labels;

            int count = labels.Count;

            if (count <= 1)
            {
                return;
            }

            SwitchLabelSyntax lastLabel = labels.Last();

            for (int i = 0; i < count - 1; i++)
            {
                SwitchLabelSyntax label = labels[i];

                if (label.Kind() == SyntaxKind.DefaultSwitchLabel)
                {
                    TextSpan span = TextSpan.FromBounds(label.Span.End, lastLabel.SpanStart);

                    if (!switchSection.ContainsDirectives(span))
                    {
                        context.ReportDiagnostic(
                            DiagnosticDescriptors.DefaultLabelShouldBeLastLabelInSwitchSection,
                            label);

                        break;
                    }
                }
            }
        }
Esempio n. 2
0
        private static bool IsDefaultLabel(SyntaxNodeAnalysisContext context, SwitchLabelSyntax switchLabel)
        {
            switch (switchLabel.Kind())
            {
            case SyntaxKind.DefaultSwitchLabel:
                return(true);

            case SyntaxKind.CasePatternSwitchLabel:
            {
                var casePatternSwitchLabel = (CasePatternSwitchLabelSyntax)switchLabel;

                var condition = casePatternSwitchLabel.WhenClause?.Condition;
                if (condition != null)
                {
                    var constantValue = context.SemanticModel.GetConstantValue(condition, context.CancellationToken);
                    return(constantValue.HasValue &&
                           constantValue.Value is bool boolValue &&
                           boolValue);
                }

                return(casePatternSwitchLabel.Pattern.IsKind(SyntaxKind.VarPattern));
            }

            default:
                return(false);
            }
        }
Esempio n. 3
0
        public static Statement Create(Context cx, SwitchLabelSyntax node, Switch parent, int child)
        {
            switch (node.Kind())
            {
            case SyntaxKind.CaseSwitchLabel:
                return(CaseLabel.Create(cx, (CaseSwitchLabelSyntax)node, parent, child));

            case SyntaxKind.DefaultSwitchLabel:
                return(CaseDefault.Create(cx, (DefaultSwitchLabelSyntax)node, parent, child));

            case SyntaxKind.CasePatternSwitchLabel:
                return(CasePattern.Create(cx, (CasePatternSwitchLabelSyntax)node, parent, child));

            default:
                throw new InternalError(node, $"Unhandled case label of kind {node.Kind()}");
            }
        }
Esempio n. 4
0
        private BoundPatternSwitchLabel BindPatternSwitchSectionLabel(
            Binder sectionBinder, BoundExpression boundSwitchExpression, SwitchLabelSyntax node, LabelSymbol label, ref BoundPatternSwitchLabel defaultLabel, DiagnosticBag diagnostics)
        {
            switch (node.Kind())
            {
            case SyntaxKind.CaseSwitchLabel:
            {
                var  caseLabelSyntax = (CaseSwitchLabelSyntax)node;
                bool wasExpression;
                var  pattern = sectionBinder.BindConstantPattern(
                    node, boundSwitchExpression, boundSwitchExpression.Type, caseLabelSyntax.Value, node.HasErrors, diagnostics, out wasExpression, wasSwitchCase: true);
                bool hasErrors     = pattern.HasErrors;
                var  constantValue = pattern.ConstantValue;
                if (!hasErrors &&
                    (object)constantValue != null &&
                    pattern.Value.Type == SwitchGoverningType &&
                    this.FindMatchingSwitchCaseLabel(constantValue, caseLabelSyntax) != label)
                {
                    diagnostics.Add(ErrorCode.ERR_DuplicateCaseLabel, node.Location, pattern.ConstantValue.GetValueToDisplay() ?? label.Name);
                    hasErrors = true;
                }
                return(new BoundPatternSwitchLabel(node, label, pattern, null, hasErrors));
            }

            case SyntaxKind.DefaultSwitchLabel:
            {
                var  defaultLabelSyntax = (DefaultSwitchLabelSyntax)node;
                var  pattern            = new BoundWildcardPattern(node);
                bool hasErrors          = pattern.HasErrors;
                if (defaultLabel != null)
                {
                    diagnostics.Add(ErrorCode.ERR_DuplicateCaseLabel, node.Location, label.Name);
                    hasErrors = true;
                }

                // Note that this is semantically last! The caller will place it in the decision tree
                // in the final position.
                defaultLabel = new BoundPatternSwitchLabel(node, label, pattern, null, hasErrors);
                return(defaultLabel);
            }

            case SyntaxKind.CasePatternSwitchLabel:
            {
                var matchLabelSyntax = (CasePatternSwitchLabelSyntax)node;
                var pattern          = sectionBinder.BindPattern(
                    matchLabelSyntax.Pattern, boundSwitchExpression, boundSwitchExpression.Type, node.HasErrors, diagnostics, wasSwitchCase: true);
                return(new BoundPatternSwitchLabel(node, label, pattern,
                                                   matchLabelSyntax.WhenClause != null ? sectionBinder.BindBooleanExpression(matchLabelSyntax.WhenClause.Condition, diagnostics) : null, node.HasErrors));
            }

            default:
                throw ExceptionUtilities.UnexpectedValue(node);
            }
        }
            private static PatternSyntax GetPattern(SwitchLabelSyntax switchLabel, out WhenClauseSyntax whenClauseOpt)
            {
                switch (switchLabel.Kind())
                {
                case SyntaxKind.CasePatternSwitchLabel:
                    var node = (CasePatternSwitchLabelSyntax)switchLabel;
                    whenClauseOpt = node.WhenClause;
                    return(node.Pattern);

                case SyntaxKind.CaseSwitchLabel:
                    whenClauseOpt = null;
                    return(ConstantPattern(((CaseSwitchLabelSyntax)switchLabel).Value));

                case SyntaxKind.DefaultSwitchLabel:
                    whenClauseOpt = null;
                    return(DiscardPattern());

                case var value:
                    throw ExceptionUtilities.UnexpectedValue(value);
                }
            }
Esempio n. 6
0
        private static BoundPatternSwitchLabel BindPatternSwitchSectionLabel(Binder sectionBinder, BoundExpression boundSwitchExpression, SwitchLabelSyntax node, ref DefaultSwitchLabelSyntax defaultLabel, DiagnosticBag diagnostics)
        {
            switch (node.Kind())
            {
                case SyntaxKind.CasePatternSwitchLabel:
                    {
                        var matchLabelSyntax = (CasePatternSwitchLabelSyntax)node;
                        var pattern = sectionBinder.BindPattern(
                            matchLabelSyntax.Pattern, boundSwitchExpression, boundSwitchExpression.Type, node.HasErrors, diagnostics, wasSwitchCase: true);
                        return new BoundPatternSwitchLabel(node, pattern,
                            matchLabelSyntax.WhenClause != null ? sectionBinder.BindBooleanExpression(matchLabelSyntax.WhenClause.Condition, diagnostics) : null, node.HasErrors);
                    }

                case SyntaxKind.CaseSwitchLabel:
                    {
                        var caseLabelSyntax = (CaseSwitchLabelSyntax)node;
                        bool wasExpression;
                        var pattern = sectionBinder.BindConstantPattern(
                            node, boundSwitchExpression, boundSwitchExpression.Type, caseLabelSyntax.Value, node.HasErrors, diagnostics, out wasExpression, wasSwitchCase: true);
                        return new BoundPatternSwitchLabel(node, pattern, null, node.HasErrors);
                    }

                case SyntaxKind.DefaultSwitchLabel:
                    {
                        var defaultLabelSyntax = (DefaultSwitchLabelSyntax)node;
                        var pattern = new BoundWildcardPattern(node);
                        if (defaultLabel != null)
                        {
                            diagnostics.Add(ErrorCode.ERR_DuplicateCaseLabel, node.Location, "default");
                        }

                        defaultLabel = defaultLabelSyntax;
                        return new BoundPatternSwitchLabel(node, pattern, null, node.HasErrors); // note that this is semantically last!
                    }

                default:
                    throw ExceptionUtilities.Unreachable;
            }
        }
        private static BoundPatternSwitchLabel BindPatternSwitchSectionLabel(Binder sectionBinder, BoundExpression boundSwitchExpression, SwitchLabelSyntax node, ref DefaultSwitchLabelSyntax defaultLabel, DiagnosticBag diagnostics)
        {
            switch (node.Kind())
            {
            case SyntaxKind.CasePatternSwitchLabel:
            {
                var matchLabelSyntax = (CasePatternSwitchLabelSyntax)node;
                var pattern          = sectionBinder.BindPattern(
                    matchLabelSyntax.Pattern, boundSwitchExpression, boundSwitchExpression.Type, node.HasErrors, diagnostics, wasSwitchCase: true);
                return(new BoundPatternSwitchLabel(node, pattern,
                                                   matchLabelSyntax.WhenClause != null ? sectionBinder.BindBooleanExpression(matchLabelSyntax.WhenClause.Condition, diagnostics) : null, node.HasErrors));
            }

            case SyntaxKind.CaseSwitchLabel:
            {
                var  caseLabelSyntax = (CaseSwitchLabelSyntax)node;
                bool wasExpression;
                var  pattern = sectionBinder.BindConstantPattern(
                    node, boundSwitchExpression, boundSwitchExpression.Type, caseLabelSyntax.Value, node.HasErrors, diagnostics, out wasExpression, wasSwitchCase: true);
                return(new BoundPatternSwitchLabel(node, pattern, null, node.HasErrors));
            }

            case SyntaxKind.DefaultSwitchLabel:
            {
                var defaultLabelSyntax = (DefaultSwitchLabelSyntax)node;
                var pattern            = new BoundWildcardPattern(node);
                if (defaultLabel != null)
                {
                    diagnostics.Add(ErrorCode.ERR_DuplicateCaseLabel, node.Location, "default");
                }

                defaultLabel = defaultLabelSyntax;
                return(new BoundPatternSwitchLabel(node, pattern, null, node.HasErrors));        // note that this is semantically last!
            }

            default:
                throw ExceptionUtilities.Unreachable;
            }
        }
Esempio n. 8
0
        private BoundSwitchLabel BindSwitchSectionLabel(SwitchLabelSyntax node, Binder sectionBinder, LabelSymbol label, DiagnosticBag diagnostics)
        {
            var switchGoverningType = SwitchGoverningType;
            BoundExpression boundLabelExpressionOpt = null;
            ConstantValue labelExpressionConstant = null;

            // Prevent cascading diagnostics
            bool hasErrors = node.HasErrors;

            switch (node.Kind())
            {
                case SyntaxKind.CaseSwitchLabel:
                    var caseLabelSyntax = (CaseSwitchLabelSyntax)node;
                    // Bind the label case expression
                    boundLabelExpressionOpt = sectionBinder.BindValue(caseLabelSyntax.Value, diagnostics, BindValueKind.RValue);
                    boundLabelExpressionOpt = ConvertCaseExpression(caseLabelSyntax, boundLabelExpressionOpt, sectionBinder, ref labelExpressionConstant, diagnostics);

                    // Check for bind errors
                    hasErrors = hasErrors || boundLabelExpressionOpt.HasAnyErrors;

                    // SPEC:    The constant expression of each case label must denote a value that
                    // SPEC:    is implicitly convertible (§6.1) to the governing type of the switch statement.
                    if (!hasErrors && labelExpressionConstant == null)
                    {
                        diagnostics.Add(ErrorCode.ERR_ConstantExpected, caseLabelSyntax.Value.Location);
                        hasErrors = true;
                    }

                    if (!hasErrors && (object)labelExpressionConstant != null && FindMatchingSwitchCaseLabel(labelExpressionConstant, caseLabelSyntax) != label)
                    {
                        diagnostics.Add(ErrorCode.ERR_DuplicateCaseLabel, node.Location, labelExpressionConstant?.GetValueToDisplay() ?? label.Name);
                        hasErrors = true;
                    }

                    // LabelSymbols for all the switch case labels are created by BuildLabels().
                    // Fetch the matching switch case label symbols
                    break;
                case SyntaxKind.CasePatternSwitchLabel:
                    if (!node.HasErrors)
                    {
                        // This should not occur, because it would have been a syntax error
                        throw ExceptionUtilities.UnexpectedValue(node.Kind());
                    }
                    break;
                case SyntaxKind.DefaultSwitchLabel:
                    if (GetDefaultLabel() != label)
                    {
                        diagnostics.Add(ErrorCode.ERR_DuplicateCaseLabel, node.Location, label.Name);
                        hasErrors = true;
                    }
                    break;
                default:
                    throw ExceptionUtilities.UnexpectedValue(node.Kind());
            }

            return new BoundSwitchLabel(
                syntax: node,
                label: label,
                expressionOpt: boundLabelExpressionOpt,
                constantValueOpt: labelExpressionConstant,
                hasErrors: hasErrors);
        }
Esempio n. 9
0
        private BoundPatternSwitchLabel BindPatternSwitchSectionLabel(
            Binder sectionBinder, BoundExpression boundSwitchExpression, SwitchLabelSyntax node, LabelSymbol label, ref BoundPatternSwitchLabel defaultLabel, DiagnosticBag diagnostics)
        {
            switch (node.Kind())
            {
                case SyntaxKind.CaseSwitchLabel:
                    {
                        var caseLabelSyntax = (CaseSwitchLabelSyntax)node;
                        bool wasExpression;
                        var pattern = sectionBinder.BindConstantPattern(
                            node, boundSwitchExpression, boundSwitchExpression.Type, caseLabelSyntax.Value, node.HasErrors, diagnostics, out wasExpression, wasSwitchCase: true);
                        bool hasErrors = pattern.HasErrors;
                        var constantValue = pattern.ConstantValue;
                        if (!hasErrors &&
                            (object)constantValue != null &&
                            pattern.Value.Type == SwitchGoverningType &&
                            this.FindMatchingSwitchCaseLabel(constantValue, caseLabelSyntax) != label)
                        {
                            diagnostics.Add(ErrorCode.ERR_DuplicateCaseLabel, node.Location, pattern.ConstantValue.GetValueToDisplay() ?? label.Name);
                            hasErrors = true;
                        }

                        // Until we've determined whether or not the switch label is reachable, we assume it
                        // is. The caller updates isReachable after determining if the label is subsumed.
                        const bool isReachable = true;
                        return new BoundPatternSwitchLabel(node, label, pattern, null, isReachable, hasErrors);
                    }

                case SyntaxKind.DefaultSwitchLabel:
                    {
                        var defaultLabelSyntax = (DefaultSwitchLabelSyntax)node;
                        var pattern = new BoundWildcardPattern(node);
                        bool hasErrors = pattern.HasErrors;
                        if (defaultLabel != null)
                        {
                            diagnostics.Add(ErrorCode.ERR_DuplicateCaseLabel, node.Location, label.Name);
                            hasErrors = true;
                        }

                        // We always treat the default label as reachable, even if the switch is complete.
                        const bool isReachable = true;

                        // Note that this is semantically last! The caller will place it in the decision tree
                        // in the final position.
                        defaultLabel = new BoundPatternSwitchLabel(node, label, pattern, null, isReachable, hasErrors);
                        return defaultLabel;
                    }

                case SyntaxKind.CasePatternSwitchLabel:
                    {
                        var matchLabelSyntax = (CasePatternSwitchLabelSyntax)node;
                        var pattern = sectionBinder.BindPattern(
                            matchLabelSyntax.Pattern, boundSwitchExpression, boundSwitchExpression.Type, node.HasErrors, diagnostics, wasSwitchCase: true);
                        return new BoundPatternSwitchLabel(node, label, pattern,
                            matchLabelSyntax.WhenClause != null ? sectionBinder.BindBooleanExpression(matchLabelSyntax.WhenClause.Condition, diagnostics) : null,
                            true, node.HasErrors);
                    }

                default:
                    throw ExceptionUtilities.UnexpectedValue(node);
            }
        }
Esempio n. 10
0
        private BoundPatternSwitchLabel BindPatternSwitchSectionLabel(
            Binder sectionBinder, BoundExpression boundSwitchExpression, SwitchLabelSyntax node, LabelSymbol label, ref BoundPatternSwitchLabel defaultLabel, DiagnosticBag diagnostics)
        {
            switch (node.Kind())
            {
            case SyntaxKind.CaseSwitchLabel:
            {
                var  caseLabelSyntax = (CaseSwitchLabelSyntax)node;
                bool wasExpression;
                var  pattern = sectionBinder.BindConstantPattern(
                    node, boundSwitchExpression, boundSwitchExpression.Type, caseLabelSyntax.Value, node.HasErrors, diagnostics, out wasExpression, wasSwitchCase: true);
                bool hasErrors     = pattern.HasErrors;
                var  constantValue = pattern.ConstantValue;
                if (!hasErrors &&
                    (object)constantValue != null &&
                    pattern.Value.Type == SwitchGoverningType &&
                    this.FindMatchingSwitchCaseLabel(constantValue, caseLabelSyntax) != label)
                {
                    diagnostics.Add(ErrorCode.ERR_DuplicateCaseLabel, node.Location, pattern.ConstantValue.GetValueToDisplay() ?? label.Name);
                    hasErrors = true;
                }

                if (caseLabelSyntax.Value.Kind() == SyntaxKind.DefaultLiteralExpression)
                {
                    diagnostics.Add(ErrorCode.WRN_DefaultInSwitch, caseLabelSyntax.Value.Location);
                }

                // Until we've determined whether or not the switch label is reachable, we assume it
                // is. The caller updates isReachable after determining if the label is subsumed.
                const bool isReachable = true;
                return(new BoundPatternSwitchLabel(node, label, pattern, null, isReachable, hasErrors));
            }

            case SyntaxKind.DefaultSwitchLabel:
            {
                var  defaultLabelSyntax = (DefaultSwitchLabelSyntax)node;
                var  pattern            = new BoundWildcardPattern(node);
                bool hasErrors          = pattern.HasErrors;
                if (defaultLabel != null)
                {
                    diagnostics.Add(ErrorCode.ERR_DuplicateCaseLabel, node.Location, label.Name);
                    hasErrors = true;
                }

                // We always treat the default label as reachable, even if the switch is complete.
                const bool isReachable = true;

                // Note that this is semantically last! The caller will place it in the decision tree
                // in the final position.
                defaultLabel = new BoundPatternSwitchLabel(node, label, pattern, null, isReachable, hasErrors);
                return(defaultLabel);
            }

            case SyntaxKind.CasePatternSwitchLabel:
            {
                var matchLabelSyntax = (CasePatternSwitchLabelSyntax)node;
                var pattern          = sectionBinder.BindPattern(
                    matchLabelSyntax.Pattern, boundSwitchExpression, boundSwitchExpression.Type, node.HasErrors, diagnostics, wasSwitchCase: true);
                return(new BoundPatternSwitchLabel(node, label, pattern,
                                                   matchLabelSyntax.WhenClause != null ? sectionBinder.BindBooleanExpression(matchLabelSyntax.WhenClause.Condition, diagnostics) : null,
                                                   true, node.HasErrors));
            }

            default:
                throw ExceptionUtilities.UnexpectedValue(node);
            }
        }
Esempio n. 11
0
        private BoundSwitchLabel BindSwitchSectionLabel(SwitchLabelSyntax node, Binder sectionBinder, DiagnosticBag diagnostics)
        {
            var switchGoverningType = GetSwitchGoverningType(diagnostics);
            BoundExpression boundLabelExpressionOpt = null;

            SourceLabelSymbol boundLabelSymbol = null;
            ConstantValue labelExpressionConstant = null;
            List<SourceLabelSymbol> matchedLabelSymbols;

            // Prevent cascading diagnostics
            bool hasErrors = node.HasErrors;

            switch (node.Kind())
            {
                case SyntaxKind.CaseSwitchLabel:
                var caseLabelSyntax = (CaseSwitchLabelSyntax)node;
                // Bind the label case expression
                boundLabelExpressionOpt = sectionBinder.BindValue(caseLabelSyntax.Value, diagnostics, BindValueKind.RValue);

                boundLabelExpressionOpt = ConvertCaseExpression(switchGoverningType, caseLabelSyntax, boundLabelExpressionOpt, sectionBinder, ref labelExpressionConstant, diagnostics);

                // Check for bind errors
                hasErrors = hasErrors || boundLabelExpressionOpt.HasAnyErrors;


                // SPEC:    The constant expression of each case label must denote a value that
                // SPEC:    is implicitly convertible (§6.1) to the governing type of the switch statement.

                // Prevent cascading diagnostics
                if (!hasErrors && labelExpressionConstant == null)
                {
                    diagnostics.Add(ErrorCode.ERR_ConstantExpected, caseLabelSyntax.Location);
                    hasErrors = true;
                }

                // LabelSymbols for all the switch case labels are created by BuildLabels().
                // Fetch the matching switch case label symbols
                matchedLabelSymbols = FindMatchingSwitchCaseLabels(labelExpressionConstant, caseLabelSyntax);
                    break;
                case SyntaxKind.CasePatternSwitchLabel:
                    // pattern matching in case is not yet implemented.
                    if (!node.HasErrors)
                    {
                        Error(diagnostics, ErrorCode.ERR_FeatureIsUnimplemented, node, MessageID.IDS_FeaturePatternMatching.Localize());
                        hasErrors = true;
                    }
                    matchedLabelSymbols = new List<SourceLabelSymbol>();
                    break;
                case SyntaxKind.DefaultSwitchLabel:
                matchedLabelSymbols = GetDefaultLabels();
                    break;
                default:
                    throw ExceptionUtilities.Unreachable;
            }

            // Get the corresponding matching label symbol created during BuildLabels()
            // and also check for duplicate case labels.

            Debug.Assert(hasErrors || !matchedLabelSymbols.IsEmpty());
            bool first = true;
            bool hasDuplicateErrors = false;
            foreach (SourceLabelSymbol label in matchedLabelSymbols)
            {
                if (node.Equals(label.IdentifierNodeOrToken.AsNode()))
                {
                    // we must have exactly one matching label created during BuildLabels()
                    boundLabelSymbol = label;

                    // SPEC:    A compile-time error occurs if two or more case labels
                    // SPEC:    in the same switch statement specify the same constant value.

                    if (!hasErrors && !first)
                    {
                        // Skipping the first label symbol ensures that the errors (if any),
                        // are reported on all but the first duplicate case label.
                        diagnostics.Add(ErrorCode.ERR_DuplicateCaseLabel, node.Location,
                            label.SwitchCaseLabelConstant?.Value ?? label.Name);
                        hasDuplicateErrors = true;
                    }
                    break;
                }
                first = false;
            }

            if ((object)boundLabelSymbol == null)
            {
                Debug.Assert(hasErrors);
                boundLabelSymbol = new SourceLabelSymbol((MethodSymbol)this.ContainingMemberOrLambda, node, labelExpressionConstant);
            }

            return new BoundSwitchLabel(
                syntax: node,
                label: boundLabelSymbol,
                expressionOpt: boundLabelExpressionOpt,
                hasErrors: hasErrors || hasDuplicateErrors);
        }
        private BoundPatternSwitchLabel BindPatternSwitchSectionLabel(
            Binder sectionBinder, BoundExpression boundSwitchExpression, SwitchLabelSyntax node, LabelSymbol label, ref BoundPatternSwitchLabel defaultLabel, DiagnosticBag diagnostics)
        {
            switch (node.Kind())
            {
                case SyntaxKind.CaseSwitchLabel:
                    {
                        var caseLabelSyntax = (CaseSwitchLabelSyntax)node;
                        bool wasExpression;
                        var pattern = sectionBinder.BindConstantPattern(
                            node, boundSwitchExpression, boundSwitchExpression.Type, caseLabelSyntax.Value, node.HasErrors, diagnostics, out wasExpression, wasSwitchCase: true);
                        bool hasErrors = pattern.HasErrors;
                        var constantValue = pattern.ConstantValue;
                        if (!hasErrors && (object)constantValue != null && this.FindMatchingSwitchCaseLabel(constantValue, caseLabelSyntax) != label)
                        {
                            diagnostics.Add(ErrorCode.ERR_DuplicateCaseLabel, node.Location, pattern.ConstantValue.GetValueToDisplay() ?? label.Name);
                            hasErrors = true;
                        }
                        return new BoundPatternSwitchLabel(node, label, pattern, null, hasErrors);
                    }

                case SyntaxKind.DefaultSwitchLabel:
                    {
                        var defaultLabelSyntax = (DefaultSwitchLabelSyntax)node;
                        var pattern = new BoundWildcardPattern(node);
                        bool hasErrors = pattern.HasErrors;
                        if (defaultLabel != null)
                        {
                            diagnostics.Add(ErrorCode.ERR_DuplicateCaseLabel, node.Location, "default");
                            hasErrors = true;
                        }

                        // Note that this is semantically last! The caller will place it in the decision tree
                        // in the final position.
                        defaultLabel = new BoundPatternSwitchLabel(node, label, pattern, null, hasErrors);
                        return defaultLabel;
                    }

                case SyntaxKind.CasePatternSwitchLabel:
                    {
                        var matchLabelSyntax = (CasePatternSwitchLabelSyntax)node;
                        var pattern = sectionBinder.BindPattern(
                            matchLabelSyntax.Pattern, boundSwitchExpression, boundSwitchExpression.Type, node.HasErrors, diagnostics, wasSwitchCase: true);
                        return new BoundPatternSwitchLabel(node, label, pattern,
                            matchLabelSyntax.WhenClause != null ? sectionBinder.BindBooleanExpression(matchLabelSyntax.WhenClause.Condition, diagnostics) : null, node.HasErrors);
                    }

                default:
                    throw ExceptionUtilities.UnexpectedValue(node);
            }
        }
            private IEnumerable<ITypeSymbol> InferTypeInSwitchLabel(
                SwitchLabelSyntax switchLabel, SyntaxToken? previousToken = null)
            {
                if (previousToken.HasValue)
                {
                    if (previousToken.Value != switchLabel.Keyword ||
                        switchLabel.Kind() != SyntaxKind.CaseSwitchLabel)
                    {
                        return SpecializedCollections.EmptyEnumerable<ITypeSymbol>();
                    }
                }

                var switchStatement = (SwitchStatementSyntax)switchLabel.Parent.Parent;
                return GetTypes(switchStatement.Expression);
            }
        private static void AnalyzeSwitchStatement(SyntaxNodeAnalysisContext context)
        {
            var switchStatement = (SwitchStatementSyntax)context.Node;

            SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections;

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

            ExpressionSyntax switchExpression = switchStatement.Expression;

            SingleLocalDeclarationStatementInfo localInfo = default;

            string name = GetName();

            if (name == null)
            {
                return;
            }

            ITypeSymbol kindSymbol = context.SemanticModel.GetTypeSymbol(switchExpression, context.CancellationToken);

            if (kindSymbol?.HasMetadataName(RoslynMetadataNames.Microsoft_CodeAnalysis_CSharp_SyntaxKind) != true)
            {
                return;
            }

            foreach (SwitchSectionSyntax section in sections)
            {
                SwitchLabelSyntax label = section.Labels.SingleOrDefault(shouldThrow: false);

                if (label == null)
                {
                    return;
                }

                SyntaxKind labelKind = label.Kind();

                if (labelKind == SyntaxKind.DefaultSwitchLabel)
                {
                    continue;
                }

                if (labelKind != SyntaxKind.CaseSwitchLabel)
                {
                    Debug.Assert(labelKind == SyntaxKind.CasePatternSwitchLabel, labelKind.ToString());
                    return;
                }

                var caseLabel = (CaseSwitchLabelSyntax)label;

                ExpressionSyntax value = caseLabel.Value;

                if (!value.IsKind(SyntaxKind.SimpleMemberAccessExpression))
                {
                    return;
                }

                var memberAccess = (MemberAccessExpressionSyntax)value;

                if (memberAccess.Name is not IdentifierNameSyntax identifierName)
                {
                    return;
                }

                string kindName = identifierName.Identifier.ValueText;

                if (!_syntaxKindNames.Contains(kindName))
                {
                    return;
                }

                SyntaxList <StatementSyntax> statements = section.Statements;

                StatementSyntax statement = statements.FirstOrDefault();

                if (statement == null)
                {
                    return;
                }

                if (statement is BlockSyntax block)
                {
                    statement = block.Statements.FirstOrDefault();
                }

                if (!statement.IsKind(SyntaxKind.LocalDeclarationStatement))
                {
                    return;
                }

                SingleLocalDeclarationStatementInfo localStatement = SyntaxInfo.SingleLocalDeclarationStatementInfo((LocalDeclarationStatementSyntax)statement);

                if (!localStatement.Success)
                {
                    return;
                }

                if (localStatement.Value is not CastExpressionSyntax castExpression)
                {
                    return;
                }

                if (castExpression.Expression is not IdentifierNameSyntax localName)
                {
                    return;
                }

                if (name != localName.Identifier.ValueText)
                {
                    return;
                }

                if (!IsFixableSyntaxSymbol(castExpression.Type, kindName, context.SemanticModel, context.CancellationToken))
                {
                    return;
                }
            }

            if (localInfo.Success &&
                IsLocalVariableReferenced(context, localInfo, switchStatement))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UsePatternMatching, switchStatement.SwitchKeyword);

            string GetName()
            {
                switch (switchExpression.Kind())
                {
                case SyntaxKind.IdentifierName:
                {
                    StatementSyntax previousStatement = switchStatement.PreviousStatement();

                    if (!previousStatement.IsKind(SyntaxKind.LocalDeclarationStatement))
                    {
                        return(null);
                    }

                    localInfo = SyntaxInfo.SingleLocalDeclarationStatementInfo((LocalDeclarationStatementSyntax)previousStatement);

                    if (!localInfo.Success)
                    {
                        return(null);
                    }

                    if (localInfo.IdentifierText != ((IdentifierNameSyntax)switchExpression).Identifier.ValueText)
                    {
                        return(null);
                    }

                    if (!localInfo.Value.IsKind(SyntaxKind.InvocationExpression))
                    {
                        return(null);
                    }

                    return(GetName2((InvocationExpressionSyntax)localInfo.Value));
                }

                case SyntaxKind.InvocationExpression:
                {
                    return(GetName2((InvocationExpressionSyntax)switchExpression));
                }

                default:
                {
                    return(null);
                }
                }
            }