From 1498adb8bcdcc4f59dcd1c58aefa279d521a0dfb Mon Sep 17 00:00:00 2001 From: Georgii Borovinskikh Date: Thu, 28 Dec 2023 11:25:39 +0100 Subject: [PATCH 1/3] Add SLCoreRunner --- src/SLCore/Process/SLCoreRunner.cs | 110 +++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/SLCore/Process/SLCoreRunner.cs diff --git a/src/SLCore/Process/SLCoreRunner.cs b/src/SLCore/Process/SLCoreRunner.cs new file mode 100644 index 0000000000..a741a8d871 --- /dev/null +++ b/src/SLCore/Process/SLCoreRunner.cs @@ -0,0 +1,110 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.Threading; +using SonarLint.VisualStudio.SLCore.Core; + +namespace SonarLint.VisualStudio.SLCore.Process +{ + [ExcludeFromCodeCoverage] + public sealed class SLCoreRunner : IDisposable + { + public ISLCoreJsonRpc Rpc { get; } + private readonly System.Diagnostics.Process process; + private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); + private readonly JsonRpcWrapper jsonRpcWrapper; + + public SLCoreRunner(string pathToBat, string logFilePath = null, string errorLogFilePath = null, bool enableVerboseLogs = false) + { + FileStream logFileStream = null; + if (!string.IsNullOrEmpty(logFilePath)) + { + logFileStream = File.OpenWrite(logFilePath); + + } + + // todo: disable telemetry + var processStartInfo = new ProcessStartInfo("cmd.exe", $@"/c {pathToBat}") + { + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardInput = true, + RedirectStandardOutput = true, + RedirectStandardError = true + }; + + process = new System.Diagnostics.Process { StartInfo = processStartInfo }; + + process.Start(); + process + .StandardOutput + .ReadLine(); // needed to skip `echo Using bundled jre` since that is not a valid rpc msg. should be removed after it's fixed on the SLCore side + + Task.Run(() => ReadErrorLog(errorLogFilePath)).Forget(); + + jsonRpcWrapper = new JsonRpcWrapper(process.StandardInput.BaseStream, process.StandardOutput.BaseStream); + jsonRpcWrapper.TraceSource.Switch.Level = enableVerboseLogs? SourceLevels.Verbose : SourceLevels.Warning; + jsonRpcWrapper.TraceSource.Listeners.Add(logFileStream == null ? new ConsoleTraceListener(): new TextWriterTraceListener(logFileStream)); + + Rpc = new SLCoreJsonRpc(jsonRpcWrapper); + } + + private void ReadErrorLog(string errorLogFilePath) + { + var token = cancellationTokenSource.Token; + var fileLoggingEnabled = errorLogFilePath != null; + var prefix = fileLoggingEnabled ? string.Empty : "ERR: "; + StreamWriter fileStream = fileLoggingEnabled ? new StreamWriter(File.OpenWrite(errorLogFilePath)) : null; + + + while (!token.IsCancellationRequested) + { + var line = process.StandardError.ReadLine(); + if (string.IsNullOrEmpty(line)) + { + continue; + } + + if (fileLoggingEnabled) + { + fileStream.WriteLine(line); + } + else + { + Console.WriteLine(prefix + line); + } + } + } + + public void Dispose() + { + cancellationTokenSource?.Cancel(); + cancellationTokenSource?.Dispose(); + jsonRpcWrapper?.Dispose(); // todo: slcore should be shutdown already + process?.Dispose(); + } + } +} From 4381a3cf719c9b21f08e550843357a4f8a7607c2 Mon Sep 17 00:00:00 2001 From: Georgii Borovinskikh Date: Thu, 28 Dec 2023 11:28:46 +0100 Subject: [PATCH 2/3] Move SLCoreRunner to tests --- src/{SLCore => SLCore.UnitTests}/Process/SLCoreRunner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/{SLCore => SLCore.UnitTests}/Process/SLCoreRunner.cs (98%) diff --git a/src/SLCore/Process/SLCoreRunner.cs b/src/SLCore.UnitTests/Process/SLCoreRunner.cs similarity index 98% rename from src/SLCore/Process/SLCoreRunner.cs rename to src/SLCore.UnitTests/Process/SLCoreRunner.cs index a741a8d871..3b85dea51a 100644 --- a/src/SLCore/Process/SLCoreRunner.cs +++ b/src/SLCore.UnitTests/Process/SLCoreRunner.cs @@ -27,7 +27,7 @@ using Microsoft.VisualStudio.Threading; using SonarLint.VisualStudio.SLCore.Core; -namespace SonarLint.VisualStudio.SLCore.Process +namespace SonarLint.VisualStudio.SLCore.UnitTests.Process { [ExcludeFromCodeCoverage] public sealed class SLCoreRunner : IDisposable From d9fbc86ce16726d5eb136ad3cd2be812a05db320 Mon Sep 17 00:00:00 2001 From: Georgii Borovinskikh Date: Thu, 28 Dec 2023 12:33:23 +0100 Subject: [PATCH 3/3] Update branch --- src/SLCore.UnitTests/Process/SLCoreRunner.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/SLCore.UnitTests/Process/SLCoreRunner.cs b/src/SLCore.UnitTests/Process/SLCoreRunner.cs index 3b85dea51a..aa3421a2e7 100644 --- a/src/SLCore.UnitTests/Process/SLCoreRunner.cs +++ b/src/SLCore.UnitTests/Process/SLCoreRunner.cs @@ -26,6 +26,7 @@ using System.Threading.Tasks; using Microsoft.VisualStudio.Threading; using SonarLint.VisualStudio.SLCore.Core; +using SonarLint.VisualStudio.SLCore.Protocol; namespace SonarLint.VisualStudio.SLCore.UnitTests.Process { @@ -69,7 +70,7 @@ public SLCoreRunner(string pathToBat, string logFilePath = null, string errorLog jsonRpcWrapper.TraceSource.Switch.Level = enableVerboseLogs? SourceLevels.Verbose : SourceLevels.Warning; jsonRpcWrapper.TraceSource.Listeners.Add(logFileStream == null ? new ConsoleTraceListener(): new TextWriterTraceListener(logFileStream)); - Rpc = new SLCoreJsonRpc(jsonRpcWrapper); + Rpc = new SLCoreJsonRpc(jsonRpcWrapper, new RpcMethodNameTransformer()); } private void ReadErrorLog(string errorLogFilePath)