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
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ public async Task CompileAsync_WhenSharedWorkerBuildFails_ShouldFallbackToOneSho
dllPath,
references,
externalCompilerPaths,
new RoslynCompilerOptions(Array.Empty<string>(), false),
compileCancellationTokenSource.Token,
() => buildStarted = true,
() => buildFinished = true,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using NUnit.Framework;

using io.github.hatayama.UnityCliLoop.FirstPartyTools;

namespace io.github.hatayama.UnityCliLoop.Tests.Editor.DynamicCodeToolTests
{
/// <summary>
/// Verifies the immutable compiler-settings snapshot used by dynamic compilation.
/// </summary>
[TestFixture]
public sealed class RoslynCompilerOptionsTests
{
/// <summary>
/// Verifies empty and whitespace-only define symbols are excluded while valid symbols are copied.
/// </summary>
[Test]
public void Constructor_FiltersWhitespaceAndCopiesDefineSymbols()
{
string[] defineSymbols =
{
"UNITY_EDITOR",
null,
"",
" ",
"CUSTOM_DEFINE"
};

RoslynCompilerOptions options = new(defineSymbols, true);
defineSymbols[0] = "MUTATED_AFTER_CAPTURE";

Assert.That(
options.DefineSymbols,
Is.EqualTo(new[] { "UNITY_EDITOR", "CUSTOM_DEFINE" }));
Assert.That(options.AllowUnsafeCode, Is.True);
}

/// <summary>
/// Verifies an empty define-symbol collection produces an empty immutable snapshot.
/// </summary>
[Test]
public void Constructor_WithEmptyDefineSymbols_CapturesEmptySnapshot()
{
RoslynCompilerOptions options = new(Array.Empty<string>(), false);

Assert.That(options.DefineSymbols, Is.Empty);
Assert.That(options.AllowUnsafeCode, Is.False);
}

/// <summary>
/// Verifies a null define-symbol collection fails fast at the snapshot boundary.
/// </summary>
[Test]
public void Constructor_WithNullDefineSymbols_ThrowsArgumentNullException()
{
Assert.That(
() => new RoslynCompilerOptions(null, false),
Throws.ArgumentNullException);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public interface ICompiledAssemblyBuilder
{
Task<CompiledAssemblyBuildResult> BuildAsync(
DynamicCompilationPlan plan,
RoslynCompilerOptions compilerOptions,
CancellationToken ct = default);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ public CompiledAssemblyBuilder(

public async Task<CompiledAssemblyBuildResult> BuildAsync(
DynamicCompilationPlan plan,
RoslynCompilerOptions compilerOptions,
CancellationToken ct = default)
{
Debug.Assert(plan != null, "plan must not be null");
Debug.Assert(compilerOptions != null, "compilerOptions must not be null");

ct.ThrowIfCancellationRequested();

Expand Down Expand Up @@ -98,6 +100,7 @@ async Task<CompilerMessage[]> BuildFunc(
resolvedDllPath,
resolvedReferences,
externalCompilerPaths,
compilerOptions,
cancellationToken,
() => canDeleteTempFiles = false,
() => canDeleteTempFiles = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using UnityEditor;
using Debug = UnityEngine.Debug;
using Stopwatch = System.Diagnostics.Stopwatch;

Expand Down Expand Up @@ -61,6 +62,11 @@ public async Task<CompilationResult> CompileAsync(CompilationRequest request, Ca
Debug.Assert(!string.IsNullOrWhiteSpace(request.Code), "request.Code must not be empty");

ct.ThrowIfCancellationRequested();
await MainThreadSwitcher.SwitchToMainThread(ct);
string[] activeDefineSymbols = EditorUserBuildSettings.activeScriptCompilationDefines ?? Array.Empty<string>();
RoslynCompilerOptions compilerOptions = new(
activeDefineSymbols,
PlayerSettings.allowUnsafeCode);
LastBuildCount = 0;
Stopwatch compilerTotalStopwatch = Stopwatch.StartNew();
Stopwatch planStopwatch = Stopwatch.StartNew();
Expand Down Expand Up @@ -95,7 +101,10 @@ public async Task<CompilationResult> CompileAsync(CompilationRequest request, Ca
}

Stopwatch builderTotalStopwatch = Stopwatch.StartNew();
CompiledAssemblyBuildResult buildResult = await _assemblyBuilder.BuildAsync(plan, ct).ConfigureAwait(false);
CompiledAssemblyBuildResult buildResult = await _assemblyBuilder.BuildAsync(
plan,
compilerOptions,
ct).ConfigureAwait(false);
builderTotalStopwatch.Stop();
LastBuildCount = buildResult.BuildCount;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public Task<DynamicCompilationBackendResult> CompileAsync(
string dllPath,
List<string> references,
ExternalCompilerPaths externalCompilerPaths,
RoslynCompilerOptions compilerOptions,
CancellationToken ct,
Action markBuildStarted,
Action markBuildFinished,
Expand All @@ -46,6 +47,7 @@ public Task<DynamicCompilationBackendResult> CompileAsync(
dllPath,
references,
externalCompilerPaths,
compilerOptions,
ct,
markBuildStarted,
markBuildFinished,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;

Expand Down Expand Up @@ -52,14 +51,15 @@ public static async Task<DynamicCompilationBackendResult> CompileAsync(
string dllPath,
List<string> references,
ExternalCompilerPaths externalCompilerPaths,
RoslynCompilerOptions compilerOptions,
CancellationToken ct,
Action markBuildStarted,
Action markBuildFinished,
Action incrementBuildCount)
{
string workerRequestFilePath = Path.ChangeExtension(sourcePath, ".worker");
string[] defineSymbols = GetActiveDefineSymbols();
bool allowUnsafeCode = PlayerSettings.allowUnsafeCode;
IReadOnlyCollection<string> defineSymbols = compilerOptions.DefineSymbols;
bool allowUnsafeCode = compilerOptions.AllowUnsafeCode;

try
{
Expand Down Expand Up @@ -271,26 +271,6 @@ internal static void WriteWorkerRequestFile(
File.WriteAllLines(Path.GetFullPath(requestFilePath), lines);
}

private static string[] GetActiveDefineSymbols()
{
string[] activeDefines = EditorUserBuildSettings.activeScriptCompilationDefines;
if (activeDefines == null || activeDefines.Length == 0)
{
return Array.Empty<string>();
}

List<string> filteredDefines = new(activeDefines.Length);
foreach (string define in activeDefines)
{
if (!string.IsNullOrWhiteSpace(define))
{
filteredDefines.Add(define);
}
}

return filteredDefines.ToArray();
}

private static string BuildDefineOption(IReadOnlyCollection<string> defineSymbols)
{
string serializedDefines = SerializeDefineSymbols(defineSymbols);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;

namespace io.github.hatayama.UnityCliLoop.FirstPartyTools
{
/// <summary>
/// Captures the Unity compiler settings required by the asynchronous Roslyn pipeline.
/// </summary>
public sealed class RoslynCompilerOptions
{
public IReadOnlyList<string> DefineSymbols { get; }

public bool AllowUnsafeCode { get; }

/// <summary>
/// Creates an immutable compiler-settings snapshot for one compilation request.
/// </summary>
public RoslynCompilerOptions(
IReadOnlyCollection<string> defineSymbols,
bool allowUnsafeCode)
{
if (defineSymbols == null)
{
throw new ArgumentNullException(nameof(defineSymbols));
}

List<string> filteredDefineSymbols = new(defineSymbols.Count);
foreach (string defineSymbol in defineSymbols)
{
if (!string.IsNullOrWhiteSpace(defineSymbol))
{
filteredDefineSymbols.Add(defineSymbol);
}
}

DefineSymbols = filteredDefineSymbols.AsReadOnly();
AllowUnsafeCode = allowUnsafeCode;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.