| File: EditAndContinue\DeclarationBody\InstanceConstructorDeclarationBody.cs | Web Access |
| Project: src\roslyn\src\Features\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Features.csproj (Microsoft.CodeAnalysis.CSharp.Features) |
// 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.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.Differencing; using Microsoft.CodeAnalysis.EditAndContinue; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue; internal abstract class InstanceConstructorDeclarationBody : MemberBody { public abstract bool HasExplicitInitializer { get; } public abstract TextSpan InitializerActiveStatementSpan { get; } public abstract SyntaxNode InitializerActiveStatement { get; } public abstract SyntaxNode? MatchRoot { get; } /// <summary> /// Expression or block body. /// </summary> public abstract SyntaxNode? ExplicitBody { get; } /// <summary> /// Node that represents the closure that constructor parameters captured within its body are lifted to. /// </summary> public abstract SyntaxNode? ParameterClosure { get; } public sealed override SyntaxTree SyntaxTree => InitializerActiveStatement.SyntaxTree; public sealed override StateMachineInfo GetStateMachineInfo() => StateMachineInfo.None; public sealed override SyntaxNode FindStatementAndPartner(TextSpan span, MemberBody? partnerDeclarationBody, out SyntaxNode? partnerStatement, out int statementPart) { var partnerCtorBody = (InstanceConstructorDeclarationBody?)partnerDeclarationBody; if (span == InitializerActiveStatementSpan) { statementPart = AbstractEditAndContinueAnalyzer.DefaultStatementPart; partnerStatement = partnerCtorBody?.InitializerActiveStatement; return InitializerActiveStatement; } if (HasExplicitInitializer && InitializerActiveStatementSpan.Contains(span)) { // If present, partner body does not have any non-trivial changes and thus the initializer is also present. Debug.Assert(partnerCtorBody == null || partnerCtorBody.HasExplicitInitializer); return CSharpEditAndContinueAnalyzer.FindStatementAndPartner( span, body: InitializerActiveStatement, partnerBody: partnerCtorBody?.InitializerActiveStatement, out partnerStatement, out statementPart); } Debug.Assert(ExplicitBody != null); // If present, partner body does not have any non-trivial changes and thus the explicit body is also present. Debug.Assert(partnerCtorBody == null || partnerCtorBody.ExplicitBody != null); return CSharpEditAndContinueAnalyzer.FindStatementAndPartner( span, body: ExplicitBody, partnerBody: partnerCtorBody?.ExplicitBody, out partnerStatement, out statementPart); } public sealed override bool TryMatchActiveStatement(DeclarationBody newBody, SyntaxNode oldStatement, ref int statementPart, [NotNullWhen(true)] out SyntaxNode? newStatement) { var newCtorBody = (InstanceConstructorDeclarationBody)newBody; if (oldStatement == InitializerActiveStatement) { newStatement = newCtorBody.InitializerActiveStatement; return true; } if (ExplicitBody != null && newCtorBody.ExplicitBody != null && CSharpEditAndContinueAnalyzer.TryMatchActiveStatement(ExplicitBody, newCtorBody.ExplicitBody, oldStatement, out newStatement)) { return true; } if (MatchRoot == null || newCtorBody.MatchRoot == null) { // General body mapping is not available, so we can't do better then // mapping any active statement in this body to the initializer of the other body. newStatement = newCtorBody.InitializerActiveStatement; return true; } newStatement = null; return false; } public sealed override Match<SyntaxNode>? ComputeSingleRootMatch(DeclarationBody newBody, IEnumerable<KeyValuePair<SyntaxNode, SyntaxNode>>? knownMatches) => MatchRoot is { } oldRoot && ((InstanceConstructorDeclarationBody)newBody).MatchRoot is { } newRoot ? SyntaxComparer.Statement.ComputeMatch(oldRoot, newRoot, knownMatches) : null; public override DeclarationBodyMap ComputeMap(DeclarationBody newBody, IEnumerable<KeyValuePair<SyntaxNode, SyntaxNode>>? knownMatches) { var map = base.ComputeMap(newBody, knownMatches); // parameter closures are represented by the constructor or type declaration node, which may not be included in the match: return ParameterClosure is { } parameterClosure && ((InstanceConstructorDeclarationBody)newBody).ParameterClosure is { } newParameterClosure && !map.Forward.ContainsKey(parameterClosure) ? map.WithAdditionalMapping(parameterClosure, newParameterClosure) : map; } }