// 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; using System.Composition; using Microsoft.CodeAnalysis.CSharp.LanguageService; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageService; using Microsoft.CodeAnalysis.SemanticModelReuse; namespace Microsoft.CodeAnalysis.CSharp.SemanticModelReuse; [ExportLanguageService(typeof(ISemanticModelReuseLanguageService), LanguageNames.CSharp), Shared] internal sealed class CSharpSemanticModelReuseLanguageService : AbstractSemanticModelReuseLanguageService< MemberDeclarationSyntax, BasePropertyDeclarationSyntax, AccessorDeclarationSyntax> { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public CSharpSemanticModelReuseLanguageService() { } protected override ISyntaxFacts SyntaxFacts => CSharpSyntaxFacts.Instance; protected override BasePropertyDeclarationSyntax GetBasePropertyDeclaration(AccessorDeclarationSyntax accessor) { Contract.ThrowIfFalse(accessor.Parent is AccessorListSyntax); Contract.ThrowIfFalse(accessor.Parent.Parent is BasePropertyDeclarationSyntax); return (BasePropertyDeclarationSyntax)accessor.Parent.Parent; } protected override SyntaxList<AccessorDeclarationSyntax> GetAccessors(BasePropertyDeclarationSyntax baseProperty) => baseProperty.AccessorList!.Accessors; public override SyntaxNode? TryGetContainingMethodBodyForSpeculation(SyntaxNode node) { for (SyntaxNode? previous = null, current = node; current != null; previous = current, current = current.Parent) { // These are the exact types that SemanticModel.TryGetSpeculativeSemanticModelForMethodBody accepts. if (current is BaseMethodDeclarationSyntax baseMethod) return previous != null && baseMethod.Body == previous ? baseMethod : null; if (current is AccessorDeclarationSyntax accessor) return previous != null && accessor.Body == previous ? accessor : null; } return null; } protected override SemanticModel? TryGetSpeculativeSemanticModelWorker(SemanticModel previousSemanticModel, SyntaxNode previousBodyNode, SyntaxNode currentBodyNode) { if (previousBodyNode is BaseMethodDeclarationSyntax previousBaseMethod && currentBodyNode is BaseMethodDeclarationSyntax currentBaseMethod && previousBaseMethod.Body != null && previousSemanticModel.TryGetSpeculativeSemanticModelForMethodBody(previousBaseMethod.Body.SpanStart, currentBaseMethod, out var speculativeModel)) { return speculativeModel; } if (previousBodyNode is AccessorDeclarationSyntax previousAccessorDeclaration && currentBodyNode is AccessorDeclarationSyntax currentAccessorDeclaration && previousAccessorDeclaration.Body != null && previousSemanticModel.TryGetSpeculativeSemanticModelForMethodBody(previousAccessorDeclaration.Body.SpanStart, currentAccessorDeclaration, out speculativeModel)) { return speculativeModel; } return null; } } |