Ejemplo n.º 1
0
        private BoundPatternSwitchLabel BindPatternSwitchSectionLabel(
            Binder sectionBinder,
            SwitchLabelSyntax node,
            LabelSymbol label,
            ref BoundPatternSwitchLabel defaultLabel,
            DiagnosticBag diagnostics)
        {
            switch (node.Kind())
            {
            case SyntaxKind.CaseSwitchLabel:
            {
                var caseLabelSyntax = (CaseSwitchLabelSyntax)node;
                var pattern         = sectionBinder.BindConstantAsPattern(
                    node, SwitchGoverningType, caseLabelSyntax.Value, node.HasErrors, diagnostics, out bool wasExpression);
                bool       hasErrors        = pattern.HasErrors;
                SyntaxNode innerValueSyntax = caseLabelSyntax.Value.SkipParens();
                if (innerValueSyntax.Kind() == SyntaxKind.DefaultLiteralExpression)
                {
                    diagnostics.Add(ErrorCode.ERR_DefaultInSwitch, innerValueSyntax.Location);
                    hasErrors = true;
                }

                pattern.WasCompilerGenerated = true;
                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, SwitchGoverningType, node.HasErrors, diagnostics);
                return(new BoundPatternSwitchLabel(node, label, pattern,
                                                   matchLabelSyntax.WhenClause != null ? sectionBinder.BindBooleanExpression(matchLabelSyntax.WhenClause.Condition, diagnostics) : null,
                                                   true, node.HasErrors));
            }

            default:
                throw ExceptionUtilities.UnexpectedValue(node);
            }
        }