File: Progression\CSharpProgressionLanguageService.cs
Web Access
Project: src\src\VisualStudio\CSharp\Impl\Microsoft.VisualStudio.LanguageServices.CSharp_lqzfqcu5_wpftmp.csproj (Microsoft.VisualStudio.LanguageServices.CSharp)
// 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.
 
#nullable disable
 
using System;
using System.Collections.Generic;
using System.Composition;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.VisualStudio.LanguageServices.Implementation.Progression;
 
namespace Microsoft.VisualStudio.LanguageServices.CSharp.Progression
{
    [ExportLanguageService(typeof(IProgressionLanguageService), LanguageNames.CSharp), Shared]
    internal partial class CSharpProgressionLanguageService : IProgressionLanguageService
    {
        private static readonly SymbolDisplayFormat s_descriptionFormat = new(
            globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.OmittedAsContaining,
            typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
            genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
            memberOptions: SymbolDisplayMemberOptions.IncludeParameters |
                           SymbolDisplayMemberOptions.IncludeContainingType,
            parameterOptions: SymbolDisplayParameterOptions.IncludeType |
                              SymbolDisplayParameterOptions.IncludeParamsRefOut |
                              SymbolDisplayParameterOptions.IncludeOptionalBrackets,
            miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes);
 
        private static readonly SymbolDisplayFormat s_labelFormat = new(
            genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
            memberOptions: SymbolDisplayMemberOptions.IncludeParameters |
                           SymbolDisplayMemberOptions.IncludeExplicitInterface,
            parameterOptions: SymbolDisplayParameterOptions.IncludeType |
                              SymbolDisplayParameterOptions.IncludeParamsRefOut |
                              SymbolDisplayParameterOptions.IncludeOptionalBrackets,
            delegateStyle: SymbolDisplayDelegateStyle.NameAndParameters,
            miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes);
 
        [ImportingConstructor]
        [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
        public CSharpProgressionLanguageService()
        {
        }
 
        public IEnumerable<SyntaxNode> GetTopLevelNodesFromDocument(SyntaxNode root, CancellationToken cancellationToken)
        {
            // We implement this method lazily so we are able to abort as soon as we need to.
            if (!cancellationToken.IsCancellationRequested)
            {
                using var _ = ArrayBuilder<SyntaxNode>.GetInstance(out var nodes);
                nodes.Push(root);
 
                while (nodes.TryPop(out var node))
                {
                    if (!cancellationToken.IsCancellationRequested)
                    {
                        if (node.Kind() is SyntaxKind.ClassDeclaration or
                            SyntaxKind.RecordDeclaration or
                            SyntaxKind.RecordStructDeclaration or
                            SyntaxKind.DelegateDeclaration or
                            SyntaxKind.EnumDeclaration or
                            SyntaxKind.InterfaceDeclaration or
                            SyntaxKind.StructDeclaration or
                            SyntaxKind.VariableDeclarator or
                            SyntaxKind.MethodDeclaration or
                            SyntaxKind.PropertyDeclaration)
                        {
                            yield return node;
                        }
                        else
                        {
                            foreach (var child in node.ChildNodes())
                            {
                                nodes.Push(child);
                            }
                        }
                    }
                }
            }
        }
 
        public string GetDescriptionForSymbol(ISymbol symbol, bool includeContainingSymbol)
            => GetSymbolText(symbol, includeContainingSymbol, s_descriptionFormat);
 
        public string GetLabelForSymbol(ISymbol symbol, bool includeContainingSymbol)
            => GetSymbolText(symbol, includeContainingSymbol, s_labelFormat);
 
        private static string GetSymbolText(ISymbol symbol, bool includeContainingSymbol, SymbolDisplayFormat displayFormat)
        {
            var label = symbol.ToDisplayString(displayFormat);
 
            var typeToShow = GetType(symbol);
 
            if (typeToShow != null)
            {
                label += " : " + typeToShow.ToDisplayString(s_labelFormat);
            }
 
            if (includeContainingSymbol && symbol.ContainingSymbol != null)
            {
                label += " (" + symbol.ContainingSymbol.ToDisplayString(s_labelFormat) + ")";
            }
 
            return label;
        }
 
        private static ITypeSymbol GetType(ISymbol symbol)
        {
            switch (symbol)
            {
                case IEventSymbol f: return f.Type;
                case IFieldSymbol f: return f.ContainingType.TypeKind == TypeKind.Enum ? null : f.Type;
                case IMethodSymbol m: return IncludeReturnType(m) ? m.ReturnType : null;
                case IPropertySymbol p: return p.Type;
                case INamedTypeSymbol n: return n.IsDelegateType() ? n.DelegateInvokeMethod.ReturnType : null;
                default: return null;
            }
        }
 
        private static bool IncludeReturnType(IMethodSymbol f)
            => f.MethodKind is MethodKind.Ordinary or MethodKind.ExplicitInterfaceImplementation;
    }
}