From 3be356cf446936aede4c28bf478449bcbf260b9e Mon Sep 17 00:00:00 2001 From: Jihoon Park Date: Sun, 10 Mar 2024 18:23:37 -0400 Subject: [PATCH 1/4] Support C# 12 by installing .NET 8 SDK in the Ubuntu pipeline --- MedallionShell.Tests/CommandLineSyntaxTest.cs | 4 +- MedallionShell.Tests/GeneralTest.cs | 36 +++---- .../Streams/MergedLinesEnumerableTest.cs | 8 +- .../Streams/ProcessIOCancellationTest.cs | 4 +- MedallionShell/AttachedCommand.cs | 4 +- MedallionShell/ProcessCommand.cs | 4 +- MedallionShell/Shims/Shims.cs | 4 +- MedallionShell/Shims/SpanShims.cs | 6 +- MedallionShell/Shims/ValueTupleShims.cs | 15 +-- .../Signals/WindowsProcessSignaler.cs | 2 +- .../Streams/LongRunningTaskScheduler.cs | 2 +- .../Streams/MergedLinesEnumerable.cs | 25 ++--- MedallionShell/Streams/Pipe.cs | 102 +++++++++++------- MedallionShell/Streams/ProcessStreamReader.cs | 10 +- SampleCommand/Program.cs | 2 +- appveyor.yml | 7 +- stylecop.analyzers.ruleset | 10 +- 17 files changed, 124 insertions(+), 121 deletions(-) diff --git a/MedallionShell.Tests/CommandLineSyntaxTest.cs b/MedallionShell.Tests/CommandLineSyntaxTest.cs index b0be6ca..7f7c87e 100644 --- a/MedallionShell.Tests/CommandLineSyntaxTest.cs +++ b/MedallionShell.Tests/CommandLineSyntaxTest.cs @@ -16,7 +16,7 @@ public void TestArgumentValidation([Values] bool isWindowsSyntax) { var syntax = isWindowsSyntax ? new WindowsCommandLineSyntax() : new MonoUnixCommandLineSyntax().As(); Assert.Throws(() => syntax.CreateArgumentString(null!)); - Assert.Throws(() => syntax.CreateArgumentString(new[] { "a", null!, "b" })); + Assert.Throws(() => syntax.CreateArgumentString(["a", null!, "b"])); } [TestCase(" ")] @@ -43,7 +43,7 @@ public void TestArgumentsRoundTrip(object[] arguments) } [Test] - public void TestEmptyArgumentsRoundTrip() => this.TestArgumentsRoundTripHelper(Array.Empty()); + public void TestEmptyArgumentsRoundTrip() => this.TestArgumentsRoundTripHelper([]); private void TestArgumentsRoundTripHelper(string[] arguments) { diff --git a/MedallionShell.Tests/GeneralTest.cs b/MedallionShell.Tests/GeneralTest.cs index e578453..c1a7f42 100644 --- a/MedallionShell.Tests/GeneralTest.cs +++ b/MedallionShell.Tests/GeneralTest.cs @@ -110,7 +110,7 @@ public void TestExitCode() var shell = MakeTestShell(o => o.ThrowOnError()); var ex = Assert.Throws(() => shell.Run(SampleCommand, "exit", -1).Task.Wait()); - ex!.InnerExceptions.Select(e => e.GetType()).SequenceEqual(new[] { typeof(ErrorExitCodeException) }) + ex!.InnerExceptions.Select(e => e.GetType()).SequenceEqual([typeof(ErrorExitCodeException)]) .ShouldEqual(true); shell.Run(SampleCommand, "exit", 0).Task.Wait(); @@ -119,16 +119,16 @@ public void TestExitCode() [Test] public void TestThrowOnErrorWithTimeout() { - var command = TestShell.Run(SampleCommand, new object[] { "exit", 1 }, o => o.ThrowOnError().Timeout(TimeSpan.FromDays(1))); + var command = TestShell.Run(SampleCommand, ["exit", 1], o => o.ThrowOnError().Timeout(TimeSpan.FromDays(1))); var ex = Assert.Throws(() => command.Task.Wait()); - ex!.InnerExceptions.Select(e => e.GetType()).SequenceEqual(new[] { typeof(ErrorExitCodeException) }) + ex!.InnerExceptions.Select(e => e.GetType()).SequenceEqual([typeof(ErrorExitCodeException)]) .ShouldEqual(true); } [Test] public void TestTimeout() { - var willTimeout = TestShell.Run(SampleCommand, new object[] { "sleep", 1000000 }, o => o.Timeout(TimeSpan.FromMilliseconds(200))); + var willTimeout = TestShell.Run(SampleCommand, ["sleep", 1000000], o => o.Timeout(TimeSpan.FromMilliseconds(200))); var ex = Assert.Throws(() => willTimeout.Task.Wait()); Assert.IsInstanceOf(ex!.InnerException); } @@ -136,7 +136,7 @@ public void TestTimeout() [Test] public void TestZeroTimeout() { - var willTimeout = TestShell.Run(SampleCommand, new object[] { "sleep", 1000000 }, o => o.Timeout(TimeSpan.Zero)); + var willTimeout = TestShell.Run(SampleCommand, ["sleep", 1000000], o => o.Timeout(TimeSpan.Zero)); var ex = Assert.Throws(() => willTimeout.Task.Wait()); Assert.IsInstanceOf(ex!.InnerException); } @@ -145,7 +145,7 @@ public void TestZeroTimeout() public void TestCancellationAlreadyCanceled() { using var alreadyCanceled = new CancellationTokenSource(millisecondsDelay: 0); - var command = TestShell.Run(SampleCommand, new object[] { "sleep", 1000000 }, o => o.CancellationToken(alreadyCanceled.Token)); + var command = TestShell.Run(SampleCommand, ["sleep", 1000000], o => o.CancellationToken(alreadyCanceled.Token)); Assert.Throws(() => command.Wait()); Assert.Throws(() => command.Result.ToString()); command.Task.Status.ShouldEqual(TaskStatus.Canceled); @@ -156,7 +156,7 @@ public void TestCancellationAlreadyCanceled() public void TestCancellationNotCanceled() { using var notCanceled = new CancellationTokenSource(); - var command = TestShell.Run(SampleCommand, new object[] { "sleep", 1000000 }, o => o.CancellationToken(notCanceled.Token)); + var command = TestShell.Run(SampleCommand, ["sleep", 1000000], o => o.CancellationToken(notCanceled.Token)); command.Task.Wait(50).ShouldEqual(false); command.Kill(); command.Task.Wait(1000).ShouldEqual(true); @@ -168,7 +168,7 @@ public void TestCancellationCanceledPartway() { using var cancellationTokenSource = new CancellationTokenSource(); var results = new SyncCollection(); - var command = TestShell.Run(SampleCommand, new object[] { "echo", "--per-char" }, o => o.CancellationToken(cancellationTokenSource.Token)) > results; + var command = TestShell.Run(SampleCommand, ["echo", "--per-char"], o => o.CancellationToken(cancellationTokenSource.Token)) > results; command.StandardInput.WriteLine("hello"); var timeout = Task.Delay(TimeSpan.FromSeconds(10)); while (results.Count == 0 && !timeout.IsCompleted) { } @@ -202,7 +202,7 @@ public void TestCancellationCanceledAfterCompletion() { using var cancellationTokenSource = new CancellationTokenSource(); var results = new List(); - var command = TestShell.Run(SampleCommand, new object[] { "echo" }, o => o.CancellationToken(cancellationTokenSource.Token)) > results; + var command = TestShell.Run(SampleCommand, ["echo"], o => o.CancellationToken(cancellationTokenSource.Token)) > results; command.StandardInput.WriteLine("hello"); command.StandardInput.Close(); command.Task.Wait(1000).ShouldEqual(true); @@ -216,7 +216,7 @@ public void TestCancellationWithTimeoutTimeoutWins() var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5)); var command = TestShell.Run( SampleCommand, - new object[] { "sleep", 1000000 }, + ["sleep", 1000000], o => o.CancellationToken(cancellationTokenSource.Token) .Timeout(TimeSpan.FromMilliseconds(50)) ); @@ -229,7 +229,7 @@ public void TestCancellationWithTimeoutCancellationWins() var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(50)); var command = TestShell.Run( SampleCommand, - new object[] { "sleep", 1000000 }, + ["sleep", 1000000], o => o.CancellationToken(cancellationTokenSource.Token) .Timeout(TimeSpan.FromSeconds(5)) ); @@ -484,10 +484,10 @@ void TestHelper(bool disposeOnExit) command1.Process.StartInfo.Arguments.ShouldContain("--id1"); command2.Process.StartInfo.Arguments.ShouldContain("--id2"); #endif - command1.Processes.SequenceEqual(new[] { command1.Process }); - command2.Processes.SequenceEqual(new[] { command2.Process }).ShouldEqual(true); + command1.Processes.SequenceEqual([command1.Process]); + command2.Processes.SequenceEqual([command2.Process]).ShouldEqual(true); pipeCommand.Process.ShouldEqual(command2.Process); - pipeCommand.Processes.SequenceEqual(new[] { command1.Process, command2.Process }).ShouldEqual(true); + pipeCommand.Processes.SequenceEqual([command1.Process, command2.Process]).ShouldEqual(true); } #if NETFRAMEWORK @@ -504,10 +504,10 @@ static string GetCommandLine(int processId) } #endif - command1.ProcessIds.SequenceEqual(new[] { command1.ProcessId }).ShouldEqual(true); - command2.ProcessIds.SequenceEqual(new[] { command2.ProcessId }).ShouldEqual(true); + command1.ProcessIds.SequenceEqual([command1.ProcessId]).ShouldEqual(true); + command2.ProcessIds.SequenceEqual([command2.ProcessId]).ShouldEqual(true); pipeCommand.ProcessId.ShouldEqual(command2.ProcessId); - pipeCommand.ProcessIds.SequenceEqual(new[] { command1.ProcessId, command2.ProcessId }).ShouldEqual(true); + pipeCommand.ProcessIds.SequenceEqual([command1.ProcessId, command2.ProcessId]).ShouldEqual(true); } finally { @@ -609,7 +609,7 @@ public async Task TestCustomCommandLineSyntaxIsUsed() { using var command = TestShell.Run( SampleCommand, - new object[] { "exit", 0 }, + ["exit", 0], options: o => o.Syntax((CommandLineSyntax)Activator.CreateInstance(PlatformCompatibilityHelper.DefaultCommandLineSyntax.GetType())!) .DisposeOnExit(false) ); diff --git a/MedallionShell.Tests/Streams/MergedLinesEnumerableTest.cs b/MedallionShell.Tests/Streams/MergedLinesEnumerableTest.cs index 0eda3c3..c62a0ae 100644 --- a/MedallionShell.Tests/Streams/MergedLinesEnumerableTest.cs +++ b/MedallionShell.Tests/Streams/MergedLinesEnumerableTest.cs @@ -21,14 +21,14 @@ public void TestOneIsEmpty() var enumerable1 = new MergedLinesEnumerable(empty1, nonEmpty1); var list1 = enumerable1.ToList(); - list1.SequenceEqual(new[] { "abc", "def", "ghi", "jkl" }) + list1.SequenceEqual(["abc", "def", "ghi", "jkl"]) .ShouldEqual(true, string.Join(", ", list1)); var empty2 = new StringReader(string.Empty); var nonEmpty2 = new StringReader("a\nbb\nccc\n"); var enumerable2 = new MergedLinesEnumerable(nonEmpty2, empty2); var list2 = enumerable2.ToList(); - list2.SequenceEqual(new[] { "a", "bb", "ccc" }) + list2.SequenceEqual(["a", "bb", "ccc"]) .ShouldEqual(true, string.Join(", ", list2)); } @@ -53,8 +53,8 @@ public void TestBothArePopulatedEqualSizes() [Test] public void TestBothArePopulatedDifferenceSizes() { - var lines1 = string.Join("\n", new[] { "x", "y", "z" }); - var lines2 = string.Join("\n", new[] { "1", "2", "3", "4", "5" }); + var lines1 = string.Join("\n", ["x", "y", "z"]); + var lines2 = string.Join("\n", ["1", "2", "3", "4", "5"]); var list1 = new MergedLinesEnumerable(new StringReader(lines1), new StringReader(lines2)) .ToList(); diff --git a/MedallionShell.Tests/Streams/ProcessIOCancellationTest.cs b/MedallionShell.Tests/Streams/ProcessIOCancellationTest.cs index 5acaaf1..757c34b 100644 --- a/MedallionShell.Tests/Streams/ProcessIOCancellationTest.cs +++ b/MedallionShell.Tests/Streams/ProcessIOCancellationTest.cs @@ -28,7 +28,7 @@ public void TestProcessIOIsCancellable() Arguments = "echo", #else FileName = PlatformCompatibilityTests.DotNetPath, - Arguments = PlatformCompatibilityHelper.DefaultCommandLineSyntax.CreateArgumentString(new[] { PlatformCompatibilityTests.SampleCommandPath, "echo" }), + Arguments = PlatformCompatibilityHelper.DefaultCommandLineSyntax.CreateArgumentString([PlatformCompatibilityTests.SampleCommandPath, "echo"]), #endif RedirectStandardInput = true, RedirectStandardOutput = true, @@ -45,7 +45,7 @@ public void TestProcessIOIsCancellable() // For write, loop to fill up the buffer; eventually we'll block while (true) { await DoIOWithCancellationAsync(process.StandardInput.BaseStream, cancellationTokenSource.Token); } }); - Task.WaitAny(new[] { readTask, writeTask }, TimeSpan.FromSeconds(0.5)).ShouldEqual(-1); + Task.WaitAny([readTask, writeTask], TimeSpan.FromSeconds(0.5)).ShouldEqual(-1); cancellationTokenSource.Cancel(); diff --git a/MedallionShell/AttachedCommand.cs b/MedallionShell/AttachedCommand.cs index 2d1ff11..10f4d7c 100644 --- a/MedallionShell/AttachedCommand.cs +++ b/MedallionShell/AttachedCommand.cs @@ -42,7 +42,7 @@ internal AttachedCommand( TaskContinuationOptions.ExecuteSynchronously ); - this.processes = new Lazy>(() => new ReadOnlyCollection(new[] { this.process })); + this.processes = new Lazy>(() => new ReadOnlyCollection([this.process])); } public override Process Process @@ -77,7 +77,7 @@ public override int ProcessId } } - public override IReadOnlyList ProcessIds => new ReadOnlyCollection(new[] { this.ProcessId }); + public override IReadOnlyList ProcessIds => new ReadOnlyCollection([this.ProcessId]); public override ProcessStreamWriter StandardInput => throw new InvalidOperationException(StreamPropertyExceptionMessage); diff --git a/MedallionShell/ProcessCommand.cs b/MedallionShell/ProcessCommand.cs index ec39442..c038175 100644 --- a/MedallionShell/ProcessCommand.cs +++ b/MedallionShell/ProcessCommand.cs @@ -118,7 +118,7 @@ public override Process Process } private IReadOnlyList? processes; - public override IReadOnlyList Processes => this.processes ??= new ReadOnlyCollection(new[] { this.Process }); + public override IReadOnlyList Processes => this.processes ??= new ReadOnlyCollection([this.Process]); private readonly object processIdOrExceptionDispatchInfo; public override int ProcessId @@ -137,7 +137,7 @@ public override int ProcessId } private IReadOnlyList? processIds; - public override IReadOnlyList ProcessIds => this.processIds ??= new ReadOnlyCollection(new[] { this.ProcessId }); + public override IReadOnlyList ProcessIds => this.processIds ??= new ReadOnlyCollection([this.ProcessId]); private readonly ProcessStreamWriter? standardInput; public override ProcessStreamWriter StandardInput => this.standardInput ?? throw new InvalidOperationException("Standard input is not redirected"); diff --git a/MedallionShell/Shims/Shims.cs b/MedallionShell/Shims/Shims.cs index f7f8f5d..50f2843 100644 --- a/MedallionShell/Shims/Shims.cs +++ b/MedallionShell/Shims/Shims.cs @@ -14,10 +14,10 @@ public static T[] EmptyArray() => private static class Empty { - public static readonly T[] Array = new T[0]; + public static readonly T[] Array = []; } #else - Array.Empty(); + []; #endif public static Task CanceledTask(CancellationToken cancellationToken) diff --git a/MedallionShell/Shims/SpanShims.cs b/MedallionShell/Shims/SpanShims.cs index 40fdfa2..9b96839 100644 --- a/MedallionShell/Shims/SpanShims.cs +++ b/MedallionShell/Shims/SpanShims.cs @@ -34,14 +34,12 @@ public void CopyTo(Memory destination) => System.Array.Copy(sourceArray: this.Array, sourceIndex: this.Offset, destinationArray: destination.Array, destinationIndex: destination.Offset, length: this.Length); } -internal readonly ref struct Span +internal readonly ref struct Span(Memory memory) { - public readonly Memory Memory; + public readonly Memory Memory = memory; public int Length => this.Memory.Length; - public Span(Memory memory) { this.Memory = memory; } - public static implicit operator Span(T[] array) => new(new(array, 0, array.Length)); public void CopyTo(Span destination) => this.Memory.CopyTo(destination.Memory); diff --git a/MedallionShell/Shims/ValueTupleShims.cs b/MedallionShell/Shims/ValueTupleShims.cs index a694348..8c4235d 100644 --- a/MedallionShell/Shims/ValueTupleShims.cs +++ b/MedallionShell/Shims/ValueTupleShims.cs @@ -3,17 +3,10 @@ namespace System; -internal struct ValueTuple +internal struct ValueTuple(T1 item1, T2 item2, T3 item3) { - public T1 Item1; - public T2 Item2; - public T3 Item3; - - public ValueTuple(T1 item1, T2 item2, T3 item3) - { - this.Item1 = item1; - this.Item2 = item2; - this.Item3 = item3; - } + public T1 Item1 = item1; + public T2 Item2 = item2; + public T3 Item3 = item3; } #endif \ No newline at end of file diff --git a/MedallionShell/Signals/WindowsProcessSignaler.cs b/MedallionShell/Signals/WindowsProcessSignaler.cs index 5e5795b..3e8a770 100644 --- a/MedallionShell/Signals/WindowsProcessSignaler.cs +++ b/MedallionShell/Signals/WindowsProcessSignaler.cs @@ -34,7 +34,7 @@ public static async Task TrySignalAsync(int processId, NativeMethods.CtrlT var exeFile = await DeploySignalerExeAsync().ConfigureAwait(false); try { - var command = Command.Run(exeFile, new object[] { processId, (int)signal }); + var command = Command.Run(exeFile, [processId, (int)signal]); return (await command.Task.ConfigureAwait(false)).Success; } finally diff --git a/MedallionShell/Streams/LongRunningTaskScheduler.cs b/MedallionShell/Streams/LongRunningTaskScheduler.cs index 0baedec..1365cab 100644 --- a/MedallionShell/Streams/LongRunningTaskScheduler.cs +++ b/MedallionShell/Streams/LongRunningTaskScheduler.cs @@ -80,7 +80,7 @@ protected override void QueueTask(Task task) WorkerThreadState.StartNew(this, task); } - protected override IEnumerable GetScheduledTasks() => Enumerable.Empty(); // all tasks run immediately + protected override IEnumerable GetScheduledTasks() => []; // all tasks run immediately protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) => false; diff --git a/MedallionShell/Streams/MergedLinesEnumerable.cs b/MedallionShell/Streams/MergedLinesEnumerable.cs index 0d3ec7f..93aa736 100644 --- a/MedallionShell/Streams/MergedLinesEnumerable.cs +++ b/MedallionShell/Streams/MergedLinesEnumerable.cs @@ -9,17 +9,10 @@ namespace Medallion.Shell.Streams { - internal sealed class MergedLinesEnumerable : IEnumerable + internal sealed class MergedLinesEnumerable(TextReader standardOutput, TextReader standardError) : IEnumerable { - private readonly TextReader standardOutput, standardError; private int consumed; - public MergedLinesEnumerable(TextReader standardOutput, TextReader standardError) - { - this.standardOutput = standardOutput; - this.standardError = standardError; - } - public IEnumerator GetEnumerator() { Throw.If( @@ -35,8 +28,8 @@ public IEnumerator GetEnumerator() private IEnumerator GetEnumeratorInternal() { var tasks = new List(capacity: 2); - tasks.Add(new ReaderAndTask(this.standardOutput)); - tasks.Add(new ReaderAndTask(this.standardError)); + tasks.Add(new ReaderAndTask(standardOutput)); + tasks.Add(new ReaderAndTask(standardError)); // phase 1: read both streams simultaneously, alternating between which is given priority. // Stop when one (or both) streams is exhausted @@ -92,16 +85,10 @@ private IEnumerator GetEnumeratorInternal() } } - private struct ReaderAndTask : IEquatable + private struct ReaderAndTask(TextReader reader) : IEquatable { - public ReaderAndTask(TextReader reader) - { - this.Reader = reader; - this.Task = reader.ReadLineAsync(); - } - - public TextReader Reader { get; } - public Task Task { get; } + public TextReader Reader { get; } = reader; + public Task Task { get; } = reader.ReadLineAsync(); public bool Equals(ReaderAndTask that) => this.Reader == that.Reader && this.Task == that.Task; diff --git a/MedallionShell/Streams/Pipe.cs b/MedallionShell/Streams/Pipe.cs index 513ceb9..2b27ad4 100644 --- a/MedallionShell/Streams/Pipe.cs +++ b/MedallionShell/Streams/Pipe.cs @@ -494,12 +494,8 @@ private void CleanUpNoLock() #endregion #region ---- Input Stream ---- - private sealed class PipeInputStream : Stream + private sealed class PipeInputStream(Pipe pipe) : Stream { - private readonly Pipe pipe; - - public PipeInputStream(Pipe pipe) { this.pipe = pipe; } - #if !NETSTANDARD1_3 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) { @@ -519,22 +515,13 @@ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, As } #endif - private sealed class AsyncWriteResult : IAsyncResult + private sealed class AsyncWriteResult(object? state, Task writeTask, Pipe.PipeInputStream stream) : IAsyncResult { - private readonly object? state; - - public AsyncWriteResult(object? state, Task writeTask, PipeInputStream stream) - { - this.state = state; - this.WriteTask = writeTask; - this.Stream = stream; - } + public Task WriteTask { get; } = writeTask; - public Task WriteTask { get; } + public Stream Stream { get; } = stream; - public Stream Stream { get; } - - object? IAsyncResult.AsyncState => this.state; + object? IAsyncResult.AsyncState => state; WaitHandle IAsyncResult.AsyncWaitHandle => this.WriteTask.As().AsyncWaitHandle; @@ -564,7 +551,7 @@ protected override void Dispose(bool disposing) { if (disposing) { - this.pipe.CloseWriteSide(); + pipe.CloseWriteSide(); } } @@ -639,7 +626,7 @@ public override void Write(byte[] buffer, int offset, int count) => this.WriteAsync(buffer, offset, count).GetAwaiter().GetResult(); public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => - this.pipe.WriteAsync(buffer, offset, count, TimeSpan.FromMilliseconds(this.WriteTimeout), cancellationToken); + pipe.WriteAsync(buffer, offset, count, TimeSpan.FromMilliseconds(this.WriteTimeout), cancellationToken); public override void WriteByte(byte value) => base.WriteByte(value); @@ -678,12 +665,58 @@ private static NotSupportedException WriteOnly([CallerMemberName] string memberN #endregion #region ---- Output Stream ---- - private sealed class PipeOutputStream : Stream + private sealed class PipeOutputStream(Pipe pipe) : Stream + +/* Unmerged change from project 'MedallionShell (net46)' +Before: + { + private readonly Pipe pipe; + + public PipeOutputStream(Pipe pipe) { this.pipe = pipe; } +After: + { +*/ + +/* Unmerged change from project 'MedallionShell (netstandard1.3)' +Before: { private readonly Pipe pipe; public PipeOutputStream(Pipe pipe) { this.pipe = pipe; } +After: + { +*/ +/* Unmerged change from project 'MedallionShell (net45)' +Before: + { + private readonly Pipe pipe; + + public PipeOutputStream(Pipe pipe) { this.pipe = pipe; } +After: + { +*/ + +/* Unmerged change from project 'MedallionShell (net471)' +Before: + { + private readonly Pipe pipe; + + public PipeOutputStream(Pipe pipe) { this.pipe = pipe; } +After: + { +*/ + +/* Unmerged change from project 'MedallionShell (netstandard2.0)' +Before: + { + private readonly Pipe pipe; + + public PipeOutputStream(Pipe pipe) { this.pipe = pipe; } +After: + { +*/ + { #if !NETSTANDARD1_3 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) { @@ -698,22 +731,13 @@ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, Asy } #endif - private sealed class AsyncReadResult : IAsyncResult + private sealed class AsyncReadResult(object? state, Task readTask, Pipe.PipeOutputStream stream) : IAsyncResult { - private readonly object? state; - - public AsyncReadResult(object? state, Task readTask, PipeOutputStream stream) - { - this.state = state; - this.ReadTask = readTask; - this.Stream = stream; - } - - public Task ReadTask { get; } + public Task ReadTask { get; } = readTask; - public Stream Stream { get; } + public Stream Stream { get; } = stream; - object? IAsyncResult.AsyncState => this.state; + object? IAsyncResult.AsyncState => state; WaitHandle IAsyncResult.AsyncWaitHandle => this.ReadTask.As().AsyncWaitHandle; @@ -751,7 +775,7 @@ protected override void Dispose(bool disposing) { if (disposing) { - this.pipe.CloseReadSide(); + pipe.CloseReadSide(); } } @@ -792,14 +816,14 @@ public override int Read(byte[] buffer, int offset, int count) { Throw.IfInvalidBuffer(buffer, offset, count); - return this.pipe.Read(buffer.AsSpan(offset, count), TimeSpan.FromMilliseconds(this.readTimeout)); + return pipe.Read(buffer.AsSpan(offset, count), TimeSpan.FromMilliseconds(this.readTimeout)); } public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { Throw.IfInvalidBuffer(buffer, offset, count); - return this.pipe.ReadAsync(new(buffer, offset, count), TimeSpan.FromMilliseconds(this.readTimeout), cancellationToken); + return pipe.ReadAsync(new(buffer, offset, count), TimeSpan.FromMilliseconds(this.readTimeout), cancellationToken); } #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1 @@ -809,7 +833,7 @@ public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationTo throw ReadOnly(); public override int Read(Span buffer) => - this.pipe.Read(buffer, TimeSpan.FromMilliseconds(this.readTimeout)); + pipe.Read(buffer, TimeSpan.FromMilliseconds(this.readTimeout)); public override int ReadByte() { @@ -819,7 +843,7 @@ public override int ReadByte() } public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken) => - new(this.pipe.ReadAsync(buffer, TimeSpan.FromMilliseconds(this.readTimeout), cancellationToken)); + new(pipe.ReadAsync(buffer, TimeSpan.FromMilliseconds(this.readTimeout), cancellationToken)); #else public override int ReadByte() => base.ReadByte(); #endif diff --git a/MedallionShell/Streams/ProcessStreamReader.cs b/MedallionShell/Streams/ProcessStreamReader.cs index c961a65..06007c0 100644 --- a/MedallionShell/Streams/ProcessStreamReader.cs +++ b/MedallionShell/Streams/ProcessStreamReader.cs @@ -31,16 +31,10 @@ internal ProcessStreamReader() { } /// public IEnumerable GetLines() => new LinesEnumerable(this); - private class LinesEnumerable : IEnumerable + private class LinesEnumerable(TextReader reader) : IEnumerable { - private readonly TextReader reader; private int consumed; - public LinesEnumerable(TextReader reader) - { - this.reader = reader; - } - IEnumerator IEnumerable.GetEnumerator() { Throw.If( @@ -54,7 +48,7 @@ IEnumerator IEnumerable.GetEnumerator() private IEnumerator GetEnumeratorInternal() { string? line; - while ((line = this.reader.ReadLine()) != null) + while ((line = reader.ReadLine()) != null) { yield return line; } diff --git a/SampleCommand/Program.cs b/SampleCommand/Program.cs index f3a09f1..20222e4 100644 --- a/SampleCommand/Program.cs +++ b/SampleCommand/Program.cs @@ -144,7 +144,7 @@ async Task EchoLinesAsync(TextWriter output) { throw new ArgumentException($"Unknown test method '{args[1]}'"); } - method.Invoke(null, new object[0]); + method.Invoke(null, []); break; default: Console.Error.WriteLine("Unrecognized mode " + args[0]); diff --git a/appveyor.yml b/appveyor.yml index dfda6ac..9b50083 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,7 +2,12 @@ version: 1.0.{build} image: - Visual Studio 2022 - - Ubuntu + - Ubuntu2204 + +init: + - sh: | + sudo apt-get update && + sudo apt-get install -y dotnet-sdk-8.0 build_script: # on linux, it seems like msbuild goes parallel such that if we don't build ProcessSignaler first, we won't have the net45 binary diff --git a/stylecop.analyzers.ruleset b/stylecop.analyzers.ruleset index 72177f7..7188995 100644 --- a/stylecop.analyzers.ruleset +++ b/stylecop.analyzers.ruleset @@ -1,16 +1,18 @@  - - + + - + + + - + From 5553ac453542006ac97656df09e565ff82ad228f Mon Sep 17 00:00:00 2001 From: Jihoon Park Date: Sun, 10 Mar 2024 20:28:48 -0400 Subject: [PATCH 2/4] Fix merge conflict from VS --- MedallionShell/Streams/Pipe.cs | 50 ---------------------------------- 1 file changed, 50 deletions(-) diff --git a/MedallionShell/Streams/Pipe.cs b/MedallionShell/Streams/Pipe.cs index 2b27ad4..8367d6a 100644 --- a/MedallionShell/Streams/Pipe.cs +++ b/MedallionShell/Streams/Pipe.cs @@ -666,56 +666,6 @@ private static NotSupportedException WriteOnly([CallerMemberName] string memberN #region ---- Output Stream ---- private sealed class PipeOutputStream(Pipe pipe) : Stream - -/* Unmerged change from project 'MedallionShell (net46)' -Before: - { - private readonly Pipe pipe; - - public PipeOutputStream(Pipe pipe) { this.pipe = pipe; } -After: - { -*/ - -/* Unmerged change from project 'MedallionShell (netstandard1.3)' -Before: - { - private readonly Pipe pipe; - - public PipeOutputStream(Pipe pipe) { this.pipe = pipe; } -After: - { -*/ - -/* Unmerged change from project 'MedallionShell (net45)' -Before: - { - private readonly Pipe pipe; - - public PipeOutputStream(Pipe pipe) { this.pipe = pipe; } -After: - { -*/ - -/* Unmerged change from project 'MedallionShell (net471)' -Before: - { - private readonly Pipe pipe; - - public PipeOutputStream(Pipe pipe) { this.pipe = pipe; } -After: - { -*/ - -/* Unmerged change from project 'MedallionShell (netstandard2.0)' -Before: - { - private readonly Pipe pipe; - - public PipeOutputStream(Pipe pipe) { this.pipe = pipe; } -After: - { -*/ { #if !NETSTANDARD1_3 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) From a34061fffbc121ff10b51c9f4767e3a530de64a7 Mon Sep 17 00:00:00 2001 From: Jihoon Park Date: Sun, 10 Mar 2024 20:28:56 -0400 Subject: [PATCH 3/4] Fix minor style issues --- appveyor.yml | 2 +- stylecop.analyzers.ruleset | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 9b50083..4cd1e6d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,7 +5,7 @@ image: - Ubuntu2204 init: - - sh: | + - sh: > sudo apt-get update && sudo apt-get install -y dotnet-sdk-8.0 diff --git a/stylecop.analyzers.ruleset b/stylecop.analyzers.ruleset index 7188995..fe9b573 100644 --- a/stylecop.analyzers.ruleset +++ b/stylecop.analyzers.ruleset @@ -12,7 +12,7 @@ - + From 9027293abab721adf44d3f84841cccc4d1aa2100 Mon Sep 17 00:00:00 2001 From: Jihoon Park Date: Sat, 30 Mar 2024 00:13:39 -0400 Subject: [PATCH 4/4] Remove unnecessary init --- appveyor.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4cd1e6d..5d6e14e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,11 +4,6 @@ image: - Visual Studio 2022 - Ubuntu2204 -init: - - sh: > - sudo apt-get update && - sudo apt-get install -y dotnet-sdk-8.0 - build_script: # on linux, it seems like msbuild goes parallel such that if we don't build ProcessSignaler first, we won't have the net45 binary # to pack into the non-net45 builds