/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Portable/Compilation/MethodBodySemanticModel.cs
308 строк
15 KB
Julien Couvreur
Extensions: address or split remaining open issues directly associated with test plan (#79452)
23 июл 2025, 11:12
Не верифицирован
23 июл 2025, 11:12
cb8d294
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Microsoft.CodeAnalysis.CSharp { internal sealed class MethodBodySemanticModel : MemberSemanticModel { /// <summary> /// Initial state for a MethodBodySemanticModel. Shared between here and the <see cref="MethodCompiler"/>. Used to make a <see cref="MethodBodySemanticModel"/> /// with the required syntax and optional precalculated starting state for the model. /// </summary> 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; } } #nullable disable internal MethodBodySemanticModel( MethodSymbol owner, Binder rootBinder, CSharpSyntaxNode syntax, PublicSemanticModel containingPublicSemanticModel, ImmutableDictionary<Symbol, Symbol> parentRemappedSymbolsOpt = null) : base(syntax, owner, rootBinder, containingPublicSemanticModel, parentRemappedSymbolsOpt) { Debug.Assert((object)owner != null); Debug.Assert(owner.Kind == SymbolKind.Method); Debug.Assert(syntax != null); Debug.Assert(parentRemappedSymbolsOpt is null || IsSpeculativeSemanticModel); Debug.Assert((syntax.Kind() == SyntaxKind.CompilationUnit) == (!IsSpeculativeSemanticModel && owner is SynthesizedSimpleProgramEntryPointSymbol)); } /// <summary> /// Creates a SemanticModel for the method. /// </summary> internal static MethodBodySemanticModel Create(SyntaxTreeSemanticModel containingSemanticModel, MethodSymbol owner, InitialState initialState) { Debug.Assert(containingSemanticModel != null); var result = new MethodBodySemanticModel(owner, initialState.Binder, initialState.Syntax, containingSemanticModel); if (initialState.Body != null) { result.UnguardedAddBoundTreeForStandaloneSyntax(initialState.Syntax, initialState.Body, initialState.SnapshotManager, initialState.RemappedSymbols); } return result; } 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.MethodDeclaration: case SyntaxKind.ConversionOperatorDeclaration: case SyntaxKind.OperatorDeclaration: case SyntaxKind.ConstructorDeclaration: case SyntaxKind.DestructorDeclaration: case SyntaxKind.GetAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: case SyntaxKind.InitAccessorDeclaration: case SyntaxKind.AddAccessorDeclaration: case SyntaxKind.RemoveAccessorDeclaration: case SyntaxKind.CompilationUnit: case SyntaxKind.RecordDeclaration: case SyntaxKind.ClassDeclaration: return binder.BindMethodBody(node, diagnostics); } return base.Bind(binder, node, diagnostics); } /// <summary> /// Creates a speculative SemanticModel for a method body that did not appear in the original source code. /// </summary> 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); } /// <summary> /// Creates a speculative SemanticModel for an expression body that did not appear in the original source code. /// </summary> internal static SpeculativeSemanticModelWithMemberModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, ArrowExpressionClauseSyntax syntax, Binder rootBinder, int position) { return CreateSpeculativeForNode(parentSemanticModel, owner, syntax, rootBinder, snapshotManagerOpt: null, parentRemappedSymbolsOpt: null, position); } /// <summary> /// Creates a speculative SemanticModel for a constructor initializer that did not appear in the original source code. /// </summary> internal static SpeculativeSemanticModelWithMemberModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, ConstructorInitializerSyntax syntax, Binder rootBinder, int position) { return CreateSpeculativeForNode(parentSemanticModel, owner, syntax, rootBinder, snapshotManagerOpt: null, parentRemappedSymbolsOpt: null, position); } /// <summary> /// Creates a speculative SemanticModel for a constructor initializer that did not appear in the original source code. /// </summary> internal static SpeculativeSemanticModelWithMemberModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, MethodSymbol owner, PrimaryConstructorBaseTypeSyntax syntax, Binder rootBinder, int position) { return CreateSpeculativeForNode(parentSemanticModel, owner, syntax, rootBinder, snapshotManagerOpt: null, parentRemappedSymbolsOpt: null, position); } internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out PublicSemanticModel speculativeModel) { // CONSIDER: Do we want to ensure that speculated method and the original method have identical signatures? return GetSpeculativeSemanticModelForMethodBody(parentModel, position, method.Body, out speculativeModel); } private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel parentModel, int position, BlockSyntax body, out PublicSemanticModel speculativeModel) { position = CheckAndAdjustPosition(position); var methodSymbol = (MethodSymbol)this.MemberSymbol; // Strip off ExecutableCodeBinder (see ctor). Binder binder = this.RootBinder; do { if (binder is ExecutableCodeBinder) { binder = binder.Next; break; } binder = binder.Next; } while (binder != null); Debug.Assert(binder != null); Binder executablebinder = new WithNullableContextBinder(SyntaxTree, position, binder ?? this.RootBinder); executablebinder = new ExecutableCodeBinder(body, methodSymbol, executablebinder); var blockBinder = executablebinder.GetBinder(body).WithAdditionalFlags(GetSemanticModelBinderFlags()); // We don't pass the snapshot manager along here, because we're speculating about an entirely new body and it should not // be influenced by any existing code in the body. speculativeModel = CreateSpeculative(parentModel, methodSymbol, body, blockBinder, snapshotManagerOpt: null, parentRemappedSymbolsOpt: 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); var binder = this.GetEnclosingBinder(position); if (binder == null) { speculativeModel = null; return false; } var methodSymbol = (MethodSymbol)this.MemberSymbol; binder = new WithNullableContextBinder(SyntaxTree, position, binder); binder = new ExecutableCodeBinder(statement, methodSymbol, binder); speculativeModel = CreateSpeculative(parentModel, methodSymbol, statement, binder, GetSnapshotManager(), GetRemappedSymbols(), position); return true; } internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out PublicSemanticModel speculativeModel) { position = CheckAndAdjustPosition(position); var binder = this.GetEnclosingBinder(position); if (binder == null) { speculativeModel = null; return false; } var methodSymbol = (MethodSymbol)this.MemberSymbol; binder = new WithNullableContextBinder(SyntaxTree, position, binder); binder = new ExecutableCodeBinder(expressionBody, methodSymbol, binder); speculativeModel = CreateSpeculative(parentModel, methodSymbol, expressionBody, binder, position); return true; } internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out PublicSemanticModel speculativeModel) { if (MemberSymbol is MethodSymbol methodSymbol && methodSymbol.MethodKind == MethodKind.Constructor && Root.FindToken(position).Parent?.AncestorsAndSelf().OfType<ConstructorInitializerSyntax>().FirstOrDefault()?.Parent == Root) { var binder = this.GetEnclosingBinder(position); if (binder != null) { binder = new WithNullableContextBinder(SyntaxTree, position, binder); binder = new ExecutableCodeBinder(constructorInitializer, methodSymbol, binder); speculativeModel = CreateSpeculative(parentModel, methodSymbol, constructorInitializer, binder, position); return true; } } speculativeModel = null; return false; } internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out PublicSemanticModel speculativeModel) { if (MemberSymbol is SynthesizedPrimaryConstructor primaryCtor && primaryCtor.GetSyntax() is TypeDeclarationSyntax typeDecl) { Debug.Assert(typeDecl.Kind() is (SyntaxKind.RecordDeclaration or SyntaxKind.ClassDeclaration)); if (Root.FindToken(position).Parent?.AncestorsAndSelf().OfType<PrimaryConstructorBaseTypeSyntax>().FirstOrDefault() == typeDecl.PrimaryConstructorBaseTypeIfClass) { var binder = this.GetEnclosingBinder(position); if (binder != null) { binder = new WithNullableContextBinder(SyntaxTree, position, binder); binder = new ExecutableCodeBinder(constructorInitializer, primaryCtor, binder); speculativeModel = CreateSpeculative(parentModel, primaryCtor, constructorInitializer, binder, 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) { var afterInitializersState = NullableWalker.GetAfterInitializersState(Compilation, MemberSymbol, boundRoot); return NullableWalker.AnalyzeAndRewrite(Compilation, 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, MemberSymbol, boundRoot, binder, diagnostics, createSnapshots); } protected override bool IsNullableAnalysisEnabledCore() { return Compilation.IsNullableAnalysisEnabledIn((MethodSymbol)MemberSymbol); } } }