using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Microsoft.CodeAnalysis.CSharp; internal sealed class MethodBodySemanticModel : MemberSemanticModel { internal readonly struct InitialState { internal readonly CSharpSyntaxNode Syntax; internal readonly BoundNode? Body; internal readonly Binder? Binder; internal readonly NullableWalker.SnapshotManager? SnapshotManager; internal readonly ImmutableDictionary? RemappedSymbols; internal InitialState(CSharpSyntaxNode syntax, BoundNode? bodyOpt = null, Binder? binder = null, NullableWalker.SnapshotManager? snapshotManager = null, ImmutableDictionary? remappedSymbols = null) { Syntax = syntax; Body = bodyOpt; Binder = binder; SnapshotManager = snapshotManager; RemappedSymbols = remappedSymbols; } } internal MethodBodySemanticModel(MethodSymbol owner, Binder rootBinder, CSharpSyntaxNode syntax, PublicSemanticModel containingPublicSemanticModel, ImmutableDictionary parentRemappedSymbolsOpt = null) : base(syntax, owner, rootBinder, containingPublicSemanticModel, parentRemappedSymbolsOpt) { } internal static MethodBodySemanticModel Create(SyntaxTreeSemanticModel containingSemanticModel, MethodSymbol owner, InitialState initialState) { MethodBodySemanticModel methodBodySemanticModel = new MethodBodySemanticModel(owner, initialState.Binder, initialState.Syntax, containingSemanticModel); if (initialState.Body != null) { methodBodySemanticModel.UnguardedAddBoundTreeForStandaloneSyntax((SyntaxNode)(object)initialState.Syntax, initialState.Body, initialState.SnapshotManager, initialState.RemappedSymbols); } return methodBodySemanticModel; } internal override BoundNode Bind(Binder binder, CSharpSyntaxNode node, BindingDiagnosticBag diagnostics) { switch (node.Kind()) { case SyntaxKind.ArrowExpressionClause: return binder.BindExpressionBodyAsBlock((ArrowExpressionClauseSyntax)node, diagnostics); case SyntaxKind.BaseConstructorInitializer: case SyntaxKind.ThisConstructorInitializer: return binder.BindConstructorInitializer((ConstructorInitializerSyntax)node, diagnostics); case SyntaxKind.PrimaryConstructorBaseType: return binder.BindConstructorInitializer((PrimaryConstructorBaseTypeSyntax)node, diagnostics); case SyntaxKind.CompilationUnit: case SyntaxKind.ClassDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.OperatorDeclaration: case SyntaxKind.ConversionOperatorDeclaration: case SyntaxKind.ConstructorDeclaration: case SyntaxKind.DestructorDeclaration: case SyntaxKind.GetAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: case SyntaxKind.AddAccessorDeclaration: case SyntaxKind.RemoveAccessorDeclaration: case SyntaxKind.InitAccessorDeclaration: case SyntaxKind.RecordDeclaration: return binder.BindMethodBody(node, diagnostics); default: return base.Bind(binder, node, diagnostics); } } internal static SpeculativeSemanticModelWithMemberModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, StatementSyntax syntax, Binder rootBinder, NullableWalker.SnapshotManager snapshotManagerOpt, ImmutableDictionary parentRemappedSymbolsOpt, int position) { return CreateSpeculativeForNode(parentSemanticModel, owner, syntax, rootBinder, snapshotManagerOpt, parentRemappedSymbolsOpt, position); } private static SpeculativeSemanticModelWithMemberModel CreateSpeculativeForNode(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, CSharpSyntaxNode syntax, Binder rootBinder, NullableWalker.SnapshotManager snapshotManagerOpt, ImmutableDictionary parentRemappedSymbolsOpt, int position) { return new SpeculativeSemanticModelWithMemberModel(parentSemanticModel, position, owner, syntax, rootBinder, parentRemappedSymbolsOpt, snapshotManagerOpt); } internal static SpeculativeSemanticModelWithMemberModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, ArrowExpressionClauseSyntax syntax, Binder rootBinder, int position) { return CreateSpeculativeForNode(parentSemanticModel, owner, syntax, rootBinder, null, null, position); } internal static SpeculativeSemanticModelWithMemberModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, ConstructorInitializerSyntax syntax, Binder rootBinder, int position) { return CreateSpeculativeForNode(parentSemanticModel, owner, syntax, rootBinder, null, null, position); } internal static SpeculativeSemanticModelWithMemberModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, PrimaryConstructorBaseTypeSyntax syntax, Binder rootBinder, int position) { return CreateSpeculativeForNode(parentSemanticModel, owner, syntax, rootBinder, null, null, position); } internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out PublicSemanticModel speculativeModel) { return GetSpeculativeSemanticModelForMethodBody(parentModel, position, method.Body, out speculativeModel); } private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel parentModel, int position, BlockSyntax body, out PublicSemanticModel speculativeModel) { position = CheckAndAdjustPosition(position); MethodSymbol methodSymbol = (MethodSymbol)base.MemberSymbol; Binder binder = RootBinder; do { if (binder is ExecutableCodeBinder) { binder = binder.Next; break; } binder = binder.Next; } while (binder != null); Binder next = new WithNullableContextBinder(SyntaxTree, position, binder ?? RootBinder); next = new ExecutableCodeBinder((SyntaxNode)(object)body, methodSymbol, next); Binder rootBinder = next.GetBinder((SyntaxNode)(object)body).WithAdditionalFlags(GetSemanticModelBinderFlags()); speculativeModel = CreateSpeculative(parentModel, methodSymbol, body, rootBinder, null, null, position); return true; } internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out PublicSemanticModel speculativeModel) { return GetSpeculativeSemanticModelForMethodBody(parentModel, position, accessor.Body, out speculativeModel); } internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out PublicSemanticModel speculativeModel) { position = CheckAndAdjustPosition(position); Binder enclosingBinder = GetEnclosingBinder(position); if (enclosingBinder == null) { speculativeModel = null; return false; } MethodSymbol methodSymbol = (MethodSymbol)base.MemberSymbol; enclosingBinder = new WithNullableContextBinder(SyntaxTree, position, enclosingBinder); enclosingBinder = new ExecutableCodeBinder((SyntaxNode)(object)statement, methodSymbol, enclosingBinder); speculativeModel = CreateSpeculative(parentModel, methodSymbol, statement, enclosingBinder, GetSnapshotManager(), GetRemappedSymbols(), position); return true; } internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out PublicSemanticModel speculativeModel) { position = CheckAndAdjustPosition(position); Binder enclosingBinder = GetEnclosingBinder(position); if (enclosingBinder == null) { speculativeModel = null; return false; } MethodSymbol methodSymbol = (MethodSymbol)base.MemberSymbol; enclosingBinder = new WithNullableContextBinder(SyntaxTree, position, enclosingBinder); enclosingBinder = new ExecutableCodeBinder((SyntaxNode)(object)expressionBody, methodSymbol, enclosingBinder); speculativeModel = CreateSpeculative(parentModel, methodSymbol, expressionBody, enclosingBinder, position); return true; } internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out PublicSemanticModel speculativeModel) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (base.MemberSymbol is MethodSymbol methodSymbol && (int)methodSymbol.MethodKind == 1) { SyntaxToken val = Root.FindToken(position); SyntaxNode parent = ((SyntaxToken)(ref val)).Parent; if (((parent == null) ? null : parent.AncestorsAndSelf(true).OfType().FirstOrDefault()?.Parent) == Root) { Binder enclosingBinder = GetEnclosingBinder(position); if (enclosingBinder != null) { enclosingBinder = new WithNullableContextBinder(SyntaxTree, position, enclosingBinder); enclosingBinder = new ExecutableCodeBinder((SyntaxNode)(object)constructorInitializer, methodSymbol, enclosingBinder); speculativeModel = CreateSpeculative(parentModel, methodSymbol, constructorInitializer, enclosingBinder, position); return true; } } } speculativeModel = null; return false; } internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out PublicSemanticModel speculativeModel) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (base.MemberSymbol is SynthesizedPrimaryConstructor synthesizedPrimaryConstructor) { TypeDeclarationSyntax syntax = synthesizedPrimaryConstructor.GetSyntax(); if (syntax != null) { SyntaxToken val = Root.FindToken(position); SyntaxNode parent = ((SyntaxToken)(ref val)).Parent; if (((parent != null) ? parent.AncestorsAndSelf(true).OfType().FirstOrDefault() : null) == syntax.PrimaryConstructorBaseTypeIfClass) { Binder enclosingBinder = GetEnclosingBinder(position); if (enclosingBinder != null) { enclosingBinder = new WithNullableContextBinder(SyntaxTree, position, enclosingBinder); enclosingBinder = new ExecutableCodeBinder((SyntaxNode)(object)constructorInitializer, synthesizedPrimaryConstructor, enclosingBinder); speculativeModel = CreateSpeculative(parentModel, synthesizedPrimaryConstructor, constructorInitializer, enclosingBinder, position); return true; } } } } speculativeModel = null; return false; } internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out PublicSemanticModel speculativeModel) { speculativeModel = null; return false; } protected override BoundNode RewriteNullableBoundNodesWithSnapshots(BoundNode boundRoot, Binder binder, DiagnosticBag diagnostics, bool createSnapshots, out NullableWalker.SnapshotManager snapshotManager, ref ImmutableDictionary remappedSymbols) { NullableWalker.VariableState afterInitializersState = NullableWalker.GetAfterInitializersState(Compilation, base.MemberSymbol, boundRoot); return NullableWalker.AnalyzeAndRewrite(Compilation, base.MemberSymbol, boundRoot, binder, afterInitializersState, diagnostics, createSnapshots, out snapshotManager, ref remappedSymbols); } protected override void AnalyzeBoundNodeNullability(BoundNode boundRoot, Binder binder, DiagnosticBag diagnostics, bool createSnapshots) { NullableWalker.AnalyzeWithoutRewrite(Compilation, base.MemberSymbol, boundRoot, binder, diagnostics, createSnapshots); } protected override bool IsNullableAnalysisEnabled() { return Compilation.IsNullableAnalysisEnabledIn((MethodSymbol)base.MemberSymbol); } }