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(); }
/// <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); }
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)); }
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)); }
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); } }
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)); }