RoslynAnalysis ReloadSolution
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Composition.Hosting;
|
using System.Composition.Hosting;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Ardalis.GuardClauses;
|
using Ardalis.GuardClauses;
|
||||||
@@ -19,6 +19,8 @@ using Microsoft.CodeAnalysis.Shared.Utilities;
|
|||||||
using Microsoft.CodeAnalysis.Text;
|
using Microsoft.CodeAnalysis.Text;
|
||||||
using SharpIDE.Application.Features.Analysis.FixLoaders;
|
using SharpIDE.Application.Features.Analysis.FixLoaders;
|
||||||
using SharpIDE.Application.Features.Analysis.Razor;
|
using SharpIDE.Application.Features.Analysis.Razor;
|
||||||
|
using SharpIDE.Application.Features.Build;
|
||||||
|
using SharpIDE.Application.Features.Events;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery;
|
using SharpIDE.Application.Features.SolutionDiscovery;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
||||||
using SharpIDE.RazorAccess;
|
using SharpIDE.RazorAccess;
|
||||||
@@ -54,7 +56,7 @@ public static class RoslynAnalysis
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public static async Task Analyse(SharpIdeSolutionModel solutionModel)
|
public static async Task Analyse(SharpIdeSolutionModel solutionModel, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"RoslynAnalysis: Loading solution");
|
Console.WriteLine($"RoslynAnalysis: Loading solution");
|
||||||
using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(Analyse)}");
|
using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(Analyse)}");
|
||||||
@@ -84,7 +86,11 @@ public static class RoslynAnalysis
|
|||||||
}
|
}
|
||||||
using (var ___ = SharpIdeOtel.Source.StartActivity("OpenSolution"))
|
using (var ___ = SharpIdeOtel.Source.StartActivity("OpenSolution"))
|
||||||
{
|
{
|
||||||
var solutionInfo = await _msBuildProjectLoader!.LoadSolutionInfoAsync(_sharpIdeSolutionModel.FilePath);
|
//_msBuildProjectLoader!.LoadMetadataForReferencedProjects = true;
|
||||||
|
|
||||||
|
// MsBuildProjectLoader doesn't do a restore which is absolutely required for resolving PackageReferences, if they have changed. I am guessing it just reads from project.assets.json
|
||||||
|
await BuildService.Instance.MsBuildAsync(_sharpIdeSolutionModel.FilePath, BuildType.Restore, cancellationToken);
|
||||||
|
var solutionInfo = await _msBuildProjectLoader!.LoadSolutionInfoAsync(_sharpIdeSolutionModel.FilePath, cancellationToken: cancellationToken);
|
||||||
_workspace.ClearSolution();
|
_workspace.ClearSolution();
|
||||||
var solution = _workspace.AddSolution(solutionInfo);
|
var solution = _workspace.AddSolution(solutionInfo);
|
||||||
}
|
}
|
||||||
@@ -144,8 +150,37 @@ public static class RoslynAnalysis
|
|||||||
Console.WriteLine("RoslynAnalysis: Analysis completed.");
|
Console.WriteLine("RoslynAnalysis: Analysis completed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Callers should call UpdateSolutionDiagnostics after this
|
||||||
|
/// Ensure that the SharpIdeSolutionModel has been updated before calling this and any subsequent calls
|
||||||
|
public static async Task ReloadSolution(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"RoslynAnalysis: Reloading Solution");
|
||||||
|
using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(ReloadSolution)}");
|
||||||
|
await _solutionLoadedTcs.Task;
|
||||||
|
Guard.Against.Null(_workspace, nameof(_workspace));
|
||||||
|
Guard.Against.Null(_msBuildProjectLoader, nameof(_msBuildProjectLoader));
|
||||||
|
|
||||||
|
// It is important to note that a Workspace has no concept of MSBuild, nuget packages etc. It is just told about project references and "metadata" references, which are dlls. This is the what MSBuild does - it reads the csproj, and most importantly resolves nuget package references to dlls
|
||||||
|
await BuildService.Instance.MsBuildAsync(_sharpIdeSolutionModel!.FilePath, BuildType.Restore, cancellationToken);
|
||||||
|
var __ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.MSBuildProjectLoader.LoadSolutionInfoAsync");
|
||||||
|
// This call is the expensive part - MSBuild is slow. There doesn't seem to be any incrementalism for solutions.
|
||||||
|
// The best we could do to speed it up is do .LoadProjectInfoAsync for the single project, and somehow munge that into the existing solution
|
||||||
|
var newSolutionInfo = await _msBuildProjectLoader.LoadSolutionInfoAsync(_sharpIdeSolutionModel!.FilePath, cancellationToken: cancellationToken);
|
||||||
|
__?.Dispose();
|
||||||
|
|
||||||
|
var ___ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.Workspace.OnSolutionReloaded");
|
||||||
|
// There doesn't appear to be any noticeable difference between ClearSolution + AddSolution vs OnSolutionReloaded
|
||||||
|
//_workspace.OnSolutionReloaded(newSolutionInfo);
|
||||||
|
_workspace.ClearSolution();
|
||||||
|
_workspace.AddSolution(newSolutionInfo);
|
||||||
|
___?.Dispose();
|
||||||
|
Console.WriteLine("RoslynAnalysis: Solution reloaded");
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task UpdateSolutionDiagnostics()
|
public static async Task UpdateSolutionDiagnostics()
|
||||||
{
|
{
|
||||||
|
Console.WriteLine("RoslynAnalysis: Updating solution diagnostics");
|
||||||
|
var timer = Stopwatch.StartNew();
|
||||||
using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(UpdateSolutionDiagnostics)}");
|
using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(UpdateSolutionDiagnostics)}");
|
||||||
await _solutionLoadedTcs.Task;
|
await _solutionLoadedTcs.Task;
|
||||||
foreach (var project in _sharpIdeSolutionModel!.AllProjects)
|
foreach (var project in _sharpIdeSolutionModel!.AllProjects)
|
||||||
@@ -155,6 +190,8 @@ public static class RoslynAnalysis
|
|||||||
project.Diagnostics.RemoveRange(project.Diagnostics);
|
project.Diagnostics.RemoveRange(project.Diagnostics);
|
||||||
project.Diagnostics.AddRange(projectDiagnostics);
|
project.Diagnostics.AddRange(projectDiagnostics);
|
||||||
}
|
}
|
||||||
|
timer.Stop();
|
||||||
|
Console.WriteLine($"RoslynAnalysis: Solution diagnostics updated in {timer.ElapsedMilliseconds}ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<ImmutableArray<Diagnostic>> GetProjectDiagnostics(SharpIdeProjectModel projectModel)
|
public static async Task<ImmutableArray<Diagnostic>> GetProjectDiagnostics(SharpIdeProjectModel projectModel)
|
||||||
|
|||||||
@@ -16,10 +16,12 @@ public enum BuildType
|
|||||||
}
|
}
|
||||||
public class BuildService
|
public class BuildService
|
||||||
{
|
{
|
||||||
|
public static BuildService Instance { get; set; } = null!;
|
||||||
public event Func<Task> BuildStarted = () => Task.CompletedTask;
|
public event Func<Task> BuildStarted = () => Task.CompletedTask;
|
||||||
public ChannelTextWriter BuildTextWriter { get; } = new ChannelTextWriter();
|
public ChannelTextWriter BuildTextWriter { get; } = new ChannelTextWriter();
|
||||||
public async Task MsBuildAsync(string solutionOrProjectFilePath, BuildType buildType = BuildType.Build, CancellationToken cancellationToken = default)
|
public async Task MsBuildAsync(string solutionOrProjectFilePath, BuildType buildType = BuildType.Build, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(BuildService)}.{nameof(MsBuildAsync)}");
|
||||||
var normalOut = Console.Out;
|
var normalOut = Console.Out;
|
||||||
Console.SetOut(BuildTextWriter);
|
Console.SetOut(BuildTextWriter);
|
||||||
var terminalLogger = InternalTerminalLoggerFactory.CreateLogger();
|
var terminalLogger = InternalTerminalLoggerFactory.CreateLogger();
|
||||||
@@ -86,12 +88,3 @@ public class BuildService
|
|||||||
return nodesToBuildWith;
|
return nodesToBuildWith;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// To build a single project
|
|
||||||
// var solutionFile = GetNodesInSolution.ParseSolutionFileFromPath(_solutionFilePath);
|
|
||||||
// ArgumentNullException.ThrowIfNull(solutionFile);
|
|
||||||
// var projects = GetNodesInSolution.GetCSharpProjectObjectsFromSolutionFile(solutionFile);
|
|
||||||
// var projectRoot = projects.First();
|
|
||||||
// var buildRequest = new BuildRequestData(
|
|
||||||
// ProjectInstance.FromProjectRootElement(projectRoot, new ProjectOptions()),
|
|
||||||
// targetsToBuild: ["Restore", "Build"]);
|
|
||||||
|
|||||||
@@ -44,8 +44,9 @@ public partial class IdeRoot : Control
|
|||||||
{
|
{
|
||||||
GodotGlobalEvents.Instance = new GodotGlobalEvents();
|
GodotGlobalEvents.Instance = new GodotGlobalEvents();
|
||||||
GlobalEvents.Instance = new GlobalEvents();
|
GlobalEvents.Instance = new GlobalEvents();
|
||||||
|
BuildService.Instance = new BuildService(); // TODO: Sort out this mess with singletons, especially access across Application services
|
||||||
Singletons.RunService = new RunService();
|
Singletons.RunService = new RunService();
|
||||||
Singletons.BuildService = new BuildService();
|
Singletons.BuildService = BuildService.Instance;
|
||||||
Singletons.FileWatcher?.Dispose();
|
Singletons.FileWatcher?.Dispose();
|
||||||
Singletons.FileWatcher = new IdeFileWatcher();
|
Singletons.FileWatcher = new IdeFileWatcher();
|
||||||
Singletons.FileManager = new IdeFileManager();
|
Singletons.FileManager = new IdeFileManager();
|
||||||
|
|||||||
Reference in New Issue
Block a user