| File: MSBuild\ProjectFileExtensionRegistry.cs | Web Access |
| Project: Microsoft.CodeAnalysis.Workspaces.MSBuild.csproj (Microsoft.CodeAnalysis.Workspaces.MSBuild) |
// 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.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.IO; using Microsoft.CodeAnalysis.FileBasedPrograms; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.MSBuild; internal sealed class ProjectFileExtensionRegistry { private readonly DiagnosticReporter _diagnosticReporter; private readonly IFileBasedProgramService? _fileBasedProgramService; private readonly Dictionary<string, string> _extensionToLanguageMap; private readonly NonReentrantLock _dataGuard; public ProjectFileExtensionRegistry(DiagnosticReporter diagnosticReporter, IFileBasedProgramService? fileBasedProgramService) { _diagnosticReporter = diagnosticReporter; _fileBasedProgramService = fileBasedProgramService; _extensionToLanguageMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { ".csproj", LanguageNames.CSharp }, { ".vbproj", LanguageNames.VisualBasic }, { ".fsproj", LanguageNames.FSharp } }; _dataGuard = new NonReentrantLock(); } /// <summary> /// Associates a project file extension with a language name. /// </summary> public void AssociateFileExtensionWithLanguage(string fileExtension, string language) { using (_dataGuard.DisposableWait()) { _extensionToLanguageMap[AddLeadingDot(fileExtension)] = language; } } /// <summary> /// Gets the registered project file extensions. Non-empty extensions have a leading '.'. /// </summary> public ImmutableArray<string> GetRegisteredProjectFileExtensions() { using (_dataGuard.DisposableWait()) { return [.. _extensionToLanguageMap.Keys]; } } /// <summary> /// Tries to get the language registered for an extension, with or without a leading '.'. /// </summary> public bool TryGetLanguageNameFromExtension(string extension, [NotNullWhen(true)] out string? languageName) { using (_dataGuard.DisposableWait()) { return _extensionToLanguageMap.TryGetValue(AddLeadingDot(extension), out languageName); } } private static string AddLeadingDot(string extension) => extension.Length == 0 || extension[0] == '.' ? extension : "." + extension; public bool TryGetLanguageNameFromProjectPath(string? projectFilePath, DiagnosticReportingMode mode, [NotNullWhen(true)] out string? languageName) => TryGetLanguageNameFromProjectPath(projectFilePath, mode, out languageName, out _); public bool TryGetLanguageNameFromProjectPath( string? projectFilePath, DiagnosticReportingMode mode, [NotNullWhen(true)] out string? languageName, out bool isFileBasedApp) { if (projectFilePath is null) { languageName = null; isFileBasedApp = false; _diagnosticReporter.Report(mode, "Project file path is null."); return false; } var projectFileExtension = Path.GetExtension(projectFilePath); if (TryGetLanguageNameFromExtension(projectFileExtension, out languageName)) { isFileBasedApp = false; return true; } if (_fileBasedProgramService?.IsValidEntryPointPath(projectFilePath) == true) { languageName = LanguageNames.CSharp; isFileBasedApp = true; return true; } isFileBasedApp = false; _diagnosticReporter.Report(mode, string.Format(WorkspacesResources.Cannot_open_project_0_because_the_file_extension_1_is_not_associated_with_a_language, projectFilePath, projectFileExtension)); return false; } }