diff --git a/.gitignore b/.gitignore index a4e4903f1..9cba68135 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,6 @@ publish/ *.dil *.dmeta *.dpdb +/.vs/ /.vscode/ /out/ diff --git a/HotReloadUtils.slnx b/HotReloadUtils.slnx new file mode 100644 index 000000000..a4a0e4d10 --- /dev/null +++ b/HotReloadUtils.slnx @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/Microsoft.DotNet.HotReload.Utils.Generator/DeltaProject.cs b/src/Microsoft.DotNet.HotReload.Utils.Generator/DeltaProject.cs index 980e6f8ce..305d08259 100644 --- a/src/Microsoft.DotNet.HotReload.Utils.Generator/DeltaProject.cs +++ b/src/Microsoft.DotNet.HotReload.Utils.Generator/DeltaProject.cs @@ -94,18 +94,21 @@ public async Task BuildDelta (Delta delta, bool ignoreUnchanged = var updates2 = await _changeMakerService.EmitSolutionUpdateAsync (updatedSolution, ct); - if (updates2.CompilationDiagnostics.Any()) { + if (updates2.CompilationDiagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { var sb = new StringBuilder(); foreach (var diag in updates2.CompilationDiagnostics) { sb.AppendLine (diag.ToString ()); } throw new DiffyException ($"Failed to emit delta for {oldDocument.Name}: {sb}", exitStatus: 8); } + foreach (var fancyChange in updates2.ProjectUpdates) { Console.WriteLine("change service made {0}", fancyChange.ModuleId); } + _changeMakerService.CommitUpdate(); + await using (var output = makeOutputs != null ? makeOutputs(dinfo) : DefaultMakeFileOutputs(dinfo)) { if (updates2.ProjectUpdates.Length != 1) { throw new DiffyException($"Expected only one module in the delta, got {updates2.ProjectUpdates.Length}", exitStatus: 10); diff --git a/src/Microsoft.DotNet.HotReload.Utils.Generator/EnC/ChangeMakerService.cs b/src/Microsoft.DotNet.HotReload.Utils.Generator/EnC/ChangeMakerService.cs index 72c31c1c2..47c0acafe 100644 --- a/src/Microsoft.DotNet.HotReload.Utils.Generator/EnC/ChangeMakerService.cs +++ b/src/Microsoft.DotNet.HotReload.Utils.Generator/EnC/ChangeMakerService.cs @@ -169,6 +169,16 @@ public void EndSession () mi.Invoke(_watchHotReloadService, Array.Empty()); } + public void CommitUpdate() + { + var mi = _watchServiceType.GetMethod("CommitUpdate"); + if (mi == null) + { + throw new Exception($"could not find method {watchServiceName}.CommitUpdate"); + } + mi.Invoke(_watchHotReloadService, Array.Empty()); + } + public Task EmitSolutionUpdateAsync(Solution solution, CancellationToken cancellationToken) { var runningProjectInfoType = _watchServiceType.GetNestedType("RunningProjectInfo", BindingFlags.Public)!; diff --git a/tests/HotReload.Generator/EnC.Tests/TempMSBuildWorkspaceTest.cs b/tests/HotReload.Generator/EnC.Tests/TempMSBuildWorkspaceTest.cs index 7248495aa..dffc4f77f 100644 --- a/tests/HotReload.Generator/EnC.Tests/TempMSBuildWorkspaceTest.cs +++ b/tests/HotReload.Generator/EnC.Tests/TempMSBuildWorkspaceTest.cs @@ -113,7 +113,7 @@ protected async Task PrepareProject(CancellationToken cancellationToken protected void WithBaselineSource(ref Project project, string csFileName, SourceText src, out DocumentId docId) { - var d = project.AddDocument(csFileName, src); + var d = project.AddDocument(csFileName, src, filePath: Path.Combine(project.FilePath!, csFileName)); project = d.Project; docId = d.Id; } diff --git a/tests/HotReload.Generator/EnC.Tests/WatchHotReloadServiceTest.cs b/tests/HotReload.Generator/EnC.Tests/WatchHotReloadServiceTest.cs index a689eddfd..1f0331e94 100644 --- a/tests/HotReload.Generator/EnC.Tests/WatchHotReloadServiceTest.cs +++ b/tests/HotReload.Generator/EnC.Tests/WatchHotReloadServiceTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Threading.Tasks; using CancellationToken = System.Threading.CancellationToken; using System.Linq; @@ -10,6 +11,8 @@ using System.Reflection.Metadata; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Emit; +using Microsoft.CodeAnalysis.Text; +using Microsoft.DotNet.HotReload.Utils.Generator.EnC; using Xunit; @@ -26,7 +29,7 @@ public async Task SanityCheckWatchService() { var cancellationToken = CancellationToken.None; var project = await PrepareProject(cancellationToken); - var src = MakeText(""" + var src1 = MakeText(""" using System; public class C1 { public static void M1() { @@ -34,21 +37,38 @@ public static void M1() { } } """); - WithBaselineSource(ref project, "Class1.cs", src, out var d); + WithBaselineSource(ref project, "Class1.cs", src1, out var documentId); var comp = await project.GetCompilationAsync(cancellationToken); Assert.NotNull(comp); - using var peStream = new System.IO.MemoryStream(); - using var pdbStream = new System.IO.MemoryStream(); - var emitResult = comp.Emit(peStream, pdbStream); - ValidateEmitResult(emitResult); + + using (var peStream = File.OpenWrite(project.CompilationOutputInfo.AssemblyPath!)) + using (var pdbStream = File.OpenWrite(Path.ChangeExtension(project.CompilationOutputInfo.AssemblyPath!, ".pdb"))) + { + var emitResult = comp.Emit(peStream, pdbStream, options: new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb)); + ValidateEmitResult(emitResult); + } var hostWorkspaceServices = project.Solution.Workspace.Services; - var changeMakerService = Microsoft.DotNet.HotReload.Utils.Generator.EnC.ChangeMakerService.Make(hostWorkspaceServices, default); + var changeMakerService = ChangeMakerService.Make(hostWorkspaceServices, EditAndContinueCapabilities.Baseline); await changeMakerService.StartSessionAsync(project.Solution, cancellationToken); + var src2 = MakeText(""" + using System; + public class C1 { + public static void M1() { + Console.WriteLine("Updated"); + } + } + """); + + var newSolution = project.Solution.WithDocumentText(documentId, src2); + + var update = await changeMakerService.EmitSolutionUpdateAsync(newSolution, cancellationToken); + Assert.NotEmpty(update.ProjectUpdates); + + changeMakerService.CommitUpdate(); + changeMakerService.EndSession(); - // var editSession = changeMakerService.GetEditSession(); - //Assert.NotNull(editSession); } }