diff --git a/Directory.Packages.props b/Directory.Packages.props index 935fc9187..21599ef71 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,9 +10,6 @@ - - - diff --git a/Src/CSharpier.Cli.Tests/GrpcTests.cs b/Src/CSharpier.Cli.Tests/GrpcTests.cs deleted file mode 100644 index 057c8149f..000000000 --- a/Src/CSharpier.Cli.Tests/GrpcTests.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace CSharpier.Cli.Tests; - -using System.Diagnostics; -using System.Text; -using CSharpier.Proto; -using FluentAssertions; -using Grpc.Core; -using NUnit.Framework; - -[TestFixture] -public class GrpcTests -{ - // TODO proto add other tests - // starting on port - // ignore file - // option file - [Test] - [Ignore("TODO proto this doesn't seem to work now, plus it needs some clean up")] - public async Task Stuff() - { - var path = Path.Combine(Directory.GetCurrentDirectory(), "dotnet-csharpier.dll"); - - var processStartInfo = new ProcessStartInfo("dotnet", $"{path} --grpc") - { - UseShellExecute = false, - ErrorDialog = false, - CreateNoWindow = true, - WindowStyle = ProcessWindowStyle.Hidden, - RedirectStandardOutput = true, - RedirectStandardError = true, - EnvironmentVariables = { ["DOTNET_NOLOGO"] = "1" }, - }; - - var process = new Process { StartInfo = processStartInfo }; - process.Start(); - - var portString = (await process.StandardOutput.ReadLineAsync() ?? string.Empty).Replace( - "Started on ", - string.Empty - ); - var port = int.Parse(portString); - - // TODO why the shit won't this connect now? - var channel = new Channel("localhost", port, ChannelCredentials.Insecure); - var client = new CSharpierService.CSharpierServiceClient(channel); - - var data = new FormatFileDto - { - FileName = "test.cs", - FileContents = "public class TestClass { }" - }; - var result = await client.FormatFileAsync(data); - - result.FormattedFile.TrimEnd().Should().Be("public class TestClass { }"); - } -} diff --git a/Src/CSharpier.Cli.Tests/IpcTests.cs b/Src/CSharpier.Cli.Tests/IpcTests.cs new file mode 100644 index 000000000..37f994ea4 --- /dev/null +++ b/Src/CSharpier.Cli.Tests/IpcTests.cs @@ -0,0 +1,68 @@ +namespace CSharpier.Cli.Tests; + +using System.Diagnostics; +using System.Net.Http.Json; +using FluentAssertions; +using NUnit.Framework; + +[TestFixture] +public class IpcTests +{ + private static readonly HttpClient httpClient = new HttpClient(); + + // TODO server add other tests + // starting on port + // ignore file + // option file + [Test] + [Ignore("not working on GH/linux")] + public async Task Stuff() + { + var path = Path.Combine(Directory.GetCurrentDirectory(), "dotnet-csharpier.dll"); + + var processStartInfo = new ProcessStartInfo("dotnet", $"{path} --ipc") + { + UseShellExecute = false, + ErrorDialog = false, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + RedirectStandardOutput = true, + RedirectStandardError = true, + EnvironmentVariables = { ["DOTNET_NOLOGO"] = "1" }, + }; + + var process = new Process { StartInfo = processStartInfo }; + try + { + process.Start(); + + var portString = (await process.StandardOutput.ReadLineAsync() ?? string.Empty).Replace( + "Started on ", + string.Empty + ); + var port = int.Parse(portString); + var data = new FormatFileDto + { + FileName = "/Temp/test.cs", + FileContents = "public class TestClass { }" + }; + + var response = await httpClient.PostAsJsonAsync( + $"http://localhost:{port}/format", + data + ); + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync(); + if (result == null) + { + Assert.Fail("Result is null"); + } + + result!.FormattedFile!.TrimEnd().Should().Be("public class TestClass { }"); + } + finally + { + process.Kill(); + } + } +} diff --git a/Src/CSharpier.Cli/CSharpier.Cli.csproj b/Src/CSharpier.Cli/CSharpier.Cli.csproj index 0ee08ea3c..06c47ddb3 100644 --- a/Src/CSharpier.Cli/CSharpier.Cli.csproj +++ b/Src/CSharpier.Cli/CSharpier.Cli.csproj @@ -12,12 +12,6 @@ - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - @@ -27,6 +21,7 @@ + diff --git a/Src/CSharpier.Cli/CommandLineOptions.cs b/Src/CSharpier.Cli/CommandLineOptions.cs index 3b291ebaa..670483006 100644 --- a/Src/CSharpier.Cli/CommandLineOptions.cs +++ b/Src/CSharpier.Cli/CommandLineOptions.cs @@ -25,8 +25,8 @@ internal delegate Task Handler( bool skipWrite, bool writeStdout, bool pipeMultipleFiles, - bool grpc, - int? grpcPort, + bool ipc, + int? ipcPort, bool noCache, bool noMSBuildCheck, bool includeGenerated, @@ -83,11 +83,11 @@ public static RootCommand Create() "Keep csharpier running so that multiples files can be piped to it via stdin." ), new Option( - new[] { "--grpc" }, - "Run CSharpier as a service using GRPC so that multiple files may be formatted." + new[] { "--server" }, + "Run CSharpier as a server so that multiple files may be formatted." ), new Option( - new[] { "--grpc-port" }, + new[] { "--server-port" }, "Specify the port that CSharpier should start on. Defaults to a random unused port." ), new Option( @@ -105,7 +105,7 @@ public static RootCommand Create() if ( !Console.IsInputRedirected && !cmd.Children.Contains("directoryOrFile") - && !cmd.Children.Contains("--grpc") + && !cmd.Children.Contains("--server") ) { return "directoryOrFile is required when not piping stdin to CSharpier"; diff --git a/Src/CSharpier.Cli/ConsoleLogger.cs b/Src/CSharpier.Cli/ConsoleLogger.cs index f8f9b71ac..037149747 100644 --- a/Src/CSharpier.Cli/ConsoleLogger.cs +++ b/Src/CSharpier.Cli/ConsoleLogger.cs @@ -110,6 +110,9 @@ public bool IsEnabled(LogLevel logLevel) } public IDisposable BeginScope(TState state) +#if NET7_0_OR_GREATER + where TState : notnull +#endif { throw new NotImplementedException(); } diff --git a/Src/CSharpier.Cli/Program.cs b/Src/CSharpier.Cli/Program.cs index 9f2d17e05..eff682079 100644 --- a/Src/CSharpier.Cli/Program.cs +++ b/Src/CSharpier.Cli/Program.cs @@ -26,8 +26,8 @@ public static async Task Run( bool skipWrite, bool writeStdout, bool pipeMultipleFiles, - bool grpc, - int? grpcPort, + bool ipc, + int? ipcPort, bool noCache, bool noMSBuildCheck, bool includeGenerated, @@ -52,10 +52,10 @@ CancellationToken cancellationToken ); } - if (grpc) + if (ipc) { - return await GrpcFormatter.StartServer( - grpcPort, + return await ServerFormatter.StartServer( + ipcPort, logger, actualConfigPath, cancellationToken diff --git a/Src/CSharpier.Cli/GrpcFormatter.cs b/Src/CSharpier.Cli/ServerFormatter.cs similarity index 65% rename from Src/CSharpier.Cli/GrpcFormatter.cs rename to Src/CSharpier.Cli/ServerFormatter.cs index b9e076b48..161702bc1 100644 --- a/Src/CSharpier.Cli/GrpcFormatter.cs +++ b/Src/CSharpier.Cli/ServerFormatter.cs @@ -1,16 +1,16 @@ -using System.Net.NetworkInformation; -using CSharpier.Proto; -using Grpc.Core; -using Microsoft.Extensions.Logging; - namespace CSharpier.Cli; using System.IO.Abstractions; +using System.Net; +using System.Net.NetworkInformation; using CSharpier.Cli.Options; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Logging; -public static class GrpcFormatter +public static class ServerFormatter { - public static Task StartServer( + public static async Task StartServer( int? port, ConsoleLogger logger, string? actualConfigPath, @@ -18,22 +18,27 @@ CancellationToken cancellationToken ) { var thePort = port ?? FindFreePort(); - var server = new Server - { - Services = + var builder = WebApplication.CreateBuilder(); + builder.WebHost.ConfigureKestrel( + (_, serverOptions) => { - CSharpierService.BindService( - new CSharpierServiceImplementation(actualConfigPath, logger) - ) - }, - Ports = { new ServerPort("localhost", thePort, ServerCredentials.Insecure) } - }; - server.Start(); - + serverOptions.Listen(IPAddress.Any, thePort); + } + ); + var app = builder.Build(); + var service = new CSharpierServiceImplementation(actualConfigPath, logger); + app.MapPost( + "/format", + async (FormatFileDto formatFileDto, CancellationToken cancellationToken) => + await service.FormatFile(formatFileDto, cancellationToken) + ); logger.LogInformation("Started on " + thePort); + + await app.RunAsync(); + Console.ReadKey(); - return Task.FromResult(0); + return 0; } public static int FindFreePort() @@ -63,7 +68,18 @@ public static int FindFreePort() } } -public class CSharpierServiceImplementation : CSharpierService.CSharpierServiceBase +public class FormatFileDto +{ + public required string FileContents { get; set; } + public required string FileName { get; set; } +} + +public class FormatFileResult +{ + public string? FormattedFile { get; set; } +} + +public class CSharpierServiceImplementation { private readonly string? configPath; private readonly IFileSystem fileSystem; @@ -76,17 +92,18 @@ public CSharpierServiceImplementation(string? configPath, ConsoleLogger logger) this.fileSystem = new FileSystem(); } - public override async Task FormatFile( + public async Task FormatFile( FormatFileDto formatFileDto, - ServerCallContext context + CancellationToken cancellationToken ) { try { var directoryName = this.fileSystem.Path.GetDirectoryName(formatFileDto.FileName); + DebugLogger.Log(directoryName ?? string.Empty); if (directoryName == null) { - // TODO proto we can probably still make this work, and just use default options + // TODO server we can probably still make this work, and just use default options throw new Exception( $"There was no directory found for file {formatFileDto.FileName}" ); @@ -97,7 +114,7 @@ ServerCallContext context this.configPath, this.fileSystem, this.logger, - context.CancellationToken + cancellationToken ); if ( @@ -105,23 +122,23 @@ ServerCallContext context || optionsProvider.IsIgnored(formatFileDto.FileName) ) { - // TODO proto should we send back that this is ignored? + // TODO server should we send back that this is ignored? return new FormatFileResult(); } var result = await CSharpFormatter.FormatAsync( formatFileDto.FileContents, optionsProvider.GetPrinterOptionsFor(formatFileDto.FileName), - context.CancellationToken + cancellationToken ); - // TODO proto what about checking if this actually formatted? + // TODO server what about checking if this actually formatted? // could send back any error messages now return new FormatFileResult { FormattedFile = result.Code }; } catch (Exception ex) { - // TODO proto should this return this as an error? + // TODO server should this return this as an error? DebugLogger.Log(ex.ToString()); return new FormatFileResult(); } diff --git a/Src/CSharpier.Cli/protos/csharpier_service.proto b/Src/CSharpier.Cli/protos/csharpier_service.proto deleted file mode 100644 index d83c0eaa7..000000000 --- a/Src/CSharpier.Cli/protos/csharpier_service.proto +++ /dev/null @@ -1,21 +0,0 @@ -syntax = "proto3"; - -option csharp_namespace = "CSharpier.Proto"; - -package proto; - -service CSharpierService -{ - rpc FormatFile(FormatFileDto) returns (FormatFileResult) {} -} - -message FormatFileDto -{ - string FileContents = 1; - string FileName = 2; -} - -message FormatFileResult -{ - string FormattedFile = 1; -} \ No newline at end of file