Files
2026-08-27 10:56:38 -06:00

242 lines
12 KiB
C#

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<Symbol, Symbol>? RemappedSymbols;
internal InitialState(CSharpSyntaxNode syntax, BoundNode? bodyOpt = null, Binder? binder = null, NullableWalker.SnapshotManager? snapshotManager = null, ImmutableDictionary<Symbol, Symbol>? remappedSymbols = null)
{
Syntax = syntax;
Body = bodyOpt;
Binder = binder;
SnapshotManager = snapshotManager;
RemappedSymbols = remappedSymbols;
}
}
internal MethodBodySemanticModel(MethodSymbol owner, Binder rootBinder, CSharpSyntaxNode syntax, PublicSemanticModel containingPublicSemanticModel, ImmutableDictionary<Symbol, Symbol> 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<Symbol, Symbol> 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<Symbol, Symbol> 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<ConstructorInitializerSyntax>().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<PrimaryConstructorBaseTypeSyntax>().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<Symbol, Symbol> 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);
}
}