Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ publish/
*.dil
*.dmeta
*.dpdb
/.vs/
/.vscode/
/out/
14 changes: 14 additions & 0 deletions HotReloadUtils.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Solution>
<Folder Name="/tests/">
<Project Path="tests/Acceptance/EncCapabilitiesCompat.Tests/EncCapabilitiesCompat.Tests.csproj" />
<Project Path="tests/BuildTool/ImportExplcitly.ShouldNotRun.Tests/ImportExplicitly.ShouldNotRun.Tests.csproj" />
<Project Path="tests/BuildTool/ImportExplcitly.Tests/ImportExplicitly.Tests.csproj" />
<Project Path="tests/HotReload.Generator/EnC.Tests/EnC.Tests.csproj" />
</Folder>
<Project Path="src/hotreload-delta-gen/src/hotreload-delta-gen.csproj" />
<Project Path="src/Microsoft.DotNet.HotReload.Utils.Generator.BuildTool/Microsoft.DotNet.HotReload.Utils.Generator.BuildTool.csproj" />
<Project Path="src/Microsoft.DotNet.HotReload.Utils.Generator.Data/Microsoft.DotNet.HotReload.Utils.Generator.Data.csproj" />
<Project Path="src/Microsoft.DotNet.HotReload.Utils.Generator.Frontend/Microsoft.DotNet.HotReload.Utils.Generator.Frontend.csproj" />
<Project Path="src/Microsoft.DotNet.HotReload.Utils.Generator.Tasks/Microsoft.DotNet.HotReload.Utils.Generator.Tasks.csproj" />
<Project Path="src/Microsoft.DotNet.HotReload.Utils.Generator/Microsoft.DotNet.HotReload.Utils.Generator.csproj" />
</Solution>
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,21 @@ public async Task<DeltaProject> 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,16 @@ public void EndSession ()
mi.Invoke(_watchHotReloadService, Array.Empty<object>());
}

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<object>());
}

public Task<Updates2> EmitSolutionUpdateAsync(Solution solution, CancellationToken cancellationToken)
{
var runningProjectInfoType = _watchServiceType.GetNestedType("RunningProjectInfo", BindingFlags.Public)!;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ protected async Task<Project> 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;
}
Expand Down
38 changes: 29 additions & 9 deletions tests/HotReload.Generator/EnC.Tests/WatchHotReloadServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using CancellationToken = System.Threading.CancellationToken;
using System.Linq;

using System.Reflection.Metadata;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Text;
using Microsoft.DotNet.HotReload.Utils.Generator.EnC;

using Xunit;

Expand All @@ -26,29 +29,46 @@ 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() {
Console.WriteLine("Hello");
}
}
""");
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);
}
}