diff --git a/Src/CSharpier.VisualStudio/CSharpier.VisualStudio.csproj b/Src/CSharpier.VisualStudio/CSharpier.VisualStudio.csproj
index 527db7988..62baf6d8e 100644
--- a/Src/CSharpier.VisualStudio/CSharpier.VisualStudio.csproj
+++ b/Src/CSharpier.VisualStudio/CSharpier.VisualStudio.csproj
@@ -46,7 +46,9 @@
4
-
+
+ Component
+
@@ -58,7 +60,7 @@
-
+
@@ -88,11 +90,4 @@
-
\ No newline at end of file
diff --git a/Src/CSharpier.VisualStudio/CSharpierOptionsPage.cs b/Src/CSharpier.VisualStudio/CSharpierOptionsPage.cs
index 347d52fd9..3470c70c1 100644
--- a/Src/CSharpier.VisualStudio/CSharpierOptionsPage.cs
+++ b/Src/CSharpier.VisualStudio/CSharpierOptionsPage.cs
@@ -3,16 +3,11 @@
namespace CSharpier.VisualStudio
{
- // TODO see https://github.com/Elders/VSE-FormatDocumentOnSave for how that works, I think Settings can go away
public class CSharpierOptionsPage : DialogPage
{
[Category("CSharpier")]
[DisplayName("Reformat with CSharpier on Save")]
[Description("Reformat with CSharpier on Save")]
- public bool RunOnSave
- {
- get => Settings.Instance.RunOnSave;
- set => Settings.Instance.RunOnSave = value;
- }
+ public bool RunOnSave { get; set; }
}
}
diff --git a/Src/CSharpier.VisualStudio/CSharpierPackage.cs b/Src/CSharpier.VisualStudio/CSharpierPackage.cs
index 6ff3eef4e..208f82f6a 100644
--- a/Src/CSharpier.VisualStudio/CSharpierPackage.cs
+++ b/Src/CSharpier.VisualStudio/CSharpierPackage.cs
@@ -1,10 +1,8 @@
using System;
using System.Runtime.InteropServices;
using System.Threading;
-using Microsoft.VisualStudio.Settings;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
-using Microsoft.VisualStudio.Shell.Settings;
using Task = System.Threading.Tasks.Task;
namespace CSharpier.VisualStudio
@@ -28,12 +26,20 @@ IProgress progress
var outputPane = await this.GetServiceAsync(typeof(SVsOutputWindow)) as IVsOutputWindow;
var logger = new Logger(outputPane);
logger.Log("Starting");
-
+
+ await InfoBarService.InitializeAsync(this);
+
var csharpierService = new CSharpierService(logger);
var formattingService = new FormattingService(logger, csharpierService);
- await Settings.InitializeAsync(this);
- await ReformatWithCSharpierOnSave.InitializeAsync(this, formattingService);
+ var csharpierOptionsPage = (CSharpierOptionsPage)GetDialogPage(
+ typeof(CSharpierOptionsPage)
+ );
+ await ReformatWithCSharpierOnSave.InitializeAsync(
+ this,
+ formattingService,
+ csharpierOptionsPage
+ );
await ReformatWithCSharpier.InitializeAsync(this, formattingService);
}
}
diff --git a/Src/CSharpier.VisualStudio/CSharpierProcessPipeMultipleFiles.cs b/Src/CSharpier.VisualStudio/CSharpierProcessPipeMultipleFiles.cs
index 1d209b0b0..93bc6db83 100644
--- a/Src/CSharpier.VisualStudio/CSharpierProcessPipeMultipleFiles.cs
+++ b/Src/CSharpier.VisualStudio/CSharpierProcessPipeMultipleFiles.cs
@@ -7,7 +7,6 @@
namespace CSharpier.VisualStudio
{
- // TODO what about disposing this?
public class CSharpierProcessPipeMultipleFiles : ICSharpierProcess
{
private readonly Logger logger;
@@ -17,8 +16,11 @@ public class CSharpierProcessPipeMultipleFiles : ICSharpierProcess
public CSharpierProcessPipeMultipleFiles(string csharpierPath, Logger logger)
{
this.logger = logger;
-
- var processStartInfo = new ProcessStartInfo("dotnet", csharpierPath + " --pipe-multiple-files")
+
+ var processStartInfo = new ProcessStartInfo(
+ "dotnet",
+ csharpierPath + " --pipe-multiple-files"
+ )
{
RedirectStandardInput = true,
RedirectStandardOutput = true,
@@ -32,6 +34,8 @@ public CSharpierProcessPipeMultipleFiles(string csharpierPath, Logger logger)
this.FormatFile("public class ClassName { }", "Test.cs");
}
+ public bool CanFormat => true;
+
public string FormatFile(string content, string fileName)
{
process.StandardInput.Write(fileName);
@@ -45,7 +49,7 @@ public string FormatFile(string content, string fileName)
var outputReaderThread = CreateReadingThread(process.StandardOutput, output);
var errorReaderThread = CreateReadingThread(process.StandardError, errorOutput);
-
+
outputReaderThread.Start();
errorReaderThread.Start();
@@ -53,41 +57,46 @@ public string FormatFile(string content, string fileName)
{
Thread.Sleep(TimeSpan.FromMilliseconds(1));
}
-
+
outputReaderThread.Interrupt();
errorReaderThread.Interrupt();
-
+
var errorResult = errorOutput.ToString();
if (string.IsNullOrEmpty(errorResult))
{
return output.ToString();
}
-
+
this.logger.Log("Got error output: " + errorResult);
return "";
-
}
private Thread CreateReadingThread(StreamReader reader, StringBuilder stringBuilder)
{
- return new Thread(() => {
- try {
- var nextCharacter = reader.Read();
- while (nextCharacter != -1) {
- if (nextCharacter == '\u0003')
+ return new Thread(
+ () =>
+ {
+ try
+ {
+ var nextCharacter = reader.Read();
+ while (nextCharacter != -1)
{
- done = true;
- return;
+ if (nextCharacter == '\u0003')
+ {
+ done = true;
+ return;
+ }
+ stringBuilder.Append((char)nextCharacter);
+ nextCharacter = reader.Read();
}
- stringBuilder.Append((char) nextCharacter);
- nextCharacter = reader.Read();
}
- } catch (Exception e)
- {
- // TODO log
- done = true;
+ catch (Exception e)
+ {
+ logger.Log(e);
+ done = true;
+ }
}
- });
+ );
}
}
-}
\ No newline at end of file
+}
diff --git a/Src/CSharpier.VisualStudio/CSharpierProcessSingleFile.cs b/Src/CSharpier.VisualStudio/CSharpierProcessSingleFile.cs
index 6246d9a5c..a88db40e1 100644
--- a/Src/CSharpier.VisualStudio/CSharpierProcessSingleFile.cs
+++ b/Src/CSharpier.VisualStudio/CSharpierProcessSingleFile.cs
@@ -14,6 +14,8 @@ public CSharpierProcessSingleFile(string csharpierPath, Logger logger)
this.logger = logger;
}
+ public bool CanFormat => true;
+
public string FormatFile(string content, string fileName)
{
var output = new StringBuilder();
diff --git a/Src/CSharpier.VisualStudio/CSharpierService.cs b/Src/CSharpier.VisualStudio/CSharpierService.cs
index 2117e7a51..5e75bafd6 100644
--- a/Src/CSharpier.VisualStudio/CSharpierService.cs
+++ b/Src/CSharpier.VisualStudio/CSharpierService.cs
@@ -1,8 +1,12 @@
using System;
using System.Diagnostics;
+using System.Windows.Forms;
namespace CSharpier.VisualStudio
{
+ // TODO figure out how to publish https://docs.microsoft.com/en-us/visualstudio/extensibility/walkthrough-publishing-a-visual-studio-extension?view=vs-2022
+ // TODO make this work in 2022 https://docs.microsoft.com/en-us/visualstudio/extensibility/migration/update-visual-studio-extension?view=vs-2022
+
public class CSharpierService
{
private readonly string csharpierPath;
@@ -42,8 +46,6 @@ public string GetCSharpierPath()
public string ExecuteCommand(string cmd, string arguments)
{
- // TODO when testing, this runs from in the csharpier directory, which means it uses csharpier from there instead of globally
-
var processStartInfo = new ProcessStartInfo(cmd, arguments)
{
UseShellExecute = false,
@@ -51,6 +53,10 @@ public string ExecuteCommand(string cmd, string arguments)
RedirectStandardOutput = true,
WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true,
+#if DEBUG
+ // TODO when testing, this runs from in the csharpier directory, which means it uses csharpier from there instead of globally
+ WorkingDirectory = "C:/"
+#endif
};
using var process = new Process { StartInfo = processStartInfo };
@@ -66,7 +72,7 @@ private ICSharpierProcess SetupCSharpierProcess()
{
var version = ExecuteCommand("dotnet", this.csharpierPath + " --version");
this.logger.Log("CSharpier version: " + version);
- if (version == null)
+ if (string.IsNullOrEmpty(version))
{
this.DisplayInstallNeededMessage();
}
@@ -78,10 +84,7 @@ private ICSharpierProcess SetupCSharpierProcess()
{
var content =
"Please upgrade to CSharpier >= 0.12.0 for bug fixes and improved formatting speed.";
- // TODO notify if csharpier should be updated
- // NotificationGroupManager.getInstance().getNotificationGroup("CSharpier")
- // .createNotification(content, NotificationType.INFORMATION)
- // .notify(project);
+ InfoBarService.Instance.ShowInfoBar(content);
return new CSharpierProcessSingleFile(this.csharpierPath, this.logger);
}
@@ -98,17 +101,18 @@ private ICSharpierProcess SetupCSharpierProcess()
private void DisplayInstallNeededMessage()
{
- // TODO notify if not installed
- // Notification notification = NotificationGroupManager.getInstance().getNotificationGroup("CSharpier")
- // .createNotification("CSharpier must be installed globally to support formatting.", NotificationType.WARNING);
- //
- // // notification.addAction(new EditAction());
- //
- // notification.notify(project);
+ InfoBarService.Instance.ShowInfoBar("CSharpier must be installed globally to support formatting.");
}
+ public bool CanFormat => this.csharpierProcess.CanFormat;
+
public string Format(string content, string filePath)
{
+ if (!this.csharpierProcess.CanFormat)
+ {
+ return null;
+ }
+
this.logger.Log("Formatting " + filePath);
try
{
diff --git a/Src/CSharpier.VisualStudio/FormattingService.cs b/Src/CSharpier.VisualStudio/FormattingService.cs
index 51b2b106d..7d8f98e5e 100644
--- a/Src/CSharpier.VisualStudio/FormattingService.cs
+++ b/Src/CSharpier.VisualStudio/FormattingService.cs
@@ -5,14 +5,16 @@ namespace CSharpier.VisualStudio
public class FormattingService
{
private readonly Logger logger;
- private readonly CSharpierService cSharpierService;
+ private readonly CSharpierService csharpierService;
- public FormattingService(Logger logger, CSharpierService cSharpierService)
+ public FormattingService(Logger logger, CSharpierService csharpierService)
{
this.logger = logger;
- this.cSharpierService = cSharpierService;
+ this.csharpierService = csharpierService;
}
+ public bool CanFormat => this.csharpierService.CanFormat;
+
public void Format(Document document)
{
Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread();
@@ -32,7 +34,7 @@ public void Format(Document document)
var endPoint = textDocument.EndPoint.CreateEditPoint();
var text = editPoint.GetText(endPoint);
- var newText = this.cSharpierService.Format(text, document.FullName);
+ var newText = this.csharpierService.Format(text, document.FullName);
if (string.IsNullOrEmpty(newText))
{
return;
diff --git a/Src/CSharpier.VisualStudio/ICSharpierProcess.cs b/Src/CSharpier.VisualStudio/ICSharpierProcess.cs
index 9d4ef41c9..91b59c0da 100644
--- a/Src/CSharpier.VisualStudio/ICSharpierProcess.cs
+++ b/Src/CSharpier.VisualStudio/ICSharpierProcess.cs
@@ -2,6 +2,7 @@ namespace CSharpier.VisualStudio
{
public interface ICSharpierProcess
{
+ bool CanFormat { get; }
string FormatFile(string content, string fileName);
}
}
diff --git a/Src/CSharpier.VisualStudio/InfoBarService.cs b/Src/CSharpier.VisualStudio/InfoBarService.cs
new file mode 100644
index 000000000..7afbb76fa
--- /dev/null
+++ b/Src/CSharpier.VisualStudio/InfoBarService.cs
@@ -0,0 +1,65 @@
+using System.Windows.Forms;
+using Microsoft.VisualStudio.Imaging;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Shell.Interop;
+using Task = System.Threading.Tasks.Task;
+
+namespace CSharpier.VisualStudio
+{
+public class InfoBarService : IVsInfoBarUIEvents
+ {
+ private readonly CSharpierPackage csharpierPackage;
+ private uint cookie;
+
+ private InfoBarService(CSharpierPackage csharpierPackage)
+ {
+ this.csharpierPackage = csharpierPackage;
+ }
+
+ public static InfoBarService Instance { get; private set; }
+
+ public static Task InitializeAsync(CSharpierPackage serviceProvider)
+ {
+ Instance = new InfoBarService(serviceProvider);
+
+ return Task.CompletedTask;
+ }
+
+ public void OnClosed(IVsInfoBarUIElement infoBarUiElement)
+ {
+ infoBarUiElement.Unadvise(cookie);
+ }
+
+ public void OnActionItemClicked(IVsInfoBarUIElement infoBarUIElement, IVsInfoBarActionItem actionItem)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public void ShowInfoBar(string message)
+ {
+ ThreadHelper.ThrowIfNotOnUIThread();
+
+ var shell = csharpierPackage.GetServiceAsync(typeof(SVsShell)).Result as IVsShell;
+ if (shell == null)
+ {
+ return;
+ }
+
+ shell.GetProperty((int) __VSSPROPID7.VSSPROPID_MainWindowInfoBarHost, out var property);
+ if (!(property is IVsInfoBarHost infoBarHost))
+ {
+ return;
+ }
+ var text = new InfoBarTextSpan(message);
+
+ var spans = new[] { text };
+ var actions = new InfoBarActionItem[] { };
+ var infoBarModel = new InfoBarModel(spans, actions, KnownMonikers.StatusInformation, isCloseButtonVisible: true);
+
+ var factory = csharpierPackage.GetServiceAsync(typeof(SVsInfoBarUIFactory)).Result as IVsInfoBarUIFactory;
+ var element = factory.CreateInfoBar(infoBarModel);
+ element.Advise(this, out cookie);
+ infoBarHost.AddInfoBar(element);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/CSharpier.VisualStudio/NullCSharpierProcess.cs b/Src/CSharpier.VisualStudio/NullCSharpierProcess.cs
index f7509502f..5304db78d 100644
--- a/Src/CSharpier.VisualStudio/NullCSharpierProcess.cs
+++ b/Src/CSharpier.VisualStudio/NullCSharpierProcess.cs
@@ -2,6 +2,8 @@ namespace CSharpier.VisualStudio
{
public class NullCSharpierProcess : ICSharpierProcess
{
+ public bool CanFormat => false;
+
public string FormatFile(string content, string fileName)
{
return null;
diff --git a/Src/CSharpier.VisualStudio/ReformatWithCSharpier.cs b/Src/CSharpier.VisualStudio/ReformatWithCSharpier.cs
index c0156f8fc..f16788efa 100644
--- a/Src/CSharpier.VisualStudio/ReformatWithCSharpier.cs
+++ b/Src/CSharpier.VisualStudio/ReformatWithCSharpier.cs
@@ -44,6 +44,7 @@ private void QueryStatus(object sender, EventArgs e)
var button = (OleMenuCommand)sender;
button.Visible = dte.ActiveDocument.Name.EndsWith(".cs");
+ button.Enabled = this.formattingService.CanFormat;
}
public static ReformatWithCSharpier Instance { get; private set; }
@@ -66,6 +67,10 @@ FormattingService formattingService
private void Execute(object sender, EventArgs e)
{
ThreadHelper.ThrowIfNotOnUIThread();
+ if (!this.formattingService.CanFormat)
+ {
+ return;
+ }
this.formattingService.Format(this.dte.ActiveDocument);
}
}
diff --git a/Src/CSharpier.VisualStudio/ReformatWithCSharpierOnSave.cs b/Src/CSharpier.VisualStudio/ReformatWithCSharpierOnSave.cs
index 4a1e1163d..53949ac97 100644
--- a/Src/CSharpier.VisualStudio/ReformatWithCSharpierOnSave.cs
+++ b/Src/CSharpier.VisualStudio/ReformatWithCSharpierOnSave.cs
@@ -13,21 +13,25 @@ public class ReformatWithCSharpierOnSave : IVsRunningDocTableEvents3
private readonly DTE dte;
private readonly RunningDocumentTable runningDocumentTable;
private readonly FormattingService formattingService;
+ private readonly CSharpierOptionsPage csharpierOptionsPage;
private ReformatWithCSharpierOnSave(
DTE dte,
RunningDocumentTable runningDocumentTable,
- FormattingService formattingService
+ FormattingService formattingService,
+ CSharpierOptionsPage csharpierOptionsPage
)
{
this.dte = dte;
this.runningDocumentTable = runningDocumentTable;
this.formattingService = formattingService;
+ this.csharpierOptionsPage = csharpierOptionsPage;
}
public static async Task InitializeAsync(
CSharpierPackage csharpierPackage,
- FormattingService formattingService
+ FormattingService formattingService,
+ CSharpierOptionsPage cSharpierOptionsPage
)
{
var dte = await csharpierPackage.GetServiceAsync(typeof(DTE)) as DTE;
@@ -35,14 +39,15 @@ FormattingService formattingService
var reformatWithCSharpierOnSave = new ReformatWithCSharpierOnSave(
dte,
runningDocumentTable,
- formattingService
+ formattingService,
+ cSharpierOptionsPage
);
runningDocumentTable.Advise(reformatWithCSharpierOnSave);
}
public int OnBeforeSave(uint docCookie)
{
- if (!Settings.Instance.RunOnSave)
+ if (!this.csharpierOptionsPage.RunOnSave)
{
return VSConstants.S_OK;
}
diff --git a/Src/CSharpier.VisualStudio/Settings.cs b/Src/CSharpier.VisualStudio/Settings.cs
deleted file mode 100644
index 3145215e0..000000000
--- a/Src/CSharpier.VisualStudio/Settings.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using System.Threading.Tasks;
-using Microsoft.VisualStudio.Settings;
-using Microsoft.VisualStudio.Shell.Settings;
-
-namespace CSharpier.VisualStudio
-{
- public class Settings
- {
- private readonly WritableSettingsStore userSettingsStore;
-
- private Settings(WritableSettingsStore userSettingsStore)
- {
- this.userSettingsStore = userSettingsStore;
- }
-
- public static Settings Instance { get; private set; }
-
- public static Task InitializeAsync(CSharpierPackage package)
- {
- var settingsManager = new ShellSettingsManager(package);
- var userSettingsStore = settingsManager.GetWritableSettingsStore(
- SettingsScope.UserSettings
- );
- if (!userSettingsStore.CollectionExists("csharpier"))
- {
- userSettingsStore.CreateCollection("csharpier");
- userSettingsStore.SetBoolean("csharpier", "RunOnSave", false);
- }
-
- Instance = new Settings(userSettingsStore);
-
- return Task.CompletedTask;
- }
-
- public bool RunOnSave
- {
- get => userSettingsStore.GetBoolean("csharpier", "RunOnSave");
- set => userSettingsStore.SetBoolean("csharpier", "RunOnSave", value);
- }
- }
-}