/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/FileBasedPrograms/CanonicalMiscellaneousFilesProjectProvider.cs
88 строк
4 KB
Jan Jones
Allow MSBuildWorkspace to open file-based apps (#84139)
30 июл 2026, 11:03
Не верифицирован
30 июл 2026, 11:03
7e7ebef
Код
Авторство
О чём код?
// 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.Immutable; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.LanguageServer.HostWorkspace; using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.Extensions.Logging; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.LanguageServer.FileBasedPrograms; internal sealed class CanonicalMiscellaneousFilesProjectProvider : IDisposable { private readonly IHostWorkspaceProvider _workspaceProvider; private readonly ILoggerFactory _loggerFactory; private readonly AsyncLazy<ImmutableArray<ProjectFileInfo>> _canonicalBuildResult; private string? _tempDirectory; public CanonicalMiscellaneousFilesProjectProvider(IHostWorkspaceProvider workspaceProvider, ILoggerFactory loggerFactory) { _workspaceProvider = workspaceProvider; _loggerFactory = loggerFactory; _canonicalBuildResult = AsyncLazy.Create(LoadCanonicalProjectAsync); } public async Task<ImmutableArray<ProjectFileInfo>> GetProjectInfoAsync(string miscDocumentPath, CancellationToken cancellationToken) { var canonicalInfos = await _canonicalBuildResult.GetValueAsync(cancellationToken); var miscDocFileInfo = new DocumentFileInfo( filePath: miscDocumentPath, logicalPath: Path.GetFileName(miscDocumentPath), isLinked: false, isGenerated: false, folders: []); var forkedInfos = canonicalInfos.SelectAsArray(info => info with { Documents = [.. info.Documents, miscDocFileInfo], FileGlobs = [], }); return forkedInfos; } private async Task<ImmutableArray<ProjectFileInfo>> LoadCanonicalProjectAsync(CancellationToken cancellationToken) { // Set the FileBasedProgram feature flag so that '#:' is permitted without errors in rich misc files. // This allows us to avoid spurious errors for files which contain '#:' directives yet are not treated // as file-based programs (due to not being saved to disk, for example.) var virtualProjectXml = $""" <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net$(BundledNETCoreAppTargetFrameworkVersion)</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <Features>$(Features);FileBasedProgram</Features> </PropertyGroup> </Project> """; _tempDirectory = Path.Combine(Path.GetTempPath(), "roslyn-canonical-misc", Guid.NewGuid().ToString()); Directory.CreateDirectory(_tempDirectory); var virtualProjectPath = Path.Combine(_tempDirectory, "Canonical.csproj"); // Write the csproj to disk so we can run restore on it later (required for SDKs prior to .NET 10) File.WriteAllText(virtualProjectPath, virtualProjectXml); await using var buildHostProcessManager = new BuildHostProcessManager( _workspaceProvider.Workspace.Services.SolutionServices.GetSupportedLanguages<ICommandLineParserService>(), globalMSBuildProperties: [], binaryLogPathProvider: null, loggerFactory: _loggerFactory); var buildHost = await buildHostProcessManager.GetBuildHostAsync(BuildHostProcessKind.NetCore, virtualProjectPath, dotnetPath: null, cancellationToken); var loadedFile = await buildHost.LoadProjectAsync(virtualProjectPath, physicalFilePath: null, virtualProjectXml, languageName: LanguageNames.CSharp, globalProperties: null, cancellationToken); return await loadedFile.GetProjectFileInfosAsync(cancellationToken); } public void Dispose() { if (_tempDirectory is not null) { IOUtilities.PerformIO(() => Directory.Delete(_tempDirectory, recursive: true)); } } }