From 6f662bda5410a7e9ff6c7958a7cdd3b5f63a64c4 Mon Sep 17 00:00:00 2001 From: Matt Parker <61717342+MattParkerDev@users.noreply.github.com> Date: Sat, 18 Oct 2025 16:31:56 +1000 Subject: [PATCH] Make RoslynAnalysis non-static --- .../Features/Analysis/RoslynAnalysis.cs | 39 ++++++++++--------- .../FilePersistence/IdeOpenTabsFileManager.cs | 6 ++- .../FileWatching/IdeFileSavedToDiskHandler.cs | 12 +++--- src/SharpIDE.Godot/DiAutoload.cs | 2 + .../Features/CodeEditor/SharpIdeCodeEdit.cs | 34 ++++++++-------- .../ContextMenus/ProjectContextMenu.cs | 1 + src/SharpIDE.Godot/IdeRoot.cs | 3 +- .../Problems/ProjectProblemComponent.razor | 2 + src/SharpIDE.Photino/Layout/MainLayout.razor | 1 + src/SharpIDE.Photino/Program.cs | 2 + 10 files changed, 59 insertions(+), 43 deletions(-) diff --git a/src/SharpIDE.Application/Features/Analysis/RoslynAnalysis.cs b/src/SharpIDE.Application/Features/Analysis/RoslynAnalysis.cs index 929d324..b9f3681 100644 --- a/src/SharpIDE.Application/Features/Analysis/RoslynAnalysis.cs +++ b/src/SharpIDE.Application/Features/Analysis/RoslynAnalysis.cs @@ -29,17 +29,18 @@ using DiagnosticSeverity = Microsoft.CodeAnalysis.DiagnosticSeverity; namespace SharpIDE.Application.Features.Analysis; -public static class RoslynAnalysis +public class RoslynAnalysis { public static AdhocWorkspace? _workspace; private static CustomMsBuildProjectLoader? _msBuildProjectLoader; private static RemoteSnapshotManager? _snapshotManager; private static RemoteSemanticTokensLegendService? _semanticTokensLegendService; - private static SharpIdeSolutionModel? _sharpIdeSolutionModel; private static HashSet _codeFixProviders = []; private static HashSet _codeRefactoringProviders = []; - private static TaskCompletionSource _solutionLoadedTcs = null!; - public static void StartSolutionAnalysis(SharpIdeSolutionModel solutionModel) + + private TaskCompletionSource _solutionLoadedTcs = null!; + private SharpIdeSolutionModel? _sharpIdeSolutionModel; + public void StartSolutionAnalysis(SharpIdeSolutionModel solutionModel) { _solutionLoadedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); _ = Task.Run(async () => @@ -54,7 +55,7 @@ public static class RoslynAnalysis } }); } - public static async Task Analyse(SharpIdeSolutionModel solutionModel, CancellationToken cancellationToken = default) + public async Task Analyse(SharpIdeSolutionModel solutionModel, CancellationToken cancellationToken = default) { Console.WriteLine($"RoslynAnalysis: Loading solution"); using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(Analyse)}"); @@ -150,7 +151,7 @@ public static class RoslynAnalysis /// 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) + public async Task ReloadSolution(CancellationToken cancellationToken = default) { Console.WriteLine($"RoslynAnalysis: Reloading Solution"); using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(ReloadSolution)}"); @@ -177,7 +178,7 @@ public static class RoslynAnalysis /// Callers should call UpdateSolutionDiagnostics after this /// Ensure that the SharpIdeSolutionModel has been updated before calling this and any subsequent calls - public static async Task ReloadProject(SharpIdeProjectModel projectModel, CancellationToken cancellationToken = default) + public async Task ReloadProject(SharpIdeProjectModel projectModel, CancellationToken cancellationToken = default) { Console.WriteLine($"RoslynAnalysis: Reloading Project {projectModel.FilePath}"); using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(ReloadSolution)}"); @@ -260,7 +261,7 @@ public static class RoslynAnalysis }).ToImmutableArray(); } - public static async Task UpdateSolutionDiagnostics() + public async Task UpdateSolutionDiagnostics() { Console.WriteLine("RoslynAnalysis: Updating solution diagnostics"); var timer = Stopwatch.StartNew(); @@ -277,7 +278,7 @@ public static class RoslynAnalysis Console.WriteLine($"RoslynAnalysis: Solution diagnostics updated in {timer.ElapsedMilliseconds}ms"); } - public static async Task> GetProjectDiagnostics(SharpIdeProjectModel projectModel) + public async Task> GetProjectDiagnostics(SharpIdeProjectModel projectModel) { using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(GetProjectDiagnostics)}"); await _solutionLoadedTcs.Task; @@ -291,7 +292,7 @@ public static class RoslynAnalysis return diagnostics; } - public static async Task> GetProjectDiagnosticsForFile(SharpIdeFile sharpIdeFile) + public async Task> GetProjectDiagnosticsForFile(SharpIdeFile sharpIdeFile) { using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(GetProjectDiagnosticsForFile)}"); await _solutionLoadedTcs.Task; @@ -310,7 +311,7 @@ public static class RoslynAnalysis return diagnostics; } - public static async Task> GetDocumentDiagnostics(SharpIdeFile fileModel, CancellationToken cancellationToken = default) + public async Task> GetDocumentDiagnostics(SharpIdeFile fileModel, CancellationToken cancellationToken = default) { if (fileModel.IsRoslynWorkspaceFile is false) return []; using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(GetDocumentDiagnostics)}"); @@ -349,7 +350,7 @@ public static class RoslynAnalysis } public record SharpIdeRazorMappedClassifiedSpan(SharpIdeRazorSourceSpan SourceSpanInRazor, string CsharpClassificationType); - public static async Task> GetRazorDocumentSyntaxHighlighting(SharpIdeFile fileModel, CancellationToken cancellationToken = default) + public async Task> GetRazorDocumentSyntaxHighlighting(SharpIdeFile fileModel, CancellationToken cancellationToken = default) { using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(GetRazorDocumentSyntaxHighlighting)}"); await _solutionLoadedTcs.Task; @@ -457,7 +458,7 @@ public static class RoslynAnalysis } // This is expensive for files that have just been updated, making it suboptimal for real-time highlighting - public static async Task> GetDocumentSyntaxHighlighting(SharpIdeFile fileModel, CancellationToken cancellationToken = default) + public async Task> GetDocumentSyntaxHighlighting(SharpIdeFile fileModel, CancellationToken cancellationToken = default) { using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(GetDocumentSyntaxHighlighting)}"); await _solutionLoadedTcs.Task; @@ -479,7 +480,7 @@ public static class RoslynAnalysis return result; } - public static async Task GetCodeCompletionsForDocumentAtPosition(SharpIdeFile fileModel, LinePosition linePosition) + public async Task GetCodeCompletionsForDocumentAtPosition(SharpIdeFile fileModel, LinePosition linePosition) { using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(GetCodeCompletionsForDocumentAtPosition)}"); await _solutionLoadedTcs.Task; @@ -490,7 +491,7 @@ public static class RoslynAnalysis return completions; } - public static async Task> GetCodeFixesForDocumentAtPosition(SharpIdeFile fileModel, LinePosition linePosition, CancellationToken cancellationToken = default) + public async Task> GetCodeFixesForDocumentAtPosition(SharpIdeFile fileModel, LinePosition linePosition, CancellationToken cancellationToken = default) { using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(GetCodeFixesForDocumentAtPosition)}"); await _solutionLoadedTcs.Task; @@ -575,9 +576,10 @@ public static class RoslynAnalysis } /// Returns the list of files modified by applying the code action - public static async Task> ApplyCodeActionAsync(CodeAction codeAction) + public async Task> ApplyCodeActionAsync(CodeAction codeAction) { using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(ApplyCodeActionAsync)}"); + await _solutionLoadedTcs.Task; var cancellationToken = CancellationToken.None; var operations = await codeAction.GetOperationsAsync(cancellationToken); var changedDocumentIds = new List(); @@ -617,7 +619,7 @@ public static class RoslynAnalysis return changedFilesWithText; } - public static async Task<(ISymbol?, LinePositionSpan?)> LookupSymbol(SharpIdeFile fileModel, LinePosition linePosition) + public async Task<(ISymbol?, LinePositionSpan?)> LookupSymbol(SharpIdeFile fileModel, LinePosition linePosition) { await _solutionLoadedTcs.Task; var (symbol, linePositionSpan) = fileModel switch @@ -699,9 +701,10 @@ public static class RoslynAnalysis return null; } - public static async Task UpdateDocument(SharpIdeFile fileModel, string newContent) + public async Task UpdateDocument(SharpIdeFile fileModel, string newContent) { using var _ = SharpIdeOtel.Source.StartActivity($"{nameof(RoslynAnalysis)}.{nameof(UpdateDocument)}"); + await _solutionLoadedTcs.Task; Guard.Against.Null(fileModel, nameof(fileModel)); Guard.Against.NullOrEmpty(newContent, nameof(newContent)); diff --git a/src/SharpIDE.Application/Features/FilePersistence/IdeOpenTabsFileManager.cs b/src/SharpIDE.Application/Features/FilePersistence/IdeOpenTabsFileManager.cs index 4f56064..2b6dcc5 100644 --- a/src/SharpIDE.Application/Features/FilePersistence/IdeOpenTabsFileManager.cs +++ b/src/SharpIDE.Application/Features/FilePersistence/IdeOpenTabsFileManager.cs @@ -7,8 +7,10 @@ namespace SharpIDE.Application.Features.FilePersistence; #pragma warning disable VSTHRD011 /// Holds the in memory copies of files, and manages saving/loading them to/from disk. -public class IdeOpenTabsFileManager +public class IdeOpenTabsFileManager(RoslynAnalysis roslynAnalysis) { + private readonly RoslynAnalysis _roslynAnalysis = roslynAnalysis; + private ConcurrentDictionary>> _openFiles = new(); /// Implicitly 'opens' a file if not already open, and returns the text. @@ -34,7 +36,7 @@ public class IdeOpenTabsFileManager // Potentially should be event based? if (file.IsRoslynWorkspaceFile) { - await RoslynAnalysis.UpdateDocument(file, newText); + await _roslynAnalysis.UpdateDocument(file, newText); GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget(); } } diff --git a/src/SharpIDE.Application/Features/FileWatching/IdeFileSavedToDiskHandler.cs b/src/SharpIDE.Application/Features/FileWatching/IdeFileSavedToDiskHandler.cs index b457cbf..bc8ceda 100644 --- a/src/SharpIDE.Application/Features/FileWatching/IdeFileSavedToDiskHandler.cs +++ b/src/SharpIDE.Application/Features/FileWatching/IdeFileSavedToDiskHandler.cs @@ -10,11 +10,13 @@ namespace SharpIDE.Application.Features.FileWatching; public class IdeFileSavedToDiskHandler { private readonly IdeOpenTabsFileManager _openTabsFileManager; + private readonly RoslynAnalysis _roslynAnalysis; public SharpIdeSolutionModel SolutionModel { get; set; } = null!; - public IdeFileSavedToDiskHandler(IdeOpenTabsFileManager openTabsFileManager) + public IdeFileSavedToDiskHandler(IdeOpenTabsFileManager openTabsFileManager, RoslynAnalysis roslynAnalysis) { _openTabsFileManager = openTabsFileManager; + _roslynAnalysis = roslynAnalysis; GlobalEvents.Instance.IdeFileSavedToDisk.Subscribe(HandleIdeFileChanged); } @@ -35,8 +37,8 @@ public class IdeFileSavedToDiskHandler var project = SolutionModel.AllProjects.SingleOrDefault(p => p.FilePath == file.Path); if (project is null) return; await ProjectEvaluation.ReloadProject(file.Path); - await RoslynAnalysis.ReloadProject(project); - await RoslynAnalysis.UpdateSolutionDiagnostics(); + await _roslynAnalysis.ReloadProject(project); + await _roslynAnalysis.UpdateSolutionDiagnostics(); } private async Task HandleWorkspaceFileChanged(SharpIdeFile file) @@ -48,9 +50,9 @@ public class IdeFileSavedToDiskHandler var fileText = wasOpenAndUpdated ? await _openTabsFileManager.GetFileTextAsync(file) : await File.ReadAllTextAsync(file.Path); - await RoslynAnalysis.UpdateDocument(file, fileText); + await _roslynAnalysis.UpdateDocument(file, fileText); GlobalEvents.Instance.SolutionAltered.InvokeParallelFireAndForget(); } - await RoslynAnalysis.UpdateSolutionDiagnostics(); + await _roslynAnalysis.UpdateSolutionDiagnostics(); } } diff --git a/src/SharpIDE.Godot/DiAutoload.cs b/src/SharpIDE.Godot/DiAutoload.cs index 6b3dbd4..8ef9f88 100644 --- a/src/SharpIDE.Godot/DiAutoload.cs +++ b/src/SharpIDE.Godot/DiAutoload.cs @@ -1,6 +1,7 @@ using Godot; using System.Reflection; using Microsoft.Extensions.DependencyInjection; +using SharpIDE.Application.Features.Analysis; using SharpIDE.Application.Features.Build; using SharpIDE.Application.Features.FilePersistence; using SharpIDE.Application.Features.FileWatching; @@ -27,6 +28,7 @@ public partial class DiAutoload : Node services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); _serviceProvider = services.BuildServiceProvider(); GetTree().NodeAdded += OnNodeAdded; diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit.cs b/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit.cs index e34218d..b48433d 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit.cs @@ -43,7 +43,7 @@ public partial class SharpIdeCodeEdit : CodeEdit [Inject] private readonly IdeOpenTabsFileManager _openTabsFileManager = null!; [Inject] private readonly RunService _runService = null!; - + [Inject] private readonly RoslynAnalysis _roslynAnalysis = null!; public override void _Ready() { @@ -66,9 +66,9 @@ public partial class SharpIdeCodeEdit : CodeEdit { if (_currentFile is null) return; GD.Print("Solution altered, updating project diagnostics for current file"); - var documentDiagnostics = await RoslynAnalysis.GetDocumentDiagnostics(_currentFile); + var documentDiagnostics = await _roslynAnalysis.GetDocumentDiagnostics(_currentFile); await this.InvokeAsync(() => SetDiagnostics(documentDiagnostics)); - var projectDiagnostics = await RoslynAnalysis.GetProjectDiagnosticsForFile(_currentFile); + var projectDiagnostics = await _roslynAnalysis.GetProjectDiagnosticsForFile(_currentFile); await this.InvokeAsync(() => SetProjectDiagnostics(projectDiagnostics)); } @@ -153,7 +153,7 @@ public partial class SharpIdeCodeEdit : CodeEdit var lineHeight = GetLineHeight(); GD.Print($"Symbol hovered: {symbol} at line {line}, column {column}"); - var (roslynSymbol, linePositionSpan) = await RoslynAnalysis.LookupSymbol(_currentFile, new LinePosition((int)line, (int)column)); + var (roslynSymbol, linePositionSpan) = await _roslynAnalysis.LookupSymbol(_currentFile, new LinePosition((int)line, (int)column)); if (roslynSymbol is null || linePositionSpan is null) { return; @@ -277,15 +277,15 @@ public partial class SharpIdeCodeEdit : CodeEdit _textChangedCts = new CancellationTokenSource(); _ = Task.GodotRun(async () => { - var syntaxHighlighting = RoslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile, _textChangedCts.Token); - var razorSyntaxHighlighting = RoslynAnalysis.GetRazorDocumentSyntaxHighlighting(_currentFile, _textChangedCts.Token); + var syntaxHighlighting = _roslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile, _textChangedCts.Token); + var razorSyntaxHighlighting = _roslynAnalysis.GetRazorDocumentSyntaxHighlighting(_currentFile, _textChangedCts.Token); await Task.WhenAll(syntaxHighlighting, razorSyntaxHighlighting); await this.InvokeAsync(async () => SetSyntaxHighlightingModel(await syntaxHighlighting, await razorSyntaxHighlighting)); __?.Dispose(); }); _ = Task.GodotRun(async () => { - var documentDiagnostics = await RoslynAnalysis.GetDocumentDiagnostics(_currentFile, _textChangedCts.Token); + var documentDiagnostics = await _roslynAnalysis.GetDocumentDiagnostics(_currentFile, _textChangedCts.Token); await this.InvokeAsync(() => SetDiagnostics(documentDiagnostics)); }); }); @@ -300,7 +300,7 @@ public partial class SharpIdeCodeEdit : CodeEdit _ = Task.GodotRun(async () => { - var affectedFiles = await RoslynAnalysis.ApplyCodeActionAsync(codeAction); + var affectedFiles = await _roslynAnalysis.ApplyCodeActionAsync(codeAction); // TODO: This can be more efficient - we can just update in memory and proceed with highlighting etc. Save to disk in background. foreach (var (affectedFile, updatedText) in affectedFiles) { @@ -313,9 +313,9 @@ public partial class SharpIdeCodeEdit : CodeEdit private async Task OnFileChangedExternallyInMemory() { var fileContents = await _openTabsFileManager.GetFileTextAsync(_currentFile); - var syntaxHighlighting = RoslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile); - var razorSyntaxHighlighting = RoslynAnalysis.GetRazorDocumentSyntaxHighlighting(_currentFile); - var diagnostics = RoslynAnalysis.GetDocumentDiagnostics(_currentFile); + var syntaxHighlighting = _roslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile); + var razorSyntaxHighlighting = _roslynAnalysis.GetRazorDocumentSyntaxHighlighting(_currentFile); + var diagnostics = _roslynAnalysis.GetDocumentDiagnostics(_currentFile); await Task.WhenAll(syntaxHighlighting, razorSyntaxHighlighting, diagnostics); Callable.From(() => { @@ -351,10 +351,10 @@ public partial class SharpIdeCodeEdit : CodeEdit _currentFile.FileContentsChangedExternally.Subscribe(OnFileChangedExternallyInMemory); _currentFile.FileContentsChangedExternallyFromDisk.Subscribe(OnFileChangedExternallyFromDisk); - var syntaxHighlighting = RoslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile); - var razorSyntaxHighlighting = RoslynAnalysis.GetRazorDocumentSyntaxHighlighting(_currentFile); - var diagnostics = RoslynAnalysis.GetDocumentDiagnostics(_currentFile); - var projectDiagnosticsForFile = RoslynAnalysis.GetProjectDiagnosticsForFile(_currentFile); + var syntaxHighlighting = _roslynAnalysis.GetDocumentSyntaxHighlighting(_currentFile); + var razorSyntaxHighlighting = _roslynAnalysis.GetRazorDocumentSyntaxHighlighting(_currentFile); + var diagnostics = _roslynAnalysis.GetDocumentDiagnostics(_currentFile); + var projectDiagnosticsForFile = _roslynAnalysis.GetProjectDiagnosticsForFile(_currentFile); var setTextTask = this.InvokeAsync(async () => { _fileChangingSuppressBreakpointToggleEvent = true; @@ -503,7 +503,7 @@ public partial class SharpIdeCodeEdit : CodeEdit _ = Task.GodotRun(async () => { var linePos = new LinePosition(caretLine, caretColumn); - var codeActions = await RoslynAnalysis.GetCodeFixesForDocumentAtPosition(_currentFile, linePos); + var codeActions = await _roslynAnalysis.GetCodeFixesForDocumentAtPosition(_currentFile, linePos); await this.InvokeAsync(() => { _popupMenu.Clear(); @@ -529,7 +529,7 @@ public partial class SharpIdeCodeEdit : CodeEdit { var linePos = new LinePosition(caretLine, caretColumn); - var completions = await RoslynAnalysis.GetCodeCompletionsForDocumentAtPosition(_currentFile, linePos); + var completions = await _roslynAnalysis.GetCodeCompletionsForDocumentAtPosition(_currentFile, linePos); await this.InvokeAsync(() => { foreach (var completionItem in completions.ItemsList) diff --git a/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/ProjectContextMenu.cs b/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/ProjectContextMenu.cs index 4bc83fa..c3c92fe 100644 --- a/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/ProjectContextMenu.cs +++ b/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/ProjectContextMenu.cs @@ -21,6 +21,7 @@ file enum ProjectContextMenuOptions public partial class SolutionExplorerPanel { private Texture2D _runIcon = ResourceLoader.Load("uid://bkty6563cthj8"); + [Inject] private readonly BuildService _buildService = null!; [Inject] private readonly RunService _runService = null!; diff --git a/src/SharpIDE.Godot/IdeRoot.cs b/src/SharpIDE.Godot/IdeRoot.cs index 165a6a6..ce98bdc 100644 --- a/src/SharpIDE.Godot/IdeRoot.cs +++ b/src/SharpIDE.Godot/IdeRoot.cs @@ -43,6 +43,7 @@ public partial class IdeRoot : Control [Inject] private readonly IdeFileWatcher _fileWatcher = null!; [Inject] private readonly BuildService _buildService = null!; [Inject] private readonly IdeOpenTabsFileManager _openTabsFileManager = null!; + [Inject] private readonly RoslynAnalysis _roslynAnalysis = null!; public override void _EnterTree() { @@ -141,7 +142,7 @@ public partial class IdeRoot : Control _fileExternalChangeHandler.SolutionModel = solutionModel; _savedToDiskHandler.SolutionModel = solutionModel; Callable.From(_solutionExplorerPanel.RepopulateTree).CallDeferred(); - RoslynAnalysis.StartSolutionAnalysis(solutionModel); + _roslynAnalysis.StartSolutionAnalysis(solutionModel); _fileWatcher.StartWatching(solutionModel); var infraProject = solutionModel.AllProjects.SingleOrDefault(s => s.Name == "WebUi"); diff --git a/src/SharpIDE.Photino/Components/Problems/ProjectProblemComponent.razor b/src/SharpIDE.Photino/Components/Problems/ProjectProblemComponent.razor index c9df6c4..0d07ccb 100644 --- a/src/SharpIDE.Photino/Components/Problems/ProjectProblemComponent.razor +++ b/src/SharpIDE.Photino/Components/Problems/ProjectProblemComponent.razor @@ -4,6 +4,8 @@ @using SharpIDE.Application.Features.SolutionDiscovery @using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence +@inject RoslynAnalysis RoslynAnalysis + @if (_diagnostics.Length is not 0) { diff --git a/src/SharpIDE.Photino/Layout/MainLayout.razor b/src/SharpIDE.Photino/Layout/MainLayout.razor index 88c32aa..72dcb04 100644 --- a/src/SharpIDE.Photino/Layout/MainLayout.razor +++ b/src/SharpIDE.Photino/Layout/MainLayout.razor @@ -9,6 +9,7 @@ @inject IDialogService DialogService @inject BuildService BuildService @inject AppState AppState +@inject RoslynAnalysis RoslynAnalysis diff --git a/src/SharpIDE.Photino/Program.cs b/src/SharpIDE.Photino/Program.cs index af35773..9e92790 100644 --- a/src/SharpIDE.Photino/Program.cs +++ b/src/SharpIDE.Photino/Program.cs @@ -3,6 +3,7 @@ using Microsoft.Build.Locator; using Microsoft.Extensions.DependencyInjection; using MudBlazor.Services; using Photino.Blazor; +using SharpIDE.Application.Features.Analysis; using SharpIDE.Application.Features.Build; using SharpIDE.Application.Features.Run; using SharpIDE.Photino.Models; @@ -23,6 +24,7 @@ public class Program appBuilder.Services.AddSingleton(); appBuilder.Services.AddSingleton(); appBuilder.Services.AddSingleton(); + appBuilder.Services.AddSingleton(); appBuilder.RootComponents.Add("app");