File: LanguageInfoProvider.cs
Web Access
Project: src\src\LanguageServer\Protocol\Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj (Microsoft.CodeAnalysis.LanguageServer.Protocol)
// 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.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using Microsoft.CodeAnalysis.Features.Workspaces;
 
namespace Microsoft.CodeAnalysis.LanguageServer;
 
internal sealed class LanguageInfoProvider : ILanguageInfoProvider
{
    // Constant so that Razor can use it (exposed via EA) otherwise their endpoints won't get hit
    public const string RazorLanguageName = "Razor";
 
    private static readonly LanguageInformation s_csharpLanguageInformation = new(LanguageNames.CSharp, ".csx");
    private static readonly LanguageInformation s_fsharpLanguageInformation = new(LanguageNames.FSharp, ".fsx");
    private static readonly LanguageInformation s_vbLanguageInformation = new(LanguageNames.VisualBasic, ".vbx");
    private static readonly LanguageInformation s_typeScriptLanguageInformation = new LanguageInformation(InternalLanguageNames.TypeScript, string.Empty);
    private static readonly LanguageInformation s_razorLanguageInformation = new(RazorLanguageName, string.Empty);
    private static readonly LanguageInformation s_xamlLanguageInformation = new("XAML", string.Empty);
 
    private static readonly Dictionary<string, LanguageInformation> s_extensionToLanguageInformation = new()
    {
        { ".cs", s_csharpLanguageInformation },
        { ".csx", s_csharpLanguageInformation },
        { ".fs", s_fsharpLanguageInformation },
        { ".fsx", s_fsharpLanguageInformation },
        { ".vb", s_vbLanguageInformation },
        { ".vbx", s_vbLanguageInformation },
        { ".cshtml", s_razorLanguageInformation },
        { ".razor", s_razorLanguageInformation },
        { ".xaml", s_xamlLanguageInformation },
        { ".ts", s_typeScriptLanguageInformation },
        { ".d.ts", s_typeScriptLanguageInformation },
        { ".tsx", s_typeScriptLanguageInformation },
        { ".js", s_typeScriptLanguageInformation },
        { ".jsx", s_typeScriptLanguageInformation },
        { ".cjs", s_typeScriptLanguageInformation },
        { ".mjs", s_typeScriptLanguageInformation },
        { ".cts", s_typeScriptLanguageInformation },
        { ".mts", s_typeScriptLanguageInformation },
    };
 
    public bool TryGetLanguageInformation(Uri uri, string? lspLanguageId, [NotNullWhen(true)] out LanguageInformation? languageInformation)
    {
        // First try to get language information from the URI path.
        // We can do this for File uris and absolute uris.  We use local path to get the value without any query parameters.
        if (uri.IsFile || uri.IsAbsoluteUri)
        {
            var localPath = uri.LocalPath;
            var extension = Path.GetExtension(localPath);
            if (s_extensionToLanguageInformation.TryGetValue(extension, out languageInformation))
            {
                return true;
            }
        }
 
        // If the URI file path mapping failed, use the languageId from the LSP client (if any).
        languageInformation = lspLanguageId switch
        {
            "csharp" => s_csharpLanguageInformation,
            "fsharp" => s_fsharpLanguageInformation,
            "vb" => s_vbLanguageInformation,
            "razor" => s_razorLanguageInformation,
            "xaml" => s_xamlLanguageInformation,
            "typescript" => s_typeScriptLanguageInformation,
            "javascript" => s_typeScriptLanguageInformation,
            _ => null,
        };
 
        return languageInformation != null;
    }
}