Skip to content

Commit

Permalink
Add local install vscode-solidity npm package on language server acti…
Browse files Browse the repository at this point in the history
…vate.
  • Loading branch information
allisterb committed Jan 25, 2024
1 parent d3bce8a commit e22a8a1
Show file tree
Hide file tree
Showing 9 changed files with 294 additions and 26 deletions.
123 changes: 123 additions & 0 deletions src/Stratis.DevEx.Base/Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,129 @@ private static void AppDomain_UnhandledException(object sender, UnhandledExcepti
}
}

public static Dictionary<string, object> RunCmd(string filename, string arguments, string workingdirectory)
{
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = filename;
info.Arguments = arguments;
info.WorkingDirectory = workingdirectory;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
info.UseShellExecute = false;
info.CreateNoWindow = true;
var output = new Dictionary<string, object>();
using (var process = new Process())
{
process.StartInfo = info;
try
{
if (!process.Start())
{
output["error"] = ("Could not start {file} {args} in {dir}.", info.FileName, info.Arguments, info.WorkingDirectory);
return output;
}
var stdout = process.StandardOutput.ReadToEnd();
var stderr = process.StandardError.ReadToEnd();
if (stdout != null && stdout.Length > 0)
{
output["stdout"] = stdout;
}
if (stderr != null && stderr.Length > 0)
{
output["stderr"] = stderr;
}
return output;
}
catch (Exception ex)
{
output["exception"] = ex;
return output;
}
}
}

public static async Task<Dictionary<string, object>> RunCmdAsync(string filename, string arguments, string workingdirectory)
{
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = filename;
info.Arguments = arguments;
info.WorkingDirectory = workingdirectory;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
info.UseShellExecute = false;
info.CreateNoWindow = true;
var output = new Dictionary<string, object>();
using (var process = new Process())
{
process.StartInfo = info;
try
{
if (!process.Start())
{
output["error"] = ("Could not start {file} {args} in {dir}.", info.FileName, info.Arguments, info.WorkingDirectory);
return output;
}
var stdout = await process.StandardOutput.ReadToEndAsync();
var stderr = await process.StandardError.ReadToEndAsync();
if (stdout != null && stdout.Length > 0)
{
output["stdout"] = stdout;
}
if (stderr != null && stderr.Length > 0)
{
output["stderr"] = stderr;
}
return output;
}
catch (Exception ex)
{
output["exception"] = ex;
return output;
}
}
}

public static bool CheckRunCmdOutput(Dictionary<string, object> output, string checktext)
{
if (output.ContainsKey("error") || output.ContainsKey("exception"))
{
if (output.ContainsKey("error"))
{
Error((string)output["error"]);
}
if (output.ContainsKey("exception"))
{
Error((Exception) output["exception"], "Exception thrown during process execution.");
}
return false;
}
else
{
if (output.ContainsKey("stderr"))
{
var stderr = (string)output["stderr"];
Info(stderr);
}
if (output.ContainsKey("stdout"))
{
var stdout = (string)output["stdout"];
Info(stdout);
if (stdout.Contains(checktext))
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
}

public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive = false)
{
using var op = Begin("Copying {0} to {1}", sourceDir, destinationDir);
Expand Down
85 changes: 67 additions & 18 deletions src/Stratis.VS.StratisEVM/SolidityLanguageClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using Microsoft.VisualStudio.Shell.Interop;
using System.Windows.Ink;
using Stratis.VS.StratisEVM;
using System.Text;

namespace Stratis.VS
{
Expand All @@ -45,8 +46,8 @@ public SolidityLanguageClient()
#endregion

#region Properties
public static string SolutionOpenFolder {get; set;}
public static string SolutionOpenFolder { get; set; }

public string Name => "Solidity Language Extension";

public IEnumerable<string> ConfigurationSections
Expand Down Expand Up @@ -77,26 +78,27 @@ internal static SolidityLanguageClient Instance
set;
}

internal System.Diagnostics.Process ServerProcess { get; set; }

internal JsonRpc Rpc
{
get;
set;
}
#endregion

#region Events
public event AsyncEventHandler<EventArgs> StartAsync;
public event AsyncEventHandler<EventArgs> StopAsync;
#endregion

#region Methods
protected bool StartLanguageServerProcess()
{
ProcessStartInfo info = new ProcessStartInfo();
var programPath = "cmd.exe";
info.FileName = programPath;
info.Arguments = "/c " + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "npm", "nomicfoundation-solidity-language-server.cmd") + " --stdio";
//info.Arguments = "/c " + "node " + "c:\\Projects\\vscode-solidity\\dist\\cli\\server.js" + " --stdio";
//info.Arguments = "/c " + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "npm", "nomicfoundation-solidity-language-server.cmd") + " --stdio";
info.Arguments = "/c " + "node \"" + Path.Combine(Runtime.AssemblyLocation, "node_modules", "solidity", "dist", "cli", "server.js") + "\" --stdio";
info.WorkingDirectory = AssemblyLocation;
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
Expand All @@ -108,15 +110,51 @@ protected bool StartLanguageServerProcess()
{
Info("Language server proceess exited.");
};
ServerProcess = process;
return process.Start();
serverProcess = process;
try
{
return process.Start();
}
catch (Exception ex)
{
Error(ex, "Exception thrown starting language server process.");
return false;
}

}

public static Dictionary<string, object> InstallVSCodeSolidityLanguageServer()
{
return RunCmd("cmd.exe", "/c npm install solidity-0.0.165.tgz --force --quiet --no-progress", AssemblyLocation);
}

public static async Task<Dictionary<string, object>> InstallVSCodeSolidityLanguageServerAsync()
{
return await RunCmdAsync("cmd.exe", "/c npm install solidity-0.0.165.tgz --force --quiet --no-progress", AssemblyLocation);
}

#region ILanguageClient, ILanguageClientCustomMessage2 implementation
public async Task<Connection> ActivateAsync(CancellationToken token)
{
await Task.Yield();
var solution = (IVsSolution) await ServiceProvider.GetGlobalServiceAsync(typeof(SVsSolution));
if (Directory.Exists(Path.Combine(Runtime.AssemblyLocation, "node_modules")) && File.Exists(Path.Combine(Runtime.AssemblyLocation, "node_modules", "solidity", "dist", "cli", "server.js")))
{
Info("VSCode Solidity language server present.");
}
else
{
var output = await InstallVSCodeSolidityLanguageServerAsync();
if (CheckRunCmdOutput(output, "Run `npm audit` for details."))
{
Info("VSCode Solidity language server installed.");
}
else
{
Error("Could not install VSCode Solidity language server.");
return null;
}
}
var solution = (IVsSolution)await ServiceProvider.GetGlobalServiceAsync(typeof(SVsSolution));
solution.GetSolutionInfo(out var dir, out var f, out var d);
Info("Solution dir is {d}", dir);
this.InitializationOptions = JObject.FromObject(new
Expand All @@ -134,12 +172,12 @@ public async Task<Connection> ActivateAsync(CancellationToken token)

if (StartLanguageServerProcess())
{
Info("Started language server process {proc} {p}.", ServerProcess.StartInfo.FileName, ServerProcess.StartInfo.Arguments);
return new Connection(ServerProcess.StandardOutput.BaseStream, ServerProcess.StandardInput.BaseStream);
Info("Started language server process {proc} {p}.", serverProcess.StartInfo.FileName, serverProcess.StartInfo.Arguments);
return new Connection(serverProcess.StandardOutput.BaseStream, serverProcess.StandardInput.BaseStream);
}
else
{
Info("Could not start language server process {proc}", ServerProcess.StartInfo.FileName);
Error("Could not start language server process: {proc} {args}. Exit code: {code}.", serverProcess.StartInfo.FileName, serverProcess.StartInfo.Arguments, serverProcess.ExitCode);
return null;
}
}
Expand Down Expand Up @@ -189,6 +227,8 @@ public Task<InitializationFailureContext> OnServerInitializeFailedAsync(ILanguag
#endregion

#endregion

#region Types
internal class SolidityLanguageClientMiddleLayer : ILanguageClientMiddleLayer
{
public bool CanHandle(string methodName)
Expand All @@ -198,25 +238,25 @@ public bool CanHandle(string methodName)

public async Task HandleNotificationAsync(string methodName, JToken methodParam, Func<JToken, Task> sendNotification)
{
Info("Notification {req} {param}.", methodName, methodParam.ToString());
await sendNotification(methodParam);
/*
//Info("Notification {req} {param}.", methodName, methodParam.ToString());
//await sendNotification(methodParam);

if (methodName == "textDocument/didChange")
{
methodParam.Root["contentChanges"] = JArray.FromObject(new[] {new
methodParam.Root["contentChanges"] = JArray.FromObject(new[] {new
{
text = methodParam.Root["contentChanges"][0]["text"].Value<string>(),
} });
Info("didchange Notification {req} {param}.", methodName, methodParam.ToString());
await sendNotification(methodParam);

}
else
{
Info("Notification {req} {param}.", methodName, methodParam.ToString());
await sendNotification(methodParam);
}
*/

}

public async Task<JToken> HandleRequestAsync(string methodName, JToken methodParam, Func<JToken, Task<JToken>> sendRequest)
Expand All @@ -226,5 +266,14 @@ public async Task<JToken> HandleRequestAsync(string methodName, JToken methodPar
return resp;
}
}
#endregion

#region Fields
internal System.Diagnostics.Process serverProcess;
#endregion
}




}
2 changes: 1 addition & 1 deletion src/Stratis.VS.StratisEVM/SolidityLanguageSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
"solidity.maxNumberOfProblems": 1,
"solidity.enabledAsYouTypeCompilationErrorCheck": true,
"solidity.defaultCompiler": "localFile",
"solidity.compileUsingLocalVersion": "C:\\Users\\Allister\\Downloads\\soljson.js"
"solidity.compileUsingLocalVersion": "C:\\Users\\Allister\\Downloads\\soljson-v0.8.23+commit.f704f362.js"
}
6 changes: 6 additions & 0 deletions src/Stratis.VS.StratisEVM/Stratis.VS.StratisEVM.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@
<Content Include="SolidityLanguageSettings.json">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="solidity-0.0.165.tgz">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<Content Include="package.json">
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
<None Include="source.extension.vsixmanifest">
<SubType>Designer</SubType>
</None>
Expand Down
41 changes: 40 additions & 1 deletion src/Stratis.VS.StratisEVM/StratisEVMPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
using Microsoft.VisualStudio.Shell.Interop;
using Stratis.DevEx;
using Microsoft.VisualStudio.TaskRunnerExplorer;
using Microsoft.IO;
using System.Windows.Threading;
using System.Collections.Generic;

namespace Stratis.VS.StratisEVM
{
Expand Down Expand Up @@ -91,17 +94,53 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
await this.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
if (VSUtil.InitializeVSServices(ServiceProvider.GlobalProvider))
{
Runtime.Info("StratisEVM package initialized.");
VSUtil.LogInfo("Stratis EVM", $"Extension assembly directory is {Runtime.AssemblyLocation}. StratisEVM package initialized.");
}
else
{
Runtime.Error("Could not initialize StratisEVM package VS services.");
return;
}

/*
if (Directory.Exists(Path.Combine(Runtime.AssemblyLocation, "node_modules")) && File.Exists(Path.Combine(Runtime.AssemblyLocation, "node_modules")))
{
VSUtil.LogInfo("Stratis EVM", "VSCode Solidity language server present.");
}
else
{
VSUtil.LogInfo("Stratis EVM", "VSCode Solidity language server not present, installing...");
/*
ThreadPool.QueueUserWorkItem((o) =>
{
var output = SolidityLanguageClient.InstallVSCodeSolidityLanguageServer();
ThreadHelper.JoinableTaskContext.MainThread.
});
var output = await SolidityLanguageClient.InstallVSCodeSolidityLanguageServerAsync();
if (VSUtil.CheckRunCmdOutput(output, "Stratis EVM", "Run `npm audit` for details."))
{
VSUtil.LogInfo("Stratis EVM", "VSCode Solidity language server installed.");
}
else
{
VSUtil.LogError("Stratis EVM", "Could not install VSCode Solidity language server.");
}
}
*/
// When initialized asynchronously, the current thread may be a background thread at this point.
// Do any initialization that requires the UI thread after switching to the UI thread.
}
#endregion

#endregion

#region Fields
public static Dispatcher _dispatcher;
#endregion
}
}
Loading

0 comments on commit e22a8a1

Please sign in to comment.