File: InheritanceMargin\AbstractInheritanceMarginService.cs
Web Access
Project: src\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.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.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Text;
 
namespace Microsoft.CodeAnalysis.InheritanceMargin;
internal abstract partial class AbstractInheritanceMarginService : IInheritanceMarginService
{
    /// <summary>
    /// Given the syntax nodes to search,
    /// get all the method, event, property and type declaration syntax nodes.
    /// </summary>
    protected abstract ImmutableArray<SyntaxNode> GetMembers(IEnumerable<SyntaxNode> nodesToSearch);
 
    /// <summary>
    /// Get the token that represents declaration node.
    /// e.g. Identifier for method/property/event and this keyword for indexer.
    /// </summary>
    protected abstract SyntaxToken GetDeclarationToken(SyntaxNode declarationNode);
 
    protected abstract string GlobalImportsTitle { get; }
 
    public async ValueTask<ImmutableArray<InheritanceMarginItem>> GetInheritanceMemberItemsAsync(
        Document document,
        TextSpan spanToSearch,
        bool includeGlobalImports,
        bool frozenPartialSemantics,
        CancellationToken cancellationToken)
    {
        var solution = document.Project.Solution;
        var remoteClient = await RemoteHostClient.TryGetClientAsync(solution.Services, cancellationToken).ConfigureAwait(false);
        if (remoteClient != null)
        {
            // Also, make it clear to the remote side that they should be using frozen semantics, just like we are.
            // we want results quickly, without waiting for the entire source generator pass to run.  The user will still get
            // accurate results in the future because taggers are set to recompute when compilations are fully
            // available on the OOP side.
            var result = await remoteClient.TryInvokeAsync<IRemoteInheritanceMarginService, ImmutableArray<InheritanceMarginItem>>(
                solution,
                (service, solutionInfo, cancellationToken) =>
                    service.GetInheritanceMarginItemsAsync(solutionInfo, document.Id, spanToSearch, includeGlobalImports, frozenPartialSemantics, cancellationToken),
                cancellationToken).ConfigureAwait(false);
 
            if (!result.HasValue)
            {
                return [];
            }
 
            return result.Value;
        }
        else
        {
            return await GetInheritanceMarginItemsInProcessAsync(
                document,
                spanToSearch,
                includeGlobalImports,
                frozenPartialSemantics,
                cancellationToken).ConfigureAwait(false);
        }
    }
 
    private static bool CanHaveInheritanceTarget(ISymbol symbol)
    {
        if (symbol is INamedTypeSymbol namedType)
        {
            return !symbol.IsStatic && namedType.TypeKind is TypeKind.Interface or TypeKind.Class or TypeKind.Struct;
        }
 
        if (symbol is IEventSymbol or IPropertySymbol
            or IMethodSymbol
            {
                MethodKind: MethodKind.Ordinary or MethodKind.ExplicitInterfaceImplementation or MethodKind.UserDefinedOperator or MethodKind.Conversion
            })
        {
            return true;
        }
 
        return false;
    }
}