示例#1
0
        internal static void BindFieldInitializers(
            CSharpCompilation compilation,
            SynthesizedInteractiveInitializerMethod?scriptInitializerOpt,
            ImmutableArray <ImmutableArray <FieldOrPropertyInitializer> > fieldInitializers,
            BindingDiagnosticBag diagnostics,
            ref ProcessedFieldInitializers processedInitializers
            )
        {
            var diagsForInstanceInitializers = BindingDiagnosticBag.GetInstance(
                withDiagnostics: true,
                diagnostics.AccumulatesDependencies
                );
            ImportChain?firstImportChain;

            processedInitializers.BoundInitializers = BindFieldInitializers(
                compilation,
                scriptInitializerOpt,
                fieldInitializers,
                diagsForInstanceInitializers,
                out firstImportChain
                );
            processedInitializers.HasErrors        = diagsForInstanceInitializers.HasAnyErrors();
            processedInitializers.FirstImportChain = firstImportChain;
            diagnostics.AddRange(diagsForInstanceInitializers);
            diagsForInstanceInitializers.Free();
        }
示例#2
0
        /// <summary>
        /// Bind a deconstruction assignment.
        /// </summary>
        /// <param name="deconstruction">The deconstruction operation</param>
        /// <param name="left">The left (tuple) operand</param>
        /// <param name="right">The right (deconstructable) operand</param>
        /// <param name="diagnostics">Where to report diagnostics</param>
        /// <param name="declaration">A variable set to the first variable declaration found in the left</param>
        /// <param name="expression">A variable set to the first expression in the left that isn't a declaration or discard</param>
        /// <param name="resultIsUsedOverride">The expression evaluator needs to bind deconstructions (both assignments and declarations) as expression-statements
        ///     and still access the returned value</param>
        /// <param name="rightPlaceholder"></param>
        /// <returns></returns>
        internal BoundDeconstructionAssignmentOperator BindDeconstruction(
            CSharpSyntaxNode deconstruction,
            ExpressionSyntax left,
            ExpressionSyntax right,
            BindingDiagnosticBag diagnostics,
            ref DeclarationExpressionSyntax?declaration,
            ref ExpressionSyntax?expression,
            bool resultIsUsedOverride = false,
            BoundDeconstructValuePlaceholder?rightPlaceholder = null)
        {
            DeconstructionVariable locals = BindDeconstructionVariables(left, diagnostics, ref declaration, ref expression);

            Debug.Assert(locals.NestedVariables is object);

            var             deconstructionDiagnostics = new BindingDiagnosticBag(new DiagnosticBag(), diagnostics.DependenciesBag);
            BoundExpression boundRight = rightPlaceholder ?? BindValue(right, deconstructionDiagnostics, BindValueKind.RValue);

            boundRight = FixTupleLiteral(locals.NestedVariables, boundRight, deconstruction, deconstructionDiagnostics);
            boundRight = BindToNaturalType(boundRight, diagnostics);

            bool resultIsUsed = resultIsUsedOverride || IsDeconstructionResultUsed(left);
            var  assignment   = BindDeconstructionAssignment(deconstruction, left, boundRight, locals.NestedVariables, resultIsUsed, deconstructionDiagnostics);

            DeconstructionVariable.FreeDeconstructionVariables(locals.NestedVariables);

            diagnostics.AddRange(deconstructionDiagnostics.DiagnosticBag);
            return(assignment);
        }
示例#3
0
        protected BoundExpression BindTargetExpression(BindingDiagnosticBag diagnostics, Binder originalBinder, TypeSymbol targetTypeOpt = null)
        {
            if (_lazyExpressionAndDiagnostics == null)
            {
                // Filter out method group in conversion.
                var             expressionDiagnostics = BindingDiagnosticBag.GetInstance();
                BoundExpression boundExpression       = originalBinder.BindValue(TargetExpressionSyntax, expressionDiagnostics, Binder.BindValueKind.RValueOrMethodGroup);
                if (targetTypeOpt is object)
                {
                    boundExpression = originalBinder.GenerateConversionForAssignment(targetTypeOpt, boundExpression, expressionDiagnostics);
                }
                else
                {
                    boundExpression = originalBinder.BindToNaturalType(boundExpression, expressionDiagnostics);
                }
                Interlocked.CompareExchange(ref _lazyExpressionAndDiagnostics, new ExpressionAndDiagnostics(boundExpression, expressionDiagnostics.ToReadOnlyAndFree()), null);
            }
            Debug.Assert(_lazyExpressionAndDiagnostics != null);

            if (diagnostics != null)
            {
                diagnostics.AddRange(_lazyExpressionAndDiagnostics.Diagnostics, allowMismatchInDependencyAccumulation: true);
            }

            return(_lazyExpressionAndDiagnostics.Expression);
        }
        internal override BoundStatement BindSwitchStatementCore(SwitchStatementSyntax node, Binder originalBinder, BindingDiagnosticBag diagnostics)
        {
            Debug.Assert(SwitchSyntax.Equals(node));

            if (node.Sections.Count == 0)
            {
                diagnostics.Add(ErrorCode.WRN_EmptySwitch, node.OpenBraceToken.GetLocation());
            }

            // Bind switch expression and set the switch governing type.
            BoundExpression boundSwitchGoverningExpression = SwitchGoverningExpression;

            diagnostics.AddRange(SwitchGoverningDiagnostics, allowMismatchInDependencyAccumulation: true);

            ImmutableArray <BoundSwitchSection>  switchSections = BindSwitchSections(originalBinder, diagnostics, out BoundSwitchLabel defaultLabel);
            ImmutableArray <LocalSymbol>         locals         = GetDeclaredLocalsForScope(node);
            ImmutableArray <LocalFunctionSymbol> functions      = GetDeclaredLocalFunctionsForScope(node);
            BoundDecisionDag decisionDag = DecisionDagBuilder.CreateDecisionDagForSwitchStatement(
                compilation: this.Compilation,
                syntax: node,
                switchGoverningExpression: boundSwitchGoverningExpression,
                switchSections: switchSections,
                // If there is no explicit default label, the default action is to break out of the switch
                defaultLabel: defaultLabel?.Label ?? BreakLabel,
                diagnostics);

            // Report subsumption errors, but ignore the input's constant value for that.
            CheckSwitchErrors(node, boundSwitchGoverningExpression, ref switchSections, decisionDag, diagnostics);

            // When the input is constant, we use that to reshape the decision dag that is returned
            // so that flow analysis will see that some of the cases may be unreachable.
            decisionDag = decisionDag.SimplifyDecisionDagIfConstantInput(boundSwitchGoverningExpression);

            return(new BoundSwitchStatement(
                       syntax: node,
                       expression: boundSwitchGoverningExpression,
                       innerLocals: locals,
                       innerLocalFunctions: functions,
                       switchSections: switchSections,
                       defaultLabel: defaultLabel,
                       breakLabel: this.BreakLabel,
                       reachabilityDecisionDag: decisionDag));
        }
示例#5
0
        internal override BoundExpression BindSwitchExpressionCore(SwitchExpressionSyntax node, Binder originalBinder, BindingDiagnosticBag diagnostics)
        {
            Debug.Assert(node == SwitchExpressionSyntax);

            // Bind switch expression and set the switch governing type.
            var boundInputExpression = InputExpression;

            diagnostics.AddRange(InputExpressionDiagnostics, allowMismatchInDependencyAccumulation: true);
            ImmutableArray <BoundSwitchExpressionArm> switchArms = BindSwitchExpressionArms(node, originalBinder, diagnostics);
            TypeSymbol naturalType           = InferResultType(switchArms, diagnostics);
            bool       reportedNotExhaustive = CheckSwitchExpressionExhaustive(node, boundInputExpression, switchArms, out BoundDecisionDag decisionDag, out LabelSymbol defaultLabel, diagnostics);

            // When the input is constant, we use that to reshape the decision dag that is returned
            // so that flow analysis will see that some of the cases may be unreachable.
            decisionDag = decisionDag.SimplifyDecisionDagIfConstantInput(boundInputExpression);

            return(new BoundUnconvertedSwitchExpression(
                       node, boundInputExpression, switchArms, decisionDag,
                       defaultLabel: defaultLabel, reportedNotExhaustive: reportedNotExhaustive, type: naturalType));
        }
示例#6
0
            private XNode[] RewriteIncludeElement(XElement includeElement, string currentXmlFilePath, CSharpSyntaxNode originatingSyntax, out string commentMessage)
            {
                Location location = GetIncludeElementLocation(includeElement, ref currentXmlFilePath, ref originatingSyntax);

                Debug.Assert(originatingSyntax != null);

                bool diagnose = originatingSyntax.SyntaxTree.ReportDocumentationCommentDiagnostics();

                if (!EnterIncludeElement(location))
                {
                    // NOTE: these must exist since we're already processed this node elsewhere in the call stack.
                    XAttribute fileAttr      = includeElement.Attribute(XName.Get(DocumentationCommentXmlNames.FileAttributeName));
                    XAttribute pathAttr      = includeElement.Attribute(XName.Get(DocumentationCommentXmlNames.PathAttributeName));
                    string     filePathValue = fileAttr.Value;
                    string     xpathValue    = pathAttr.Value;

                    if (diagnose)
                    {
                        _diagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, new LocalizableErrorArgument(MessageID.IDS_OperationCausedStackOverflow));
                    }

                    commentMessage = ErrorFacts.GetMessage(MessageID.IDS_XMLNOINCLUDE, CultureInfo.CurrentUICulture);

                    // Don't inspect the children - we're already in a cycle.
                    return(new XNode[] { new XComment(commentMessage), includeElement.Copy(copyAttributeAnnotations: false) });
                }

                DiagnosticBag includeDiagnostics = DiagnosticBag.GetInstance();

                try
                {
                    XAttribute fileAttr = includeElement.Attribute(XName.Get(DocumentationCommentXmlNames.FileAttributeName));
                    XAttribute pathAttr = includeElement.Attribute(XName.Get(DocumentationCommentXmlNames.PathAttributeName));

                    bool hasFileAttribute = fileAttr != null;
                    bool hasPathAttribute = pathAttr != null;
                    if (!hasFileAttribute || !hasPathAttribute)
                    {
                        var subMessage = hasFileAttribute ? MessageID.IDS_XMLMISSINGINCLUDEPATH.Localize() : MessageID.IDS_XMLMISSINGINCLUDEFILE.Localize();
                        includeDiagnostics.Add(ErrorCode.WRN_InvalidInclude, location, subMessage);
                        commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLBADINCLUDE);
                        return(null);
                    }

                    string xpathValue    = pathAttr.Value;
                    string filePathValue = fileAttr.Value;

                    var resolver = _compilation.Options.XmlReferenceResolver;
                    if (resolver == null)
                    {
                        includeDiagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, new CodeAnalysisResourcesLocalizableErrorArgument(nameof(CodeAnalysisResources.XmlReferencesNotSupported)));
                        commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLFAILEDINCLUDE);
                        return(null);
                    }

                    string resolvedFilePath = resolver.ResolveReference(filePathValue, currentXmlFilePath);

                    if (resolvedFilePath == null)
                    {
                        // NOTE: same behavior as IOException.
                        includeDiagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, new CodeAnalysisResourcesLocalizableErrorArgument(nameof(CodeAnalysisResources.FileNotFound)));
                        commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLFAILEDINCLUDE);
                        return(null);
                    }

                    if (_includedFileCache == null)
                    {
                        _includedFileCache = new DocumentationCommentIncludeCache(resolver);
                    }

                    try
                    {
                        XDocument doc;

                        try
                        {
                            doc = _includedFileCache.GetOrMakeDocument(resolvedFilePath);
                        }
                        catch (IOException e)
                        {
                            // NOTE: same behavior as resolvedFilePath == null.
                            includeDiagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, e.Message);
                            commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLFAILEDINCLUDE);
                            return(null);
                        }

                        Debug.Assert(doc != null);

                        string     errorMessage;
                        bool       invalidXPath;
                        XElement[] loadedElements = XmlUtilities.TrySelectElements(doc, xpathValue, out errorMessage, out invalidXPath);
                        if (loadedElements == null)
                        {
                            includeDiagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, errorMessage);

                            commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLFAILEDINCLUDE);
                            if (invalidXPath)
                            {
                                // leave the include node as is
                                return(null);
                            }

                            if (location.IsInSource)
                            {
                                // As in Dev11, return only the comment - drop the include element.
                                return(new XNode[] { new XComment(commentMessage) });
                            }
                            else
                            {
                                commentMessage = null;
                                return(Array.Empty <XNode>());
                            }
                        }

                        if (loadedElements != null && loadedElements.Length > 0)
                        {
                            // change the current XML file path for nodes contained in the document:
                            XNode[] result = RewriteMany(loadedElements, resolvedFilePath, originatingSyntax);

                            // The elements could be rewritten away if they are includes that refer to invalid
                            // (but existing and accessible) XML files.  If this occurs, behave as if we
                            // had failed to find any XPath results (as in Dev11).
                            if (result.Length > 0)
                            {
                                // NOTE: in this case, we do NOT visit the children of the include element -
                                // they are dropped.
                                commentMessage = null;
                                return(result);
                            }
                        }

                        commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLNOINCLUDE);
                        return(null);
                    }
                    catch (XmlException e)
                    {
                        // NOTE: invalid XML is handled differently from other errors - we don't include the include element
                        // in the results and the location is in the included (vs includING) file.

                        Location errorLocation = XmlLocation.Create(e, resolvedFilePath);
                        includeDiagnostics.Add(ErrorCode.WRN_XMLParseIncludeError, errorLocation, GetDescription(e)); //NOTE: location is in included file.

                        if (location.IsInSource)
                        {
                            commentMessage = string.Format(ErrorFacts.GetMessage(MessageID.IDS_XMLIGNORED2, CultureInfo.CurrentUICulture), resolvedFilePath);

                            // As in Dev11, return only the comment - drop the include element.
                            return(new XNode[] { new XComment(commentMessage) });
                        }
                        else
                        {
                            commentMessage = null;
                            return(Array.Empty <XNode>());
                        }
                    }
                }
                finally
                {
                    if (diagnose)
                    {
                        _diagnostics.AddRange(includeDiagnostics);
                    }

                    includeDiagnostics.Free();

                    LeaveIncludeElement(location);
                }
            }
示例#7
0
        private BoundExpression FinalTranslation(QueryTranslationState state, BindingDiagnosticBag diagnostics)
        {
            Debug.Assert(state.clauses.IsEmpty());
            switch (state.selectOrGroup.Kind())
            {
            case SyntaxKind.SelectClause:
            {
                // A query expression of the form
                //     from x in e select v
                // is translated into
                //     ( e ) . Select ( x => v )
                var selectClause = (SelectClauseSyntax)state.selectOrGroup;
                var x            = state.rangeVariable;
                var e            = state.fromExpression;
                var v            = selectClause.Expression;
                var lambda       = MakeQueryUnboundLambda(state.RangeVariableMap(), x, v, diagnostics.AccumulatesDependencies);
                var result       = MakeQueryInvocation(state.selectOrGroup, e, "Select", lambda, diagnostics);
                return(MakeQueryClause(selectClause, result, queryInvocation: result));
            }

            case SyntaxKind.GroupClause:
            {
                // A query expression of the form
                //     from x in e group v by k
                // is translated into
                //     ( e ) . GroupBy ( x => k , x => v )
                // except when v is the identifier x, the translation is
                //     ( e ) . GroupBy ( x => k )
                var       groupClause = (GroupClauseSyntax)state.selectOrGroup;
                var       x           = state.rangeVariable;
                var       e           = state.fromExpression;
                var       v           = groupClause.GroupExpression;
                var       k           = groupClause.ByExpression;
                var       vId         = v as IdentifierNameSyntax;
                BoundCall result;
                var       lambdaLeft = MakeQueryUnboundLambda(state.RangeVariableMap(), x, k, diagnostics.AccumulatesDependencies);

                // this is the unoptimized form (when v is not the identifier x)
                var             d           = BindingDiagnosticBag.GetInstance(diagnostics);
                BoundExpression lambdaRight = MakeQueryUnboundLambda(state.RangeVariableMap(), x, v, diagnostics.AccumulatesDependencies);
                result = MakeQueryInvocation(state.selectOrGroup, e, "GroupBy", ImmutableArray.Create(lambdaLeft, lambdaRight), d);
                // k and v appear reversed in the invocation, so we reorder their evaluation
                result = ReverseLastTwoParameterOrder(result);

                BoundExpression?unoptimizedForm = null;
                if (vId != null && vId.Identifier.ValueText == x.Name)
                {
                    // The optimized form.  We store the unoptimized form for analysis
                    unoptimizedForm = result;
                    result          = MakeQueryInvocation(state.selectOrGroup, e, "GroupBy", lambdaLeft, diagnostics);
                    if (unoptimizedForm.HasAnyErrors && !result.HasAnyErrors)
                    {
                        unoptimizedForm = null;
                    }
                }
                else
                {
                    diagnostics.AddRange(d);
                }

                d.Free();
                return(MakeQueryClause(groupClause, result, queryInvocation: result, unoptimizedForm: unoptimizedForm));
            }

            default:
            {
                // there should have been a syntax error if we get here.
                Debug.Assert(state.fromExpression.Type is { });
                return(new BoundBadExpression(
                           state.selectOrGroup, LookupResultKind.OverloadResolutionFailure, ImmutableArray <Symbol?> .Empty,
                           ImmutableArray.Create(state.fromExpression), state.fromExpression.Type));
            }