242 lines
12 KiB
C#
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);
|
||
|
|
}
|
||
|
|
}
|