From 66e25135841b1b8d23cb7458f60366c32ef25219 Mon Sep 17 00:00:00 2001 From: Sergey M Date: Mon, 10 Aug 2020 08:30:43 -0400 Subject: [PATCH 1/4] Logging readability improvements. --- .../Features/BookmarksServiceTests.cs | 13 ++++++- .../Features/FileBrowserViewModelTests.cs | 2 +- .../SupportOptionsFirstTimeUseTests.cs | 7 +--- DPackRx.Tests/Options/OptionsServiceTests.cs | 2 + .../Services/SearchMatchServiceTests.cs | 38 ++++++++++--------- DPackRx/CodeModel/FileProcessor.cs | 27 ++++++------- DPackRx/CodeModel/FileTypeResolver.cs | 16 ++++---- DPackRx/CodeModel/IFileProcessor.cs | 1 - DPackRx/CodeModel/ProjectProcessor.cs | 9 +++-- DPackRx/CodeModel/SolutionProcessor.cs | 14 ++++--- DPackRx/DPackRx.csproj | 1 + DPackRx/Extensions/KnownFeatureExtensions.cs | 22 +++++++++++ DPackRx/Extensions/LogExtensions.cs | 5 +-- DPackRx/Features/Bookmarks/BookmarkTag.cs | 5 ++- .../Bookmarks/BookmarksSimpleTagger.cs | 2 +- .../CodeBrowser/CodeBrowserViewModel.cs | 4 +- DPackRx/Features/Feature.cs | 10 ++--- .../FileBrowser/FileBrowserViewModel.cs | 5 +-- .../Miscellaneous/MiscellaneousFeature.cs | 15 ++++---- .../SupportOptions/SupportOptionsFeature.cs | 4 +- .../SupportOptionsFirstTimeUse.cs | 7 +--- DPackRx/Helpers/KeyboardHelper.cs | 5 +-- .../Language/LanguageRegistrationService.cs | 4 +- DPackRx/Language/LanguageService.cs | 4 +- DPackRx/Language/LanguageSettings.cs | 12 +++--- DPackRx/Options/OptionsFileBrowser.cs | 2 +- DPackRx/Options/OptionsGeneral.cs | 4 +- DPackRx/Options/OptionsPersistenceService.cs | 6 ++- DPackRx/Options/OptionsService.cs | 7 +++- DPackRx/Package.cs | 14 ++++--- DPackRx/Package/FeatureCommand.cs | 6 ++- DPackRx/Package/GUIDs.cs | 14 +++---- DPackRx/Package/LanguageConsts.cs | 14 +++---- ...InstalledProductRegistrationExAttribute.cs | 2 +- DPackRx/Services/FeatureFactory.cs | 20 +++++----- DPackRx/Services/Log.cs | 28 +++++++------- DPackRx/Services/ShellEventsService.cs | 22 +++++------ DPackRx/Services/ShellInfoBarService.cs | 9 +++-- 38 files changed, 214 insertions(+), 168 deletions(-) create mode 100644 DPackRx/Extensions/KnownFeatureExtensions.cs diff --git a/DPackRx.Tests/Features/BookmarksServiceTests.cs b/DPackRx.Tests/Features/BookmarksServiceTests.cs index 4492a95..024b909 100644 --- a/DPackRx.Tests/Features/BookmarksServiceTests.cs +++ b/DPackRx.Tests/Features/BookmarksServiceTests.cs @@ -378,7 +378,6 @@ public void GoToBookmark_ErrorHandling() [TestCase(null)] [TestCase("")] - [TestCase("bad")] public void GoToBookmark_NoFile(string fileName) { var service = GetService(); @@ -429,6 +428,18 @@ public void GoToBookmark_InvalidLine() _shellStatusBarServiceMock.Verify(s => s.SetStatusBarText(It.IsNotNull())); } + [Test] + public void GoToBookmark_NoFileBookmarks() + { + var service = GetService(); + + var result = service.GoToBookmark(1); + + Assert.That(result, Is.False); + _shellSelectionServiceMock.Verify(s => s.GetActiveFileName()); + _shellStatusBarServiceMock.Verify(s => s.SetStatusBarText(It.IsNotNull())); + } + [Test] public void SetGlobalBookmark() { diff --git a/DPackRx.Tests/Features/FileBrowserViewModelTests.cs b/DPackRx.Tests/Features/FileBrowserViewModelTests.cs index 4a5d1b2..d0003f9 100644 --- a/DPackRx.Tests/Features/FileBrowserViewModelTests.cs +++ b/DPackRx.Tests/Features/FileBrowserViewModelTests.cs @@ -356,7 +356,7 @@ public void OpenFilesCommand_Execute(bool controlKeyDown) var selection = new List(); viewModel.OpenFilesCommand.Execute(selection); - Assert.That(viewModel.SelectionCode, Is.EqualTo(controlKeyDown ? false : true)); + Assert.That(viewModel.SelectionCode, Is.EqualTo(!controlKeyDown)); Assert.That(viewModel.Selection, Is.EqualTo(selection)); Assert.That(viewModel.CloseWindow, Is.True); _utilsServiceMock.Verify(u => u.ControlKeyDown()); diff --git a/DPackRx.Tests/Features/SupportOptionsFirstTimeUseTests.cs b/DPackRx.Tests/Features/SupportOptionsFirstTimeUseTests.cs index f490588..dffa833 100644 --- a/DPackRx.Tests/Features/SupportOptionsFirstTimeUseTests.cs +++ b/DPackRx.Tests/Features/SupportOptionsFirstTimeUseTests.cs @@ -19,7 +19,6 @@ public class SupportOptionsFirstTimeUseTests { #region Fields - private Mock _logMock; private Mock _optionsServiceMock; private Mock _packageServiceMock; private Mock _shellHelperServiceMock; @@ -33,9 +32,6 @@ public class SupportOptionsFirstTimeUseTests [SetUp] public void Setup() { - _logMock = new Mock(); - _logMock.Setup(l => l.LogMessage(It.IsAny(), It.IsAny())).Verifiable(); - _optionsServiceMock = new Mock(); _optionsServiceMock.Setup(o => o.GetBoolOption(It.IsAny(), It.IsAny(), false)).Returns(false).Verifiable(); _optionsServiceMock.Setup(o => o.SetBoolOption(It.IsAny(), It.IsAny(), true)).Verifiable(); @@ -57,7 +53,6 @@ public void Setup() [TearDown] public void TearDown() { - _logMock = null; _optionsServiceMock = null; _packageServiceMock = null; _shellHelperServiceMock = null; @@ -73,7 +68,7 @@ public void TearDown() /// private ISolutionEvents GetFeature() { - return new SupportOptionsFirstTimeUse(_logMock.Object, _optionsServiceMock.Object, + return new SupportOptionsFirstTimeUse(_optionsServiceMock.Object, _packageServiceMock.Object, _shellHelperServiceMock.Object, _shellInfoBarServiceMock.Object, _messageServiceMock.Object); } diff --git a/DPackRx.Tests/Options/OptionsServiceTests.cs b/DPackRx.Tests/Options/OptionsServiceTests.cs index da294c7..7f118e4 100644 --- a/DPackRx.Tests/Options/OptionsServiceTests.cs +++ b/DPackRx.Tests/Options/OptionsServiceTests.cs @@ -358,6 +358,7 @@ public void Flush() Assert.That(changed, Is.True); _optionsPersistenceServiceMock.Verify(o => o.SaveOptions(KnownFeature.SupportOptions, It.IsAny>())); + _logMock.Verify(l => l.LogMessage(It.IsNotNull(), It.IsNotNull())); } [Test] @@ -421,6 +422,7 @@ public void ResetAll() _optionsPersistenceServiceMock.Verify(o => o.LoadOptions(KnownFeature.SupportOptions), Times.Never); _optionsPersistenceServiceMock.Verify(o => o.LoadDefaultOptions(KnownFeature.SupportOptions), Times.Once); _optionsPersistenceServiceMock.Verify(o => o.DeleteOptions(KnownFeature.SupportOptions), Times.Once); + _logMock.Verify(l => l.LogMessage(It.IsNotNull(), It.IsNotNull())); Assert.That(changed, Is.True); Assert.That(reset, Is.True); Assert.That(service.GetOption(KnownFeature.SupportOptions, "test"), Is.EqualTo(789)); diff --git a/DPackRx.Tests/Services/SearchMatchServiceTests.cs b/DPackRx.Tests/Services/SearchMatchServiceTests.cs index e0d3b3d..0d1957e 100644 --- a/DPackRx.Tests/Services/SearchMatchServiceTests.cs +++ b/DPackRx.Tests/Services/SearchMatchServiceTests.cs @@ -86,25 +86,27 @@ private ISearchMatchService GetService() private static List GetItems(bool matched = false, int rank = 0) { - var items = new List(); - items.Add(new TestMatchItem + var items = new List { - ItemSubType = FileSubType.None, - Data = "TestFile1.txt", - PascalCasedData = "TF1", - DataEndingIndex = 9, - Matched = matched, - Rank = rank - }); - items.Add(new TestMatchItem - { - ItemSubType = FileSubType.Code, - Data = "TestCodeFile2.cs", - PascalCasedData = "TCF2", - DataEndingIndex = 13, - Matched = matched, - Rank = rank - }); + new TestMatchItem + { + ItemSubType = FileSubType.None, + Data = "TestFile1.txt", + PascalCasedData = "TF1", + DataEndingIndex = 9, + Matched = matched, + Rank = rank + }, + new TestMatchItem + { + ItemSubType = FileSubType.Code, + Data = "TestCodeFile2.cs", + PascalCasedData = "TCF2", + DataEndingIndex = 13, + Matched = matched, + Rank = rank + } + }; return items; } diff --git a/DPackRx/CodeModel/FileProcessor.cs b/DPackRx/CodeModel/FileProcessor.cs index 6241d02..58537a1 100644 --- a/DPackRx/CodeModel/FileProcessor.cs +++ b/DPackRx/CodeModel/FileProcessor.cs @@ -28,6 +28,7 @@ public class FileProcessor : IFileProcessor private readonly IShellCodeModelService _shellCodeModelService; private readonly IFileTypeResolver _fileTypeResolver; + private const string LOG_CATEGORY = "File Processor"; private const string UNNAMED_NAME = ""; private const string DESTRUCTOR_PREFIX = "~"; private const string DOC_TAG = "doc"; @@ -155,7 +156,7 @@ public bool IsDocumentValid(object document, out object projectItem) } if (!string.IsNullOrEmpty(fileName)) - _log.LogMessage($"Collecting file code model: {Path.GetFileName(fileName)}"); + _log.LogMessage($"Collecting file code model: {Path.GetFileName(fileName)}", LOG_CATEGORY); if ((languageSet?.Type == LanguageType.Unknown) || string.IsNullOrEmpty(fileName)) dteItem = null; @@ -228,7 +229,7 @@ private void GetMembersInternal(object projectItem, List model, if (dteItem == null) throw new ArgumentNullException(nameof(projectItem)); - _log.LogMessage($"Collecting code members for '{dteItem.Name}'"); + _log.LogMessage($"Collecting code members for '{dteItem.Name}'", LOG_CATEGORY); var languageSet = _fileTypeResolver.GetCurrentLanguage(dteItem.ContainingProject, out _); @@ -239,13 +240,13 @@ private void GetMembersInternal(object projectItem, List model, } catch (Exception ex) { - _log.LogMessage($"Error collecting code members for '{dteItem.Name}': {ex.Message}", ex); + _log.LogMessage($"Error collecting code members for '{dteItem.Name}': {ex.Message}", ex, LOG_CATEGORY); throw; } if (elements == null) { - _log.LogMessage($"Code member information is not available for '{dteItem.Name}'"); + _log.LogMessage($"Code member information is not available for '{dteItem.Name}'", LOG_CATEGORY); return; } @@ -260,11 +261,11 @@ private void GetMembersInternal(object projectItem, List model, } catch (Exception ex) { - _log.LogMessage("Error refreshing code model for '{dteItem.Name}'", ex); + _log.LogMessage($"Error refreshing code model for '{dteItem.Name}'", ex, LOG_CATEGORY); return; } - _log.LogMessage($"Collected {model.Count} '{dteItem.Name}' code members"); + _log.LogMessage($"Collected {model.Count} '{dteItem.Name}' code members", LOG_CATEGORY); } /// @@ -301,7 +302,7 @@ private void ProcessCodeElement(ProjectItem item, CodeElement element, List model, ProcessorFl if (_shellProjectService.IsProjectLoadDeferred(project, out _)) return; - _log.LogMessage($"Collecting '{dteProject.Name}' project files"); + _log.LogMessage($"Collecting '{dteProject.Name}' project files", LOG_CATEGORY); // No need to process project's items if we fail to check its code model // The exception is made for solution folder *if* that's requested @@ -85,14 +86,14 @@ private void GetFilesInternal(object project, List model, ProcessorFl { if (flags.HasFlag(ProcessorFlags.IncludeSolutionFolderFiles) && (dteProject.Kind == Constants.vsProjectKindSolutionItems)) { - _log.LogMessage($"Allow '{dteProject.Name}' solution folder processing"); + _log.LogMessage($"Allow '{dteProject.Name}' solution folder processing", LOG_CATEGORY); process = true; } } if (!process && !flags.HasFlag(ProcessorFlags.KnownProjectsOnly) && _shellProjectService.IsProject(project)) { - _log.LogMessage($"Allow '{dteProject.Name}' unknown project type processing"); + _log.LogMessage($"Allow '{dteProject.Name}' unknown project type processing", LOG_CATEGORY); process = true; } @@ -108,7 +109,7 @@ private void GetFilesInternal(object project, List model, ProcessorFl } } - _log.LogMessage($"Collected {model.Count} '{dteProject.Name}' project files"); + _log.LogMessage($"Collected {model.Count} '{dteProject.Name}' project files", LOG_CATEGORY); } /// diff --git a/DPackRx/CodeModel/SolutionProcessor.cs b/DPackRx/CodeModel/SolutionProcessor.cs index 2eceaa2..ccddfdf 100644 --- a/DPackRx/CodeModel/SolutionProcessor.cs +++ b/DPackRx/CodeModel/SolutionProcessor.cs @@ -24,6 +24,8 @@ public class SolutionProcessor : ISolutionProcessor private readonly IShellProjectService _shellProjectService; private readonly IProjectProcessor _projectProcessor; + private const string LOG_CATEGORY = "Solution Processor"; + #endregion public SolutionProcessor(ILog log, ILanguageService languageService, IShellProjectService shellProjectService, @@ -65,14 +67,14 @@ private void GetProjectsInternal(SolutionModel model, ProcessorFlags flags, Code var dte = _shellProjectService.GetDTE() as DTE; - _log.LogMessage("Resolving solution name"); + _log.LogMessage("Resolving solution name", LOG_CATEGORY); var solution = dte.Solution?.FileName; if (!string.IsNullOrEmpty(solution)) solution = Path.GetFileNameWithoutExtension(solution); model.SolutionName = solution; - _log.LogMessage("Collecting solution projects"); + _log.LogMessage("Collecting solution projects", LOG_CATEGORY); var projects = dte.Solution.Projects; for (int index = 1; index <= projects.Count; index++) @@ -114,7 +116,7 @@ private void GetProjectsInternal(SolutionModel model, ProcessorFlags flags, Code } } - _log.LogMessage($"Collected {model.Projects.Count} solution projects"); + _log.LogMessage($"Collected {model.Projects.Count} solution projects", LOG_CATEGORY); } /// @@ -151,12 +153,12 @@ private bool ProcessProject(Project project, ICollection model, Pr catch (NotImplementedException) // This is an acceptable condition - keep on going { process = false; - _log.LogMessage($"Project '{project?.Name}' doesn't implement code model"); + _log.LogMessage($"Project '{project?.Name}' doesn't implement code model", LOG_CATEGORY); } catch (Exception ex) // But this is a legit problem - keep on going anyways { process = false; - _log.LogMessage("Failed to retrieve project code model / language", ex); + _log.LogMessage("Failed to retrieve project code model / language", ex, LOG_CATEGORY); } string projectFullName = string.Empty; @@ -166,7 +168,7 @@ private bool ProcessProject(Project project, ICollection model, Pr if ((string.IsNullOrEmpty(projectPath) || string.IsNullOrEmpty(projectFullName)) && _shellProjectService.IsProject(project)) { process = false; - _log.LogMessage($"Project '{project?.Name}' path is not available"); + _log.LogMessage($"Project '{project?.Name}' path is not available", LOG_CATEGORY); } } diff --git a/DPackRx/DPackRx.csproj b/DPackRx/DPackRx.csproj index 83c6602..9946905 100644 --- a/DPackRx/DPackRx.csproj +++ b/DPackRx/DPackRx.csproj @@ -63,6 +63,7 @@ + diff --git a/DPackRx/Extensions/KnownFeatureExtensions.cs b/DPackRx/Extensions/KnownFeatureExtensions.cs new file mode 100644 index 0000000..a9a847c --- /dev/null +++ b/DPackRx/Extensions/KnownFeatureExtensions.cs @@ -0,0 +1,22 @@ +using System.ComponentModel; + +using DPackRx.Features; + +namespace DPackRx.Extensions +{ + /// + /// extensions. + /// + public static class KnownFeatureExtensions + { + /// + /// Custom: returns feature's description. + /// + public static string GetDescription(this KnownFeature feature) + { + var attribs = typeof(KnownFeature).GetField(feature.ToString())?.GetCustomAttributes(typeof(DescriptionAttribute), false); + + return (attribs == null) || (attribs.Length == 0) ? feature.ToString() : ((DescriptionAttribute)attribs[0]).Description; + } + } +} \ No newline at end of file diff --git a/DPackRx/Extensions/LogExtensions.cs b/DPackRx/Extensions/LogExtensions.cs index 4070e8f..35278a8 100644 --- a/DPackRx/Extensions/LogExtensions.cs +++ b/DPackRx/Extensions/LogExtensions.cs @@ -31,10 +31,7 @@ public static void LogMessage(this ILog log, KnownFeature feature, Exception ex) /// public static void LogMessage(this ILog log, KnownFeature feature, string message, Exception ex) { - var featureMessage = $"{feature}:{Log.INDENT}"; - message = string.IsNullOrEmpty(message) ? featureMessage : featureMessage + message; - - log.LogMessage(message, ex); + log.LogMessage(message, ex, feature.GetDescription()); } } } \ No newline at end of file diff --git a/DPackRx/Features/Bookmarks/BookmarkTag.cs b/DPackRx/Features/Bookmarks/BookmarkTag.cs index a029cfa..386fbf9 100644 --- a/DPackRx/Features/Bookmarks/BookmarkTag.cs +++ b/DPackRx/Features/Bookmarks/BookmarkTag.cs @@ -1,10 +1,13 @@ -using Microsoft.VisualStudio.Text.Editor; +using System.Diagnostics; + +using Microsoft.VisualStudio.Text.Editor; namespace DPackRx.Features.Bookmarks { /// /// Bookmark glyph tag. /// + [DebuggerDisplay("{Number} - {Type}")] public class BookmarkTag : IGlyphTag { public BookmarkTag(int number, BookmarkType type) diff --git a/DPackRx/Features/Bookmarks/BookmarksSimpleTagger.cs b/DPackRx/Features/Bookmarks/BookmarksSimpleTagger.cs index 3f82ed0..f6e923f 100644 --- a/DPackRx/Features/Bookmarks/BookmarksSimpleTagger.cs +++ b/DPackRx/Features/Bookmarks/BookmarksSimpleTagger.cs @@ -24,7 +24,7 @@ public class BookmarksSimpleTagger : SimpleTagger, IBookmarksSimple private ILog _log; private readonly Dictionary> _bookmarkSpans = new Dictionary>(10); - private const string LOG_CATEGORY = "Tagger"; + private const string LOG_CATEGORY = "Bookmark Tagger"; #endregion diff --git a/DPackRx/Features/CodeBrowser/CodeBrowserViewModel.cs b/DPackRx/Features/CodeBrowser/CodeBrowserViewModel.cs index e4280cc..d302a59 100644 --- a/DPackRx/Features/CodeBrowser/CodeBrowserViewModel.cs +++ b/DPackRx/Features/CodeBrowser/CodeBrowserViewModel.cs @@ -73,7 +73,7 @@ public CodeBrowserViewModel(IServiceProvider serviceProvider, ILog log, IMessage /// Optional argument. public override void OnInitialize(object argument) { - _log.LogMessage(this.Feature, "initializing..."); + _log.LogMessage(this.Feature, "Initializing..."); if (!(argument is CodeModelFilterFlags)) throw new ArgumentException("Invalid initialization argument", nameof(argument)); @@ -94,7 +94,7 @@ public override void OnInitialize(object argument) OnSearch(); } - _log.LogMessage(this.Feature, "initialized"); + _log.LogMessage(this.Feature, "Initialized"); } /// diff --git a/DPackRx/Features/Feature.cs b/DPackRx/Features/Feature.cs index f4d28a7..cc82dff 100644 --- a/DPackRx/Features/Feature.cs +++ b/DPackRx/Features/Feature.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Diagnostics; using System.Linq; +using DPackRx.Extensions; using DPackRx.Options; using DPackRx.Services; @@ -29,10 +29,8 @@ protected Feature() if (feature == null) throw new ApplicationException($"Invalid feature {this.GetType()}"); - var attribs = typeof(KnownFeature).GetField(feature.Feature.ToString())?.GetCustomAttributes(typeof(DescriptionAttribute), false); - this.KnownFeature = feature.Feature; - this.Name = (attribs == null) || (attribs.Length == 0) ? feature.ToString() : ((DescriptionAttribute)attribs[0]).Description; + this.Name = this.KnownFeature.GetDescription(); } #region Properties @@ -92,7 +90,7 @@ public virtual void Initialize() /// Command status. public virtual bool IsValidContext(int commandId) { - this.Log.LogMessage($"Feature {this.Name} - unknown command Id {commandId}"); + this.Log.LogMessage($"Feature {this.Name} - unknown command Id {commandId}", this.KnownFeature.GetDescription()); return false; } @@ -103,7 +101,7 @@ public virtual bool IsValidContext(int commandId) /// Execution status. public virtual bool Execute(int commandId) { - this.Log.LogMessage($"Feature {this.Name} - unknown command Id {commandId}"); + this.Log.LogMessage($"Feature {this.Name} - unknown command Id {commandId}", this.KnownFeature.GetDescription()); return false; } diff --git a/DPackRx/Features/FileBrowser/FileBrowserViewModel.cs b/DPackRx/Features/FileBrowser/FileBrowserViewModel.cs index 8509b21..5921917 100644 --- a/DPackRx/Features/FileBrowser/FileBrowserViewModel.cs +++ b/DPackRx/Features/FileBrowser/FileBrowserViewModel.cs @@ -6,7 +6,6 @@ using System.ComponentModel.Design; using System.IO; using System.Linq; -using System.Windows; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; @@ -87,7 +86,7 @@ public FileBrowserViewModel(IServiceProvider serviceProvider, ILog log, IMessage /// Optional argument. public override void OnInitialize(object argument) { - _log.LogMessage(this.Feature, "initializing..."); + _log.LogMessage(this.Feature, "Initializing..."); var model = _solutionProcessor.GetProjects(ProcessorFlags.IncludeFiles | ProcessorFlags.GroupLinkedFiles); var files = model.Files; @@ -113,7 +112,7 @@ public override void OnInitialize(object argument) OnSearch(); } - _log.LogMessage(this.Feature, "initialized"); + _log.LogMessage(this.Feature, "Initialized"); } /// diff --git a/DPackRx/Features/Miscellaneous/MiscellaneousFeature.cs b/DPackRx/Features/Miscellaneous/MiscellaneousFeature.cs index d7c8680..83ef738 100644 --- a/DPackRx/Features/Miscellaneous/MiscellaneousFeature.cs +++ b/DPackRx/Features/Miscellaneous/MiscellaneousFeature.cs @@ -4,6 +4,7 @@ using System.IO; using System.Text; +using DPackRx.Extensions; using DPackRx.Options; using DPackRx.Package; using DPackRx.Services; @@ -142,7 +143,7 @@ private bool CollapseAllProjects() /// private bool CopyReferences(bool copyAll) { - this.Log.LogMessage($"Copy references - check selection - {copyAll}"); + this.Log.LogMessage(this.KnownFeature, $"Copy references - check selection - {copyAll}"); var references = _shellReferenceService.GetProjectReferences(!copyAll); var referenceCount = 0; @@ -172,7 +173,7 @@ private bool CopyReferences(bool copyAll) _shellStatusBarService.SetStatusBarText($"Copied {referenceCount} references"); - this.Log.LogMessage($"Copy references - copied selection - {copyAll} - {referenceCount}"); + this.Log.LogMessage(this.KnownFeature, $"Copy references - copied selection - {copyAll} - {referenceCount}"); return true; } @@ -181,7 +182,7 @@ private bool CopyReferences(bool copyAll) /// private bool PasteReferences() { - this.Log.LogMessage("Paste references - check selection"); + this.Log.LogMessage(this.KnownFeature, "Paste references - check selection"); if (!_utilsService.GetClipboardData(out string refs) || string.IsNullOrEmpty(refs)) return false; @@ -274,7 +275,7 @@ private bool PasteReferences() if (invalidFileName) { - this.Log.LogMessage($"Paste references - ignored invalid file name - {fileName}"); + this.Log.LogMessage(this.KnownFeature, $"Paste references - ignored invalid file name - {fileName}"); continue; } @@ -291,7 +292,7 @@ private bool PasteReferences() _shellStatusBarService.SetStatusBarText($"Pasted {referenceCount} reference(s)"); - this.Log.LogMessage($"Paste references - pasted - {referenceCount}"); + this.Log.LogMessage(this.KnownFeature, $"Paste references - pasted - {referenceCount}"); return true; } @@ -325,7 +326,7 @@ private bool OpenCommandPrompt() } if (string.IsNullOrEmpty(commandToolsPath) || !File.Exists(commandToolsPath)) { - this.Log.LogMessage($"Command Prompt - failed to find command tools: {commandToolsPath}"); + this.Log.LogMessage(this.KnownFeature, $"Command Prompt - failed to find command tools: {commandToolsPath}"); return false; } @@ -334,7 +335,7 @@ private bool OpenCommandPrompt() startInfo.Verb = "runas"; if (Process.Start(startInfo) != null) - this.Log.LogMessage($"Command Prompt - failed to start: {startInfo.Arguments}"); + this.Log.LogMessage(this.KnownFeature, $"Command Prompt - failed to start: {startInfo.Arguments}"); return true; } diff --git a/DPackRx/Features/SupportOptions/SupportOptionsFeature.cs b/DPackRx/Features/SupportOptions/SupportOptionsFeature.cs index 248ad42..08350cc 100644 --- a/DPackRx/Features/SupportOptions/SupportOptionsFeature.cs +++ b/DPackRx/Features/SupportOptions/SupportOptionsFeature.cs @@ -24,7 +24,7 @@ public class SupportOptionsFeature : Feature, IDisposable private readonly IMessageService _messageService; private SupportOptionsFirstTimeUse _firstTimeUse; - private const string EMAIL = "mailto:{0}?subject={1} v{2} for {3}" + + private const string EMAIL = "mailto:{0}?subject={1} v{2} for {3}" + "&body=Please include extension log file when submitting a problem report."; #endregion @@ -67,7 +67,7 @@ public override void Initialize() { base.Initialize(); - _firstTimeUse = new SupportOptionsFirstTimeUse(this.Log, this.OptionsService, _packageService, _shellHelperService, _shellInfoBarService, _messageService); + _firstTimeUse = new SupportOptionsFirstTimeUse(this.OptionsService, _packageService, _shellHelperService, _shellInfoBarService, _messageService); _shellEventsService.SubscribeSolutionEvents(_firstTimeUse); } diff --git a/DPackRx/Features/SupportOptions/SupportOptionsFirstTimeUse.cs b/DPackRx/Features/SupportOptions/SupportOptionsFirstTimeUse.cs index 84c349b..6c61154 100644 --- a/DPackRx/Features/SupportOptions/SupportOptionsFirstTimeUse.cs +++ b/DPackRx/Features/SupportOptions/SupportOptionsFirstTimeUse.cs @@ -10,7 +10,6 @@ public class SupportOptionsFirstTimeUse : ISolutionEvents { #region Fields - private readonly ILog _log; private readonly IOptionsService _optionsService; private readonly IPackageService _packageService; private readonly IShellHelperService _shellHelperService; @@ -25,13 +24,10 @@ public class SupportOptionsFirstTimeUse : ISolutionEvents #endregion - public SupportOptionsFirstTimeUse(ILog log, IOptionsService optionsService, + public SupportOptionsFirstTimeUse(IOptionsService optionsService, IPackageService packageService, IShellHelperService shellHelperService, IShellInfoBarService shellInfoBarService, IMessageService messageService) { - if (log == null) - throw new ArgumentNullException(nameof(log)); - if (optionsService == null) throw new ArgumentNullException(nameof(optionsService)); @@ -41,7 +37,6 @@ public SupportOptionsFirstTimeUse(ILog log, IOptionsService optionsService, if (messageService == null) throw new ArgumentNullException(nameof(messageService)); - _log = log; _optionsService = optionsService; _packageService = packageService; _shellHelperService = shellHelperService; diff --git a/DPackRx/Helpers/KeyboardHelper.cs b/DPackRx/Helpers/KeyboardHelper.cs index d7ad58c..c528f61 100644 --- a/DPackRx/Helpers/KeyboardHelper.cs +++ b/DPackRx/Helpers/KeyboardHelper.cs @@ -20,8 +20,7 @@ public static class KeyboardHelper private const int VKEY_SHIFT_MASK = 0x0100; private const int VKEY_CHAR_MASK = 0x00FF; - private const int INPUT_MOUSE = 0; - private const int INPUT_KEYBOARD = 1; + private const int INPUT_KEYBOARD = 1; // INPUT_MOUSE = 0; private const int KEY_EVENT_EXTENDED_KEY = 0x0001; private const int KEY_EVENT_KEY_UP = 0x0002; @@ -140,7 +139,7 @@ public static void Type(string text) } } - Thread.Sleep(250); + Thread.Sleep(200); } /// diff --git a/DPackRx/Language/LanguageRegistrationService.cs b/DPackRx/Language/LanguageRegistrationService.cs index ec4a817..46655a0 100644 --- a/DPackRx/Language/LanguageRegistrationService.cs +++ b/DPackRx/Language/LanguageRegistrationService.cs @@ -32,6 +32,8 @@ public class LanguageRegistrationService : ILanguageRegistrationService private const string PARENTLESS_FULL_NAME = "ParentlessFullName"; private const string SURROUND_WITH_NAME = "SurroundWith"; + private const string LOG_CATEGORY = "Language Registry"; + #endregion public LanguageRegistrationService(ILog log, IPackageService packageService) @@ -111,7 +113,7 @@ public ICollection GetLanguages() } if (string.IsNullOrEmpty(friendlyName)) { - _log.LogMessage($"Skipped language {id} definition w/o a friendly name"); + _log.LogMessage($"Skipped language {id} definition w/o a friendly name", LOG_CATEGORY); continue; } var webNames = !string.IsNullOrEmpty(webName) ? webName.Split(',') : new string[0]; diff --git a/DPackRx/Language/LanguageService.cs b/DPackRx/Language/LanguageService.cs index 9b94aec..e49c398 100644 --- a/DPackRx/Language/LanguageService.cs +++ b/DPackRx/Language/LanguageService.cs @@ -25,6 +25,8 @@ public class LanguageService : ILanguageService private readonly Dictionary _languageFromDenormalizedExtension = new Dictionary(StringComparer.OrdinalIgnoreCase); + private const string LOG_CATEGORY = "Language"; + #endregion public LanguageService(ILog log, ILanguageRegistrationService languageRegistrationService) @@ -250,7 +252,7 @@ private void CacheLanguages() if (_languageFromId.Count == 0) throw new ApplicationException("No language definitions were found"); - _log.LogMessage($"Cached {_languageFromId.Count} language definitions"); + _log.LogMessage($"Cached {_languageFromId.Count} language definitions", LOG_CATEGORY); } // lock } diff --git a/DPackRx/Language/LanguageSettings.cs b/DPackRx/Language/LanguageSettings.cs index b6fe079..67b86bc 100644 --- a/DPackRx/Language/LanguageSettings.cs +++ b/DPackRx/Language/LanguageSettings.cs @@ -24,28 +24,28 @@ public LanguageSettings(string language, string friendlyName, string xmlDoc = nu switch (this.Language) { - case LanguageConsts.vsCMLanguageCSharp: + case LanguageConsts.VS_CM_LANGUAGE_CSHARP: this.Type = LanguageType.CSharp; this.SupportsCompileBuildAction = true; this.SupportsGenerics = true; break; - case LanguageConsts.vsCMLanguageVB: + case LanguageConsts.VS_CM_LANGUAGE_VB: this.Type = LanguageType.VB; this.SupportsCompileBuildAction = true; this.SupportsGenerics = true; break; - case LanguageConsts.vsCMLanguageVC: + case LanguageConsts.VS_CM_LANGUAGE_VC: this.Type = LanguageType.CPP; break; - case LanguageConsts.vsLanguageJavaScript: + case LanguageConsts.VS_LANGUAGE_JAVA_SCRIPT: this.Type = LanguageType.JavaScript; this.SupportsStatistics = false; break; - case LanguageConsts.vsLanguageXml: + case LanguageConsts.VS_LANGUAGE_XML: this.Type = LanguageType.Xml; this.SupportsStatistics = false; break; - case LanguageConsts.vsLanguageSolutionItems: + case LanguageConsts.VS_LANGUAGE_SOLUTION_ITEMS: this.Type = LanguageType.SolutionItems; break; default: diff --git a/DPackRx/Options/OptionsFileBrowser.cs b/DPackRx/Options/OptionsFileBrowser.cs index 03c7e1e..135a8d5 100644 --- a/DPackRx/Options/OptionsFileBrowser.cs +++ b/DPackRx/Options/OptionsFileBrowser.cs @@ -10,7 +10,7 @@ namespace DPackRx.Options /// /// File Browser Tools|Options page. /// - [Guid(Package.GUIDs.OptionsFileBrowser)] + [Guid(Package.GUIDs.OPTIONS_FILE_BROWSER)] [ComVisible(true)] [ClassInterface(ClassInterfaceType.AutoDual)] [ToolboxItem(false)] diff --git a/DPackRx/Options/OptionsGeneral.cs b/DPackRx/Options/OptionsGeneral.cs index 9d51ecc..8db21fa 100644 --- a/DPackRx/Options/OptionsGeneral.cs +++ b/DPackRx/Options/OptionsGeneral.cs @@ -17,7 +17,7 @@ namespace DPackRx.Options /// /// General Tools|Options page. /// - [Guid(GUIDs.OptionsGeneral)] + [Guid(GUIDs.OPTIONS_GENERAL)] [ComVisible(true)] [ClassInterface(ClassInterfaceType.AutoDual)] [ToolboxItem(false)] @@ -169,7 +169,7 @@ private void OnAssignShortcuts(object parameter) private void OnLogging(object obj) { - this.OptionsService.SetBoolOption(this.Feature, "Logging", obj != null ? Convert.ToBoolean(obj) : false); + this.OptionsService.SetBoolOption(this.Feature, "Logging", obj != null && Convert.ToBoolean(obj)); } private void OnLogFolder(object obj) diff --git a/DPackRx/Options/OptionsPersistenceService.cs b/DPackRx/Options/OptionsPersistenceService.cs index edb6e0a..bf5bbc8 100644 --- a/DPackRx/Options/OptionsPersistenceService.cs +++ b/DPackRx/Options/OptionsPersistenceService.cs @@ -20,6 +20,8 @@ public class OptionsPersistenceService : IOptionsPersistenceService private readonly ILog _log; private readonly IPackageService _packageService; + private const string LOG_CATEGORY = "Options Persister"; + #endregion public OptionsPersistenceService(ILog log, IPackageService packageService) @@ -65,7 +67,7 @@ public IDictionary LoadOptions(KnownFeature feature) } else { - _log.LogMessage($"No {feature} options to load"); + _log.LogMessage($"No {feature} options to load", LOG_CATEGORY); } return options; @@ -92,7 +94,7 @@ public void SaveOptions(KnownFeature feature, IDictionary option } if (featureKey == null) { - _log.LogMessage($"Failed to saved {feature} options"); + _log.LogMessage($"Failed to saved {feature} options", LOG_CATEGORY); return; } diff --git a/DPackRx/Options/OptionsService.cs b/DPackRx/Options/OptionsService.cs index d100c2d..9558831 100644 --- a/DPackRx/Options/OptionsService.cs +++ b/DPackRx/Options/OptionsService.cs @@ -18,6 +18,8 @@ public class OptionsService : IOptionsService, IDisposable private readonly ConcurrentDictionary> _options = new ConcurrentDictionary>(); private readonly ConcurrentDictionary> _deletedOptions = new ConcurrentDictionary>(); + private const string LOG_CATEGORY = "Options"; + #endregion public OptionsService(ILog log, IOptionsPersistenceService optionsPersistenceService) @@ -82,7 +84,7 @@ public bool OptionExists(KnownFeature feature, string name) if (options == null) return false; - return string.IsNullOrEmpty(name) ? false : options.ContainsKey(name); + return !string.IsNullOrEmpty(name) && options.ContainsKey(name); } /// @@ -299,6 +301,8 @@ public void ResetAll() RaiseChanged(feature); RaiseReset(feature); } + + _log.LogMessage("Reset all options", LOG_CATEGORY); } #endregion @@ -355,6 +359,7 @@ private bool Save(KnownFeature feature) } _optionsPersistenceService.SaveOptions(feature, _options[feature]); + _log.LogMessage("Options saved", LOG_CATEGORY); return true; } diff --git a/DPackRx/Package.cs b/DPackRx/Package.cs index 69c01b1..b6201ec 100644 --- a/DPackRx/Package.cs +++ b/DPackRx/Package.cs @@ -33,7 +33,7 @@ namespace DPackRx #region Package Attributes [PackageRegistration(UseManagedResourcesOnly = true, RegisterUsing = RegistrationMethod.CodeBase, AllowsBackgroundLoading = true)] [InstalledProductRegistrationEx("#101", "#102", 400)] // Help|About information - [Guid(GUIDs.ProductID)] + [Guid(GUIDs.PRODUCT_ID)] [ProvideMenuResource("Menus.ctmenu", 1)] // Auto-load context [ProvideAutoLoad(UIContextGuids.NoSolution, PackageAutoLoadFlags.BackgroundLoad)] @@ -56,10 +56,10 @@ namespace DPackRx Comments = new[] { "//", "/*" }, XmlDoc = "/summary,", XmlDocSurround = true, CheckDuplicateNames = true, IgnoreCodeType = true, ParentlessFullName = true, SurroundWith = true)] [ProvideLanguage( - "#101", LanguageConsts.vsLanguageJavaScript, "JavaScript", new[] { "js", "aspx", "ascx", "html", "htm", "asp", "master", "cshtml", "vbhtml" }, + "#101", LanguageConsts.VS_LANGUAGE_JAVA_SCRIPT, "JavaScript", new[] { "js", "aspx", "ascx", "html", "htm", "asp", "master", "cshtml", "vbhtml" }, Comments = new[] { "//", "/*" }, SmartFormat = false)] - [ProvideLanguage("#101", LanguageConsts.vsLanguageXml, "Xml", new[] { "xml", "config", "targets", "vsct" }, Comments = new[] { "!--" })] - [ProvideLanguage("#101", LanguageConsts.vsLanguageSolutionItems, "Solution Items", new string[0])] + [ProvideLanguage("#101", LanguageConsts.VS_LANGUAGE_XML, "Xml", new[] { "xml", "config", "targets", "vsct" }, Comments = new[] { "!--" })] + [ProvideLanguage("#101", LanguageConsts.VS_LANGUAGE_SOLUTION_ITEMS, "Solution Items", new string[0])] #endregion public sealed class DPackRx : AsyncPackage { @@ -67,6 +67,8 @@ public sealed class DPackRx : AsyncPackage private IServiceContainer _container; + private const string LOG_CATEGORY = "Package"; + [Import] private ISharedServiceProvider _sharedServiceProvider = null; @@ -127,7 +129,7 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke catch (Exception ex) { var log = _container.TryGetInstance(); - log?.LogMessage($"{nameof(InitializeAsync)} error", ex); + log?.LogMessage($"{nameof(InitializeAsync)} error", ex, LOG_CATEGORY); } } @@ -151,7 +153,7 @@ private void PreloadReferences() finally { var log = _container.TryGetInstance(); - log?.LogMessage("Preloaded references"); + log?.LogMessage("Preloaded select references", LOG_CATEGORY); } } diff --git a/DPackRx/Package/FeatureCommand.cs b/DPackRx/Package/FeatureCommand.cs index d13c503..89f77b7 100644 --- a/DPackRx/Package/FeatureCommand.cs +++ b/DPackRx/Package/FeatureCommand.cs @@ -21,6 +21,8 @@ public class FeatureCommand : IFeatureCommand private readonly IUtilsService _utilsService; private IFeature _feature; + private const string LOG_CATEGORY = "Command"; + #endregion public FeatureCommand(ILog log, IMenuCommandService menuCommandService, IMessageService messageService, IUtilsService utilsService) @@ -94,7 +96,7 @@ public bool IsValidContext() } catch (Exception ex) { - _log.LogMessage(ex); + _log.LogMessage(ex, LOG_CATEGORY); return false; } } @@ -165,7 +167,7 @@ private void Execute(object sender, EventArgs e) } catch (Exception ex) { - _log.LogMessage(ex); + _log.LogMessage(ex, LOG_CATEGORY); } } diff --git a/DPackRx/Package/GUIDs.cs b/DPackRx/Package/GUIDs.cs index 5c1ce09..2da4c36 100644 --- a/DPackRx/Package/GUIDs.cs +++ b/DPackRx/Package/GUIDs.cs @@ -10,16 +10,16 @@ public static class GUIDs /// /// Must match VSIX manifest Product ID. /// - public const string ProductID = "EE57E48A-8422-4CEC-B415-3E3BA31F1199"; + public const string PRODUCT_ID = "EE57E48A-8422-4CEC-B415-3E3BA31F1199"; public static readonly Guid CommandSet = new Guid("{BD0B0377-DC68-4C27-A9A3-D240F33367D4}"); - public const string GUID_XamlEditorFactory = "4C87B692-1202-46AA-B64C-EF01FAEC53DA"; - public const string GUID_XamlLanguageService = "C9164055-039B-4669-832D-F257BD5554D4"; - public const string GUID_NewXamlLanguageService = "CD53C9A1-6BC2-412B-BE36-CC715ED8DD41"; - public const string GUID_XamlDesigner = "2E06F766-183C-46F9-B8AC-BC4FB78480A7"; + public const string GUID_XAML_EDITOR_FACTORY = "4C87B692-1202-46AA-B64C-EF01FAEC53DA"; + public const string GUID_XAML_LANGUAGE_SERVICE = "C9164055-039B-4669-832D-F257BD5554D4"; + public const string GUID_NEW_XAML_LANGUAGE_SERVICE = "CD53C9A1-6BC2-412B-BE36-CC715ED8DD41"; + public const string GUID_XAML_DESIGNER = "2E06F766-183C-46F9-B8AC-BC4FB78480A7"; - public const string OptionsGeneral = "F26A055B-47EC-4642-839F-3240A2594742"; - public const string OptionsFileBrowser = "B998A0CD-69D6-4980-9240-5EC65F3B6E02"; + public const string OPTIONS_GENERAL = "F26A055B-47EC-4642-839F-3240A2594742"; + public const string OPTIONS_FILE_BROWSER = "B998A0CD-69D6-4980-9240-5EC65F3B6E02"; } } \ No newline at end of file diff --git a/DPackRx/Package/LanguageConsts.cs b/DPackRx/Package/LanguageConsts.cs index 29ca715..3e43cca 100644 --- a/DPackRx/Package/LanguageConsts.cs +++ b/DPackRx/Package/LanguageConsts.cs @@ -7,32 +7,32 @@ public static class LanguageConsts { // EnvDTE.CodeModelLanguageConstants.vsCMLanguageCSharp - public const string vsCMLanguageCSharp = "{B5E9BD34-6D3E-4B5D-925E-8A43B79820B4}"; + public const string VS_CM_LANGUAGE_CSHARP = "{B5E9BD34-6D3E-4B5D-925E-8A43B79820B4}"; // EnvDTE.CodeModelLanguageConstants.vsCMLanguageVB - public const string vsCMLanguageVB = "{B5E9BD33-6D3E-4B5D-925E-8A43B79820B4}"; + public const string VS_CM_LANGUAGE_VB = "{B5E9BD33-6D3E-4B5D-925E-8A43B79820B4}"; // EnvDTE.CodeModelLanguageConstants.vsCMLanguageVC - public const string vsCMLanguageVC = "{B5E9BD32-6D3E-4B5D-925E-8A43B79820B4}"; + public const string VS_CM_LANGUAGE_VC = "{B5E9BD32-6D3E-4B5D-925E-8A43B79820B4}"; /// /// Unknown language friendly name. /// - public const string vsLanguageUnknown = "Unknown"; + public const string VS_LANGUAGE_UNKNOWN = "Unknown"; /// /// Fake J/S language Guid. /// - public const string vsLanguageJavaScript = "{FFFFFFFF-0001-FFFF-FFFF-FFFFFFFFFFFF}"; + public const string VS_LANGUAGE_JAVA_SCRIPT = "{FFFFFFFF-0001-FFFF-FFFF-FFFFFFFFFFFF}"; /// /// Fake Xml language Guid. /// - public const string vsLanguageXml = "{FFFFFFFF-0002-FFFF-FFFF-FFFFFFFFFFFF}"; + public const string VS_LANGUAGE_XML = "{FFFFFFFF-0002-FFFF-FFFF-FFFFFFFFFFFF}"; /// /// Fake solution items project language Guid. /// - public const string vsLanguageSolutionItems = "{FFFFFFFF-0000-FFFF-FFFF-FFFFFFFFFFFF}"; + public const string VS_LANGUAGE_SOLUTION_ITEMS = "{FFFFFFFF-0000-FFFF-FFFF-FFFFFFFFFFFF}"; } } \ No newline at end of file diff --git a/DPackRx/Package/Registration/InstalledProductRegistrationExAttribute.cs b/DPackRx/Package/Registration/InstalledProductRegistrationExAttribute.cs index 92b6d14..2f4a023 100644 --- a/DPackRx/Package/Registration/InstalledProductRegistrationExAttribute.cs +++ b/DPackRx/Package/Registration/InstalledProductRegistrationExAttribute.cs @@ -53,7 +53,7 @@ private InstalledProductRegistrationAttribute GetAttribute() var productId = version.Revision == 0 ? version.ToString(3) : version.ToString(4); #if BETA - productId = $"{productId} - Beta expires on {Beta.ExpirationDate.ToString("d")}"; + productId = $"{productId} - Beta expires on {Beta.ExpirationDate:d}"; #endif var attrib = new InstalledProductRegistrationAttribute(_productName, _productDetails, productId) diff --git a/DPackRx/Services/FeatureFactory.cs b/DPackRx/Services/FeatureFactory.cs index 2e2c11f..4ddfc40 100644 --- a/DPackRx/Services/FeatureFactory.cs +++ b/DPackRx/Services/FeatureFactory.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; +using DPackRx.Extensions; using DPackRx.Features; namespace DPackRx.Services @@ -21,6 +21,8 @@ public sealed class FeatureFactory : IFeatureFactory, IDisposable private readonly ConcurrentDictionary _features = new ConcurrentDictionary(); private bool _initialized; + private const string LOG_CATEGORY = "Feature Factory"; + #endregion public FeatureFactory(IServiceProvider serviceProvider, ILog log, IMessageService messageService) @@ -35,7 +37,7 @@ public FeatureFactory(IServiceProvider serviceProvider, ILog log, IMessageServic /// /// Tracks whether Dispose has been called. /// - private bool disposed = false; + private bool _disposed = false; public void Dispose() { @@ -54,7 +56,7 @@ public void Dispose() private void Dispose(bool disposing) { // Check to see if Dispose() has already been called - if (!disposed) + if (!_disposed) { // Dispose all managed and unmanaged resources // Called upon IDE shutdown @@ -64,7 +66,7 @@ private void Dispose(bool disposing) } } - disposed = true; + _disposed = true; } #endregion @@ -78,9 +80,7 @@ private void Dispose(bool disposing) /// Feature name. public string GetFeatureName(KnownFeature feature) { - var attribs = typeof(KnownFeature).GetField(feature.ToString())?.GetCustomAttributes(typeof(DescriptionAttribute), false); - var name = (attribs == null) || (attribs.Length == 0) ? feature.ToString() : ((DescriptionAttribute)attribs[0]).Description; - return name; + return feature.GetDescription(); } /// @@ -132,7 +132,7 @@ private void Initialize() var feature = ((KnownFeatureAttribute)attribs[0]).Feature; if (!_features.ContainsKey(feature)) { - _log.LogMessage($"Loading {feature} feature"); + _log.LogMessage($"Loading {feature} feature", LOG_CATEGORY); var featureInstance = (IFeature)_serviceProvider.GetService(type); try { @@ -143,12 +143,12 @@ private void Initialize() } catch (Exception ex) { - _log.LogMessage($"Failed to initialize feature {feature}", ex); + _log.LogMessage($"Failed to initialize feature {feature}", ex, LOG_CATEGORY); errors.Add(GetFeatureName(feature)); } _features.TryAdd(feature, featureInstance); - _log.LogMessage($"Loaded {feature} feature"); + _log.LogMessage($"Loaded {feature} feature", LOG_CATEGORY); } } } diff --git a/DPackRx/Services/Log.cs b/DPackRx/Services/Log.cs index aa94584..616c1f2 100644 --- a/DPackRx/Services/Log.cs +++ b/DPackRx/Services/Log.cs @@ -19,13 +19,15 @@ public class Log : ILog private readonly IPackageService _packageService; private FileStream _fileStream; private StreamWriter _file; - private object _threadSafeLock = new object(); + private readonly object _threadSafeLock = new object(); private bool _enabled; + private const string LOG_CATEGORY = "Initialization"; private const int MAX_FILE_NAME_TRY = 20; private const long MAX_FILE_SIZE = 1024 * 1024 * 10; // in Mb + private const int CATEGORY_LENGTH = 18; protected internal const string INDENT = " "; - protected internal const string CATEGORY_INDENT = ": "; + protected internal const string CATEGORY_INDENT = " "; #endregion @@ -39,7 +41,7 @@ public Log(IPackageService packageService) /// /// Tracks whether Dispose has been called. /// - private bool disposed = false; + private bool _disposed = false; /// /// Called upon IDE shutdown. @@ -61,7 +63,7 @@ public void Dispose() private void Dispose(bool disposing) { // Check to see if Dispose() has already been called - if (!disposed) + if (!_disposed) { // Dispose all managed and unmanaged resources if (disposing) @@ -74,7 +76,7 @@ private void Dispose(bool disposing) } } - disposed = true; + _disposed = true; } ~Log() @@ -213,14 +215,14 @@ private void Open() _file.AutoFlush = true; InternalWriteMessage("*** Start logging ***"); - InternalWriteMessage($"Date: {DateTime.Now.ToString("M/d/yy")}"); - InternalWriteMessage($"Version: {Assembly.GetExecutingAssembly().GetName().Version.ToString()}"); + InternalWriteMessage($"Date: {DateTime.Now:M/d/yy}", null, LOG_CATEGORY); + InternalWriteMessage($"Version: {Assembly.GetExecutingAssembly().GetName().Version}", null, LOG_CATEGORY); #if BETA - InternalWriteMessage($"Beta expires on: {Beta.ExpirationDate.ToShortDateString()}"); + InternalWriteMessage($"Beta expires on: {Beta.ExpirationDate.ToShortDateString()}", null, LOG_CATEGORY); #endif - InternalWriteMessage($"Visual Studio: {_packageService.VSVersion}"); - InternalWriteMessage($"OS: {Environment.OSVersion.Version}"); - InternalWriteMessage($"Process Id: {Process.GetCurrentProcess().Id}"); + InternalWriteMessage($"Visual Studio: {_packageService.VSVersion}", null, LOG_CATEGORY); + InternalWriteMessage($"OS: {Environment.OSVersion.Version}", null, LOG_CATEGORY); + InternalWriteMessage($"Process Id: {Process.GetCurrentProcess().Id}", null, LOG_CATEGORY); } } @@ -298,13 +300,13 @@ private void InternalWriteMessage(string message, Exception exception = null, st { if (timeStamp) { - _file.Write(DateTime.Now.ToString("HH:mm:ss.fff")); + _file.Write($"{DateTime.Now:HH:mm:ss.fff}"); _file.Write(INDENT); } if (!string.IsNullOrEmpty(category)) { - _file.Write(category); + _file.Write($"{category,-CATEGORY_LENGTH}"); _file.Write(CATEGORY_INDENT); } diff --git a/DPackRx/Services/ShellEventsService.cs b/DPackRx/Services/ShellEventsService.cs index 2350a0c..4d6b362 100644 --- a/DPackRx/Services/ShellEventsService.cs +++ b/DPackRx/Services/ShellEventsService.cs @@ -22,7 +22,6 @@ public class ShellEventsService : IShellEventsService, IDisposable, #region Fields private readonly IServiceProvider _serviceProvider; - private readonly ILog _log; private readonly IPackageService _packageService; private readonly IShellProjectService _shellProjectService; private readonly IShellStatusBarService _shellStatusBarService; @@ -38,11 +37,10 @@ public class ShellEventsService : IShellEventsService, IDisposable, #endregion - public ShellEventsService(IServiceProvider serviceProvider, ILog log, IPackageService packageService, + public ShellEventsService(IServiceProvider serviceProvider, IPackageService packageService, IShellProjectService shellProjectService, IShellStatusBarService shellStatusBarService) { _serviceProvider = serviceProvider; - _log = log; _packageService = packageService; _shellProjectService = shellProjectService; _shellStatusBarService = shellStatusBarService; @@ -294,7 +292,7 @@ public int OnAfterAsynchOpenProject(IVsHierarchy pHierarchy, int fAdded) return VSConstants.S_OK; } - public int OnQueryChangeProjectParent(IVsHierarchy pHierarchy, IVsHierarchy pNewParentHier, + public int OnQueryChangeProjectParent(IVsHierarchy pHierarchy, IVsHierarchy pNewParentHier, ref int pfCancel) { pfCancel = Convert.ToInt32(false); @@ -354,13 +352,13 @@ public int OnAfterLoadProjectBatch(bool fIsBackgroundIdleBatch) #region IVsRunningDocTableEvents3 - documents selection changes - public int OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, + public int OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining) { return VSConstants.S_OK; } - public int OnBeforeLastDocumentUnlock(uint docCookie, uint dwRDTLockType, + public int OnBeforeLastDocumentUnlock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining) { return VSConstants.S_OK; @@ -408,8 +406,8 @@ public int OnAfterAttributeChange(uint docCookie, uint grfAttribs) return VSConstants.S_OK; } - public int OnAfterAttributeChangeEx(uint docCookie, uint grfAttribs, - IVsHierarchy pHierOld, uint itemidOld, string pszMkDocumentOld, + public int OnAfterAttributeChangeEx(uint docCookie, uint grfAttribs, + IVsHierarchy pHierOld, uint itemidOld, string pszMkDocumentOld, IVsHierarchy pHierNew, uint itemidNew, string pszMkDocumentNew) { return VSConstants.S_OK; @@ -432,7 +430,7 @@ public int OnAfterDocumentWindowHide(uint docCookie, IVsWindowFrame pFrame) #region Files public int OnQueryAddFiles(IVsProject pProject, int cFiles, string[] rgpszMkDocuments, - VSQUERYADDFILEFLAGS[] rgFlags, VSQUERYADDFILERESULTS[] pSummaryResult, + VSQUERYADDFILEFLAGS[] rgFlags, VSQUERYADDFILERESULTS[] pSummaryResult, VSQUERYADDFILERESULTS[] rgResults) { return VSConstants.S_OK; @@ -655,7 +653,7 @@ private void DocumentEvents_DocumentClosing(Document document) ThreadHelper.ThrowIfNotOnUIThread(); // Work around for file's code model changed event not being raised for web project - // when file is closed w/o saving changes. Thus, FileChanged change type needs to be + // when file is closed w/o saving changes. Thus, FileChanged change type needs to be // processed for web projects only if ((document != null) && IsSolutionOpen()) { @@ -680,8 +678,8 @@ private void DocumentEvents_DocumentSaved(Document document) { ThreadHelper.ThrowIfNotOnUIThread(); - // Work around for file's code model changed event not being raised when - // code member line # is changed. Thus, FileChanged change type needs to be + // Work around for file's code model changed event not being raised when + // code member line # is changed. Thus, FileChanged change type needs to be // processed to force the code model refresh if ((document != null) && IsSolutionOpen()) { diff --git a/DPackRx/Services/ShellInfoBarService.cs b/DPackRx/Services/ShellInfoBarService.cs index 6b170d4..c8c3294 100644 --- a/DPackRx/Services/ShellInfoBarService.cs +++ b/DPackRx/Services/ShellInfoBarService.cs @@ -24,6 +24,7 @@ public class ShellInfoBarService : IShellInfoBarService, IVsInfoBarUIEvents private uint _cookie; private Action _action; + private const string LOG_CATEGORY = "Shell Info"; private const string CONTEXT_ACTION = "action"; private const string CONTEXT_OPTIONS = "options"; @@ -62,7 +63,7 @@ public void ShowInfoBar(string message, string actionText, Action action, bool s if (_cookie > 0) { - _log.LogMessage($"InfoBar is already in use: {_cookie}"); + _log.LogMessage($"InfoBar is already in use: {_cookie}", LOG_CATEGORY); return; } @@ -72,7 +73,7 @@ public void ShowInfoBar(string message, string actionText, Action action, bool s var host = obj as IVsInfoBarHost; if (host == null) { - _log.LogMessage("InfoBar host is not available"); + _log.LogMessage("InfoBar host is not available", LOG_CATEGORY); return; } @@ -93,7 +94,7 @@ public void ShowInfoBar(string message, string actionText, Action action, bool s host.AddInfoBar(element); _action = action; - _log.LogMessage($"InfoBar is set: {_cookie}"); + _log.LogMessage($"InfoBar is set: {_cookie}", LOG_CATEGORY); } #endregion @@ -127,7 +128,7 @@ public void OnActionItemClicked(IVsInfoBarUIElement infoBarUIElement, IVsInfoBar } else { - _log.LogMessage($"InfoBar invalid context: {context}"); + _log.LogMessage($"InfoBar invalid context: {context}", LOG_CATEGORY); } } catch (Exception ex) From d7b6b0cb843aa9235dd15429393d5ec428ff558a Mon Sep 17 00:00:00 2001 From: Sergey M Date: Mon, 10 Aug 2020 08:32:09 -0400 Subject: [PATCH 2/4] Refactored keyboard shortcuts assignment to work around international VS versions compatibility. --- DPackRx/Options/OptionsGeneralControl.xaml | 10 +- DPackRx/Package/CommandBindings.cs | 30 ++-- DPackRx/Package/CommandIDs.cs | 110 ++++++------- DPackRx/Services/ShellService.cs | 174 +++++++++++++-------- 4 files changed, 184 insertions(+), 140 deletions(-) diff --git a/DPackRx/Options/OptionsGeneralControl.xaml b/DPackRx/Options/OptionsGeneralControl.xaml index 067f9ef..07d57f2 100644 --- a/DPackRx/Options/OptionsGeneralControl.xaml +++ b/DPackRx/Options/OptionsGeneralControl.xaml @@ -1,10 +1,10 @@  @@ -19,7 +19,7 @@ - public static class CommandIDs { - [CommandName("Tools.AllMembers", "Global::Alt+G")] public const int CODE_BROWSER = 100; - [CommandName("Tools.ClassesInterfacesOnly", "Global::Alt+C")] public const int CODE_BROWSER_CI = 101; - [CommandName("Tools.MethodsOnly", "Global::Alt+M")] public const int CODE_BROWSER_M = 102; - [CommandName("Tools.PropertiesOnly", "Global::Shift+Alt+P")] public const int CODE_BROWSER_P = 103; + [CommandName("Tools.AllMembers", "Alt+G")] public const int CODE_BROWSER = 100; + [CommandName("Tools.ClassesInterfacesOnly", "Alt+C")] public const int CODE_BROWSER_CI = 101; + [CommandName("Tools.MethodsOnly", "Alt+M")] public const int CODE_BROWSER_M = 102; + [CommandName("Tools.PropertiesOnly", "Shift+Alt+P")] public const int CODE_BROWSER_P = 103; - [CommandName("Tools.FileBrowser", "Global::Alt+U")] public const int FILE_BROWSER = 200; + [CommandName("Tools.FileBrowser", "Alt+U")] public const int FILE_BROWSER = 200; - [CommandName("Edit.ToggleBookmark1", "Global::Ctrl+Shift+1")] public const int BOOKMARK_SET_1 = 500; - [CommandName("Edit.ToggleBookmark2", "Global::Ctrl+Shift+2")] public const int BOOKMARK_SET_2 = 501; - [CommandName("Edit.ToggleBookmark3", "Global::Ctrl+Shift+3")] public const int BOOKMARK_SET_3 = 502; - [CommandName("Edit.ToggleBookmark4", "Global::Ctrl+Shift+4")] public const int BOOKMARK_SET_4 = 503; - [CommandName("Edit.ToggleBookmark5", "Global::Ctrl+Shift+5")] public const int BOOKMARK_SET_5 = 504; - [CommandName("Edit.ToggleBookmark6", "Global::Ctrl+Shift+6")] public const int BOOKMARK_SET_6 = 505; - [CommandName("Edit.ToggleBookmark7", "Global::Ctrl+Shift+7")] public const int BOOKMARK_SET_7 = 506; - [CommandName("Edit.ToggleBookmark8", "Global::Ctrl+Shift+8")] public const int BOOKMARK_SET_8 = 507; - [CommandName("Edit.ToggleBookmark9", "Global::Ctrl+Shift+9")] public const int BOOKMARK_SET_9 = 508; - [CommandName("Edit.ToggleBookmark0", "Global::Ctrl+Shift+0")] public const int BOOKMARK_SET_0 = 509; - [CommandName("Edit.GoToBookmark1", "Global::Ctrl+1")] public const int BOOKMARK_GET_1 = 510; - [CommandName("Edit.GoToBookmark2", "Global::Ctrl+2")] public const int BOOKMARK_GET_2 = 511; - [CommandName("Edit.GoToBookmark3", "Global::Ctrl+3")] public const int BOOKMARK_GET_3 = 512; - [CommandName("Edit.GoToBookmark4", "Global::Ctrl+4")] public const int BOOKMARK_GET_4 = 513; - [CommandName("Edit.GoToBookmark5", "Global::Ctrl+5")] public const int BOOKMARK_GET_5 = 514; - [CommandName("Edit.GoToBookmark6", "Global::Ctrl+6")] public const int BOOKMARK_GET_6 = 515; - [CommandName("Edit.GoToBookmark7", "Global::Ctrl+7")] public const int BOOKMARK_GET_7 = 516; - [CommandName("Edit.GoToBookmark8", "Global::Ctrl+8")] public const int BOOKMARK_GET_8 = 517; - [CommandName("Edit.GoToBookmark9", "Global::Ctrl+9")] public const int BOOKMARK_GET_9 = 518; - [CommandName("Edit.GoToBookmark0", "Global::Ctrl+0")] public const int BOOKMARK_GET_0 = 519; - [CommandName("Edit.ClearAllFileBookmarks", "Global::Ctrl+K, C")] public const int BOOKMARK_CLEAR_F = 520; - [CommandName("Edit.ClearAllSolutionBookmarks", "Global::Ctrl+K, A")] public const int BOOKMARK_CLEAR_S = 521; - [CommandName("Edit.ToggleGlobalBookmark1", "Global::Ctrl+Shift+Alt+1")] public const int BOOKMARK_SET_GLB_1 = 530; - [CommandName("Edit.ToggleGlobalBookmark2", "Global::Ctrl+Shift+Alt+2")] public const int BOOKMARK_SET_GLB_2 = 531; - [CommandName("Edit.ToggleGlobalBookmark3", "Global::Ctrl+Shift+Alt+3")] public const int BOOKMARK_SET_GLB_3 = 532; - [CommandName("Edit.ToggleGlobalBookmark4", "Global::Ctrl+Shift+Alt+4")] public const int BOOKMARK_SET_GLB_4 = 533; - [CommandName("Edit.ToggleGlobalBookmark5", "Global::Ctrl+Shift+Alt+5")] public const int BOOKMARK_SET_GLB_5 = 534; - [CommandName("Edit.ToggleGlobalBookmark6", "Global::Ctrl+Shift+Alt+6")] public const int BOOKMARK_SET_GLB_6 = 535; - [CommandName("Edit.ToggleGlobalBookmark7", "Global::Ctrl+Shift+Alt+7")] public const int BOOKMARK_SET_GLB_7 = 536; - [CommandName("Edit.ToggleGlobalBookmark8", "Global::Ctrl+Shift+Alt+8")] public const int BOOKMARK_SET_GLB_8 = 537; - [CommandName("Edit.ToggleGlobalBookmark9", "Global::Ctrl+Shift+Alt+9")] public const int BOOKMARK_SET_GLB_9 = 538; - [CommandName("Edit.ToggleGlobalBookmark0", "Global::Ctrl+Shift+Alt+0")] public const int BOOKMARK_SET_GLB_0 = 539; - [CommandName("Edit.GoToGlobalBookmark1", "Global::Ctrl+Alt+1")] public const int BOOKMARK_GET_GLB_1 = 540; - [CommandName("Edit.GoToGlobalBookmark2", "Global::Ctrl+Alt+2")] public const int BOOKMARK_GET_GLB_2 = 541; - [CommandName("Edit.GoToGlobalBookmark3", "Global::Ctrl+Alt+3")] public const int BOOKMARK_GET_GLB_3 = 542; - [CommandName("Edit.GoToGlobalBookmark4", "Global::Ctrl+Alt+4")] public const int BOOKMARK_GET_GLB_4 = 543; - [CommandName("Edit.GoToGlobalBookmark5", "Global::Ctrl+Alt+5")] public const int BOOKMARK_GET_GLB_5 = 544; - [CommandName("Edit.GoToGlobalBookmark6", "Global::Ctrl+Alt+6")] public const int BOOKMARK_GET_GLB_6 = 545; - [CommandName("Edit.GoToGlobalBookmark7", "Global::Ctrl+Alt+7")] public const int BOOKMARK_GET_GLB_7 = 546; - [CommandName("Edit.GoToGlobalBookmark8", "Global::Ctrl+Alt+8")] public const int BOOKMARK_GET_GLB_8 = 547; - [CommandName("Edit.GoToGlobalBookmark9", "Global::Ctrl+Alt+9")] public const int BOOKMARK_GET_GLB_9 = 548; - [CommandName("Edit.GoToGlobalBookmark0", "Global::Ctrl+Alt+0")] public const int BOOKMARK_GET_GLB_0 = 549; + [CommandName("Edit.ToggleBookmark1", "Ctrl+Shift+1")] public const int BOOKMARK_SET_1 = 500; + [CommandName("Edit.ToggleBookmark2", "Ctrl+Shift+2")] public const int BOOKMARK_SET_2 = 501; + [CommandName("Edit.ToggleBookmark3", "Ctrl+Shift+3")] public const int BOOKMARK_SET_3 = 502; + [CommandName("Edit.ToggleBookmark4", "Ctrl+Shift+4")] public const int BOOKMARK_SET_4 = 503; + [CommandName("Edit.ToggleBookmark5", "Ctrl+Shift+5")] public const int BOOKMARK_SET_5 = 504; + [CommandName("Edit.ToggleBookmark6", "Ctrl+Shift+6")] public const int BOOKMARK_SET_6 = 505; + [CommandName("Edit.ToggleBookmark7", "Ctrl+Shift+7")] public const int BOOKMARK_SET_7 = 506; + [CommandName("Edit.ToggleBookmark8", "Ctrl+Shift+8")] public const int BOOKMARK_SET_8 = 507; + [CommandName("Edit.ToggleBookmark9", "Ctrl+Shift+9")] public const int BOOKMARK_SET_9 = 508; + [CommandName("Edit.ToggleBookmark0", "Ctrl+Shift+0")] public const int BOOKMARK_SET_0 = 509; + [CommandName("Edit.GoToBookmark1", "Ctrl+1")] public const int BOOKMARK_GET_1 = 510; + [CommandName("Edit.GoToBookmark2", "Ctrl+2")] public const int BOOKMARK_GET_2 = 511; + [CommandName("Edit.GoToBookmark3", "Ctrl+3")] public const int BOOKMARK_GET_3 = 512; + [CommandName("Edit.GoToBookmark4", "Ctrl+4")] public const int BOOKMARK_GET_4 = 513; + [CommandName("Edit.GoToBookmark5", "Ctrl+5")] public const int BOOKMARK_GET_5 = 514; + [CommandName("Edit.GoToBookmark6", "Ctrl+6")] public const int BOOKMARK_GET_6 = 515; + [CommandName("Edit.GoToBookmark7", "Ctrl+7")] public const int BOOKMARK_GET_7 = 516; + [CommandName("Edit.GoToBookmark8", "Ctrl+8")] public const int BOOKMARK_GET_8 = 517; + [CommandName("Edit.GoToBookmark9", "Ctrl+9")] public const int BOOKMARK_GET_9 = 518; + [CommandName("Edit.GoToBookmark0", "Ctrl+0")] public const int BOOKMARK_GET_0 = 519; + [CommandName("Edit.ClearAllFileBookmarks", "Ctrl+K, C")] public const int BOOKMARK_CLEAR_F = 520; + [CommandName("Edit.ClearAllSolutionBookmarks", "Ctrl+K, A")] public const int BOOKMARK_CLEAR_S = 521; + [CommandName("Edit.ToggleGlobalBookmark1", "Ctrl+Shift+Alt+1")] public const int BOOKMARK_SET_GLB_1 = 530; + [CommandName("Edit.ToggleGlobalBookmark2", "Ctrl+Shift+Alt+2")] public const int BOOKMARK_SET_GLB_2 = 531; + [CommandName("Edit.ToggleGlobalBookmark3", "Ctrl+Shift+Alt+3")] public const int BOOKMARK_SET_GLB_3 = 532; + [CommandName("Edit.ToggleGlobalBookmark4", "Ctrl+Shift+Alt+4")] public const int BOOKMARK_SET_GLB_4 = 533; + [CommandName("Edit.ToggleGlobalBookmark5", "Ctrl+Shift+Alt+5")] public const int BOOKMARK_SET_GLB_5 = 534; + [CommandName("Edit.ToggleGlobalBookmark6", "Ctrl+Shift+Alt+6")] public const int BOOKMARK_SET_GLB_6 = 535; + [CommandName("Edit.ToggleGlobalBookmark7", "Ctrl+Shift+Alt+7")] public const int BOOKMARK_SET_GLB_7 = 536; + [CommandName("Edit.ToggleGlobalBookmark8", "Ctrl+Shift+Alt+8")] public const int BOOKMARK_SET_GLB_8 = 537; + [CommandName("Edit.ToggleGlobalBookmark9", "Ctrl+Shift+Alt+9")] public const int BOOKMARK_SET_GLB_9 = 538; + [CommandName("Edit.ToggleGlobalBookmark0", "Ctrl+Shift+Alt+0")] public const int BOOKMARK_SET_GLB_0 = 539; + [CommandName("Edit.GoToGlobalBookmark1", "Ctrl+Alt+1")] public const int BOOKMARK_GET_GLB_1 = 540; + [CommandName("Edit.GoToGlobalBookmark2", "Ctrl+Alt+2")] public const int BOOKMARK_GET_GLB_2 = 541; + [CommandName("Edit.GoToGlobalBookmark3", "Ctrl+Alt+3")] public const int BOOKMARK_GET_GLB_3 = 542; + [CommandName("Edit.GoToGlobalBookmark4", "Ctrl+Alt+4")] public const int BOOKMARK_GET_GLB_4 = 543; + [CommandName("Edit.GoToGlobalBookmark5", "Ctrl+Alt+5")] public const int BOOKMARK_GET_GLB_5 = 544; + [CommandName("Edit.GoToGlobalBookmark6", "Ctrl+Alt+6")] public const int BOOKMARK_GET_GLB_6 = 545; + [CommandName("Edit.GoToGlobalBookmark7", "Ctrl+Alt+7")] public const int BOOKMARK_GET_GLB_7 = 546; + [CommandName("Edit.GoToGlobalBookmark8", "Ctrl+Alt+8")] public const int BOOKMARK_GET_GLB_8 = 547; + [CommandName("Edit.GoToGlobalBookmark9", "Ctrl+Alt+9")] public const int BOOKMARK_GET_GLB_9 = 548; + [CommandName("Edit.GoToGlobalBookmark0", "Ctrl+Alt+0")] public const int BOOKMARK_GET_GLB_0 = 549; - [CommandName("Edit.TryCatch", "Global::Ctrl+K, X")] public const int SW_TRY_CATCH = 600; - [CommandName("Edit.TryFinally", "Global::Ctrl+K, T")] public const int SW_TRY_FINALLY = 601; - [CommandName("Edit.For", "Global::Ctrl+K, F")] public const int SW_FOR = 602; - [CommandName("Edit.ForEach", "Global::Ctrl+K, E")] public const int SW_FOR_EACH = 603; - [CommandName("Edit.Region", "Global::Ctrl+K, R")] public const int SW_REGION = 604; + [CommandName("Edit.TryCatch", "Ctrl+K, X")] public const int SW_TRY_CATCH = 600; + [CommandName("Edit.TryFinally", "Ctrl+K, T")] public const int SW_TRY_FINALLY = 601; + [CommandName("Edit.For", "Ctrl+K, F")] public const int SW_FOR = 602; + [CommandName("Edit.ForEach", "Ctrl+K, E")] public const int SW_FOR_EACH = 603; + [CommandName("Edit.Region", "Ctrl+K, R")] public const int SW_REGION = 604; [CommandName("Tools.DPackWebSite")] public const int PROJECT_HOME = 700; [CommandName("Tools.DPackEmailUs")] public const int SUPPORT_EMAIL = 701; @@ -67,13 +67,13 @@ public static class CommandIDs [CommandName("Tools.SolutionStatistics")] public const int CODE_STATS = 800; - [CommandName("Tools.SolutionBackup", "Global::Shift+Alt+B")] public const int BACKUP = 900; + [CommandName("Tools.SolutionBackup", "Shift+Alt+B")] public const int BACKUP = 900; - [CommandName("ProjectandSolutionContextMenus.Solution.CollapseAllProjects", "Global::Shift+Alt+C")] public const int COLLAPSE_SOLUTION_CONTEXT = 1101; + [CommandName("ProjectandSolutionContextMenus.Solution.CollapseAllProjects", "Shift+Alt+C")] public const int COLLAPSE_SOLUTION_CONTEXT = 1101; [CommandName("ProjectandSolutionContextMenus.ReferenceRoot.Copy")] public const int COPY_REFERENCES_CONTEXT = 1102; [CommandName("ProjectandSolutionContextMenus.ReferenceRoot.Paste")] public const int PASTE_REFERENCES_CONTEXT = 1103; [CommandName("ProjectandSolutionContextMenus.ReferenceRoot.Copy")] public const int COPY_REFERENCE_CONTEXT = 1104; - [CommandName("OtherContextMenus.EasyMDIDocumentWindow.LocateInSolutionExplorer", "Global::Shift+Alt+L")] public const int LOCATE_IN_SOLUTION_EXPLORER_CONTEXT = 1105; + [CommandName("OtherContextMenus.EasyMDIDocumentWindow.LocateInSolutionExplorer", "Shift+Alt+L")] public const int LOCATE_IN_SOLUTION_EXPLORER_CONTEXT = 1105; [CommandName("ProjectandSolutionContextMenus.Project.OpenCommandPrompt")] public const int COMMAND_PROMPT = 1106; [CommandName("ProjectandSolutionContextMenus.Project.CopyFullPath")] public const int COPY_FULL_PATH = 1107; } diff --git a/DPackRx/Services/ShellService.cs b/DPackRx/Services/ShellService.cs index 14f9864..36fe525 100644 --- a/DPackRx/Services/ShellService.cs +++ b/DPackRx/Services/ShellService.cs @@ -44,6 +44,7 @@ public class ShellService : IShellHelperService, IShellStatusBarService, IShellR private readonly bool _webInteropAvailable; private readonly bool _cppInteropAvailable; + private const string LOG_CATEGORY = "Shell"; internal const int DEFAULT_WAIT_MSECS = 1000; internal const string PROJECT_ITEM_KIND_SETUP = "{54435603-DBB4-11D2-8724-00A0C9A8B90C}"; internal const string TEXT_DOCUMENT = "TextDocument"; @@ -77,7 +78,7 @@ public ShellService(IServiceProvider serviceProvider, ILog log, ILanguageService { _webInteropAvailable = false; - _log.LogMessage("Web Interop is not available"); + _log.LogMessage("Web Interop is not available", LOG_CATEGORY); } try @@ -89,7 +90,7 @@ public ShellService(IServiceProvider serviceProvider, ILog log, ILanguageService { _cppInteropAvailable = false; - _log.LogMessage("C++ Interop is not available"); + _log.LogMessage("C++ Interop is not available", LOG_CATEGORY); } } @@ -179,7 +180,7 @@ public string GetCurrentProjectPath() } catch (Exception ex) { - _log.LogMessage(ex); + _log.LogMessage(ex, LOG_CATEGORY); return null; } } @@ -214,7 +215,7 @@ public void CollapseAllProjects() { ThreadHelper.ThrowIfNotOnUIThread(); - _log.LogMessage("Collapse all projects - enter"); + _log.LogMessage("Collapse all projects - enter", LOG_CATEGORY); System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor; try @@ -223,12 +224,12 @@ public void CollapseAllProjects() var solution = dte.Solution; var solutionName = GetSolutionName(solution); - _log.LogMessage($"Collapse all projects - solution {solutionName}"); + _log.LogMessage($"Collapse all projects - solution {solutionName}", LOG_CATEGORY); var solutionWindow = dte.Windows.Item(EnvDTE.Constants.vsWindowKindSolutionExplorer); if (solutionWindow == null) { - _log.LogMessage("Collapse all projects - failed to retrieve Solution Explorer window"); + _log.LogMessage("Collapse all projects - failed to retrieve Solution Explorer window", LOG_CATEGORY); return; } @@ -256,7 +257,7 @@ public void CollapseAllProjects() } else { - _log.LogMessage("Collapse all projects - no solution items detected"); + _log.LogMessage("Collapse all projects - no solution items detected", LOG_CATEGORY); } } } @@ -265,7 +266,7 @@ public void CollapseAllProjects() System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default; } - _log.LogMessage("Collapse all projects - exit"); + _log.LogMessage("Collapse all projects - exit", LOG_CATEGORY); } /// @@ -288,6 +289,7 @@ public bool OpenFileAt(string fileName, int line, int column) if (textView.SetCaretPos(line - 1, column - 1) != VSConstants.S_OK) // text view coordinates are 0-based return false; + textView.CenterLines(line - 1, 1); return true; } @@ -331,6 +333,14 @@ public bool AssignShortcuts() try { var dte = GetDTEInternal(); + + var scope = GetGlobalScopeName(dte); + if (string.IsNullOrEmpty(scope)) + { + _log.LogMessage("Failed to retrieve global scope name", LOG_CATEGORY); + return false; + } + var fields = typeof(CommandIDs).GetFields(BindingFlags.Public | BindingFlags.Static).ToList(); var attribs = new List(fields.Count); fields.ForEach(f => attribs.Add((CommandNameAttribute)f.GetCustomAttribute(typeof(CommandNameAttribute)))); @@ -343,13 +353,13 @@ public bool AssignShortcuts() { var command = dte.Commands.Item(attrib.Name, 1); if (command != null) - command.Bindings = attrib.Binding; + command.Bindings = $"{scope}::{attrib.Binding}"; else - _log.LogMessage($"Command {attrib.Name} is not available"); + _log.LogMessage($"Command {attrib.Name} is not available", LOG_CATEGORY); } catch (Exception ex) { - _log.LogMessage($"Error assigning shortcut for {attrib.Name} command and {attrib.Binding} binding", ex); + _log.LogMessage($"Error assigning shortcut for {attrib.Name} command and {attrib.Binding} binding", ex, LOG_CATEGORY); } } } @@ -381,13 +391,13 @@ public bool AssignShortcuts() if (!string.IsNullOrEmpty(resolvedBinding)) { scopes.Add(attrib.Scope, resolvedBinding); - _log.LogMessage($"VS command {attrib.Name} - resolved {attrib.Scope} scope to {resolvedBinding}"); + _log.LogMessage($"VS command {attrib.Name} - resolved {attrib.Scope} scope to {resolvedBinding}", LOG_CATEGORY); } } if (string.IsNullOrEmpty(resolvedBinding)) { - _log.LogMessage($"VS command {attrib.Name} - could not resolve {attrib.Scope} scope"); + _log.LogMessage($"VS command {attrib.Name} - could not resolve {attrib.Scope} scope", LOG_CATEGORY); continue; } @@ -397,20 +407,20 @@ public bool AssignShortcuts() command.Bindings = binding; } else - _log.LogMessage($"VS command {attrib.Name} is not available"); + _log.LogMessage($"VS command {attrib.Name} is not available", LOG_CATEGORY); } catch (Exception ex) { - _log.LogMessage($"Error assigning shortcut for VS {attrib.Name} command and {attrib.Binding} binding", ex); + _log.LogMessage($"Error assigning shortcut for VS {attrib.Name} command and {attrib.Binding} binding", ex, LOG_CATEGORY); } } - _log.LogMessage("Assigned shortcuts"); + _log.LogMessage("Assigned shortcuts", LOG_CATEGORY); return true; } catch (Exception ex) { - _log.LogMessage($"Error assigning shortcuts: {ex.Message}", ex); + _log.LogMessage($"Error assigning shortcuts: {ex.Message}", ex, LOG_CATEGORY); return false; } finally @@ -447,7 +457,7 @@ public void ExecuteCommand(string command, string arguments = null) } catch (Exception ex) { - _log.LogMessage($"Error executing {command} command: {ex.Message}", ex); + _log.LogMessage($"Error executing {command} command: {ex.Message}", ex, LOG_CATEGORY); } } @@ -542,7 +552,7 @@ public bool AddProjectReference(string projectName) } catch (Exception ex) { - _log.LogMessage($"Error referencing project: {projectName}", ex); + _log.LogMessage($"Error referencing project: {projectName}", ex, LOG_CATEGORY); return false; } @@ -572,7 +582,7 @@ public bool AddAssemblyReference(string fileName) } catch (Exception ex) { - _log.LogMessage($"Error referencing project assembly: {fileName}", ex); + _log.LogMessage($"Error referencing project assembly: {fileName}", ex, LOG_CATEGORY); throw; } } @@ -613,13 +623,13 @@ public bool IsContextActive(ContextType context) case ContextType.HTMLSourceEditor: return IsContextActiveInternal(new Guid(ContextGuids.vsContextGuidHTMLSourceEditor)); case ContextType.XamlEditor: - return IsContextActiveInternal(new Guid(GUIDs.GUID_XamlLanguageService)); + return IsContextActiveInternal(new Guid(GUIDs.GUID_XAML_LANGUAGE_SERVICE)); case ContextType.NewXamlEditor: - return IsContextActiveInternal(new Guid(GUIDs.GUID_NewXamlLanguageService)); + return IsContextActiveInternal(new Guid(GUIDs.GUID_NEW_XAML_LANGUAGE_SERVICE)); case ContextType.XamlDesigner: - return IsContextActiveInternal(new Guid(GUIDs.GUID_XamlDesigner)); + return IsContextActiveInternal(new Guid(GUIDs.GUID_XAML_DESIGNER)); default: - _log.LogMessage($"Invalid selection context: {context}"); + _log.LogMessage($"Invalid selection context: {context}", LOG_CATEGORY); return false; } } @@ -728,21 +738,21 @@ public Position GetActiveFilePosition() /// /// Sets active document's cursor position. /// - public bool SetActiveFilePosition(int row, int column) + public bool SetActiveFilePosition(int line, int column) { ThreadHelper.ThrowIfNotOnUIThread(); - if ((row <= 0) || (column <= 0)) + if ((line <= 0) || (column <= 0)) return false; var textManager = _serviceProvider.GetService(); if (textManager.GetActiveView(Convert.ToInt32(true), null, out IVsTextView textView) != VSConstants.S_OK) return false; - if (textView.SetCaretPos(row - 1, column - 1) != VSConstants.S_OK) // text view coordinates are 0-based + if (textView.SetCaretPos(line - 1, column - 1) != VSConstants.S_OK) // text view coordinates are 0-based return false; - textView.CenterLines(row - 1, 1); + textView.CenterLines(line - 1, 1); return true; } @@ -823,7 +833,7 @@ public bool IsProjectLoadDeferred(object project, out bool loaded) !(deferred is bool) || !(bool)deferred) return false; - _log.LogMessage($"Project '{dteProject?.Name}' load is deferred"); + _log.LogMessage($"Project '{dteProject?.Name}' load is deferred", LOG_CATEGORY); if (hierarchy.GetGuidProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID.VSHPROPID_ProjectIDGuid, out Guid projectGuid) != VSConstants.S_OK) return false; @@ -832,11 +842,11 @@ public bool IsProjectLoadDeferred(object project, out bool loaded) if (result == VSConstants.S_OK) { loaded = true; - _log.LogMessage($"Deferred project '{dteProject?.Name}' is loaded"); + _log.LogMessage($"Deferred project '{dteProject?.Name}' is loaded", LOG_CATEGORY); } else { - _log.LogMessage($"Failed to load deferred project '{dteProject?.Name}' - error {result}"); + _log.LogMessage($"Failed to load deferred project '{dteProject?.Name}' - error {result}", LOG_CATEGORY); return true; } @@ -946,7 +956,7 @@ public void GetProjectPath(object project, out string projectPath, out string pr } else { - // Don't even attempt getting full name on projects that don't support extensibility + // Don't even attempt getting full name on projects that don't support extensibility // code model. Those include DB projects, Script debug time projects, etc. if (dteProject.Kind != EnvDTE.Constants.vsProjectKindUnmodeled) { @@ -1046,11 +1056,11 @@ public string GetProjectLanguage(object project) { if (ex is NotImplementedException) // This is an acceptable condition { - _log.LogMessage($"Project '{dteProject.Name}' doesn't implement code model"); + _log.LogMessage($"Project '{dteProject.Name}' doesn't implement code model", LOG_CATEGORY); return string.Empty; } - _log.LogMessage($"Project '{dteProject.Name}' code model is not yet available"); + _log.LogMessage($"Project '{dteProject.Name}' code model is not yet available", LOG_CATEGORY); // Project could still be loading System.Threading.Thread.Sleep(DEFAULT_WAIT_MSECS); @@ -1060,7 +1070,7 @@ public string GetProjectLanguage(object project) if ((codeModel == null) && IsWebProject(dteProject)) { - _log.LogMessage($"Loading web project: {dteProject.Name}"); + _log.LogMessage($"Loading web project: {dteProject.Name}", LOG_CATEGORY); try { @@ -1070,12 +1080,12 @@ public string GetProjectLanguage(object project) } catch (Exception ex) { - _log.LogMessage($"Project '{dteProject.Name}' code model is not available", ex); + _log.LogMessage($"Project '{dteProject.Name}' code model is not available", ex, LOG_CATEGORY); return string.Empty; } if (codeModel == null) - _log.LogMessage($"Project '{dteProject.Name}' code model is not available"); + _log.LogMessage($"Project '{dteProject.Name}' code model is not available", LOG_CATEGORY); } if ((codeModel != null) && (codeModel.Language != null)) @@ -1170,7 +1180,7 @@ public object GetFileCodeModel(object projectItem) EnvDTE.FileCodeModel result; try { - _log.LogMessage($"Collecting item code model: {dteItem.Name}"); + _log.LogMessage($"Collecting item code model: {dteItem.Name}", LOG_CATEGORY); result = dteItem.FileCodeModel; } @@ -1179,19 +1189,19 @@ public object GetFileCodeModel(object projectItem) // File/directory missing means that file is not available if ((ex is DirectoryNotFoundException) || (ex is FileNotFoundException)) { - _log.LogMessage($"File is not on disk: {dteItem.Name}"); + _log.LogMessage($"File is not on disk: {dteItem.Name}", LOG_CATEGORY); result = null; } else { - _log.LogMessage($"File code model access error: {dteItem.Name}"); + _log.LogMessage($"File code model access error: {dteItem.Name}", LOG_CATEGORY); throw; } } if ((result == null) && IsWebProjectItem(projectItem)) { - _log.LogMessage($"Loading web item: {dteItem.Name}"); + _log.LogMessage($"Loading web item: {dteItem.Name}", LOG_CATEGORY); try { @@ -1204,12 +1214,12 @@ public object GetFileCodeModel(object projectItem) } catch (Exception ex) { - _log.LogMessage($"File '{dteItem.Name}' code model is not available", ex); + _log.LogMessage($"File '{dteItem.Name}' code model is not available", ex, LOG_CATEGORY); result = null; } } - _log.LogMessage($"Collected item code model: {dteItem.Name}"); + _log.LogMessage($"Collected item code model: {dteItem.Name}", LOG_CATEGORY); return result; } @@ -1239,7 +1249,7 @@ public bool CompileBuildAction(object projectItemOrProject) } catch (Exception ex) { - _log.LogMessage("Error retrieving build action", ex); + _log.LogMessage("Error retrieving build action", ex, LOG_CATEGORY); return false; } } @@ -1331,25 +1341,25 @@ public string GetProjectItemSubType(object projectItem) var solution = _serviceProvider.GetService(); if (solution.GetProjectOfUniqueName(project.UniqueName, out IVsHierarchy projectHierarchy) != VSConstants.S_OK) { - _log.LogMessage($"Failed to retrieve '{project.UniqueName}' project hierarchy"); + _log.LogMessage($"Failed to retrieve '{project.UniqueName}' project hierarchy", LOG_CATEGORY); return null; } if (projectHierarchy.ParseCanonicalName(fileName, out uint itemId) != VSConstants.S_OK) { - _log.LogMessage($"Failed to parse '{project.UniqueName}' project name"); + _log.LogMessage($"Failed to parse '{project.UniqueName}' project name", LOG_CATEGORY); return null; } if (projectHierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_ItemSubType, out object value) != VSConstants.S_OK) { - _log.LogMessage($"'{project.UniqueName}' project {itemId} item sub-type is not available"); + _log.LogMessage($"'{project.UniqueName}' project {itemId} item sub-type is not available", LOG_CATEGORY); return null; } if (!(value is string)) { - _log.LogMessage($"'{project.UniqueName}' project {itemId} item sub-type is invalid: {value}"); + _log.LogMessage($"'{project.UniqueName}' project {itemId} item sub-type is invalid: {value}", LOG_CATEGORY); return null; } @@ -1804,27 +1814,27 @@ private bool GetSelectionProject(out Project project, out VSProject vsProject, if (solution == null) { - _log.LogMessage("Failed to retrieve solution service"); + _log.LogMessage("Failed to retrieve solution service", LOG_CATEGORY); return false; } if ((selectedItems == null) || (selectedItems.Count == 0)) { - _log.LogMessage("Selection is empty"); + _log.LogMessage("Selection is empty", LOG_CATEGORY); return false; } var hierarchy = GetSelectionHierarchy(); if (hierarchy == null) { - _log.LogMessage("Failed to retrieve selection"); + _log.LogMessage("Failed to retrieve selection", LOG_CATEGORY); return false; } project = GetProjectFromHierarchy(hierarchy); if (project == null) { - _log.LogMessage("Failed to retrieve selected project"); + _log.LogMessage("Failed to retrieve selected project", LOG_CATEGORY); return false; } @@ -1982,7 +1992,7 @@ private bool SelectSolutionExplorerItem(ProjectItem item) var result = uiShell.FindToolWindow(0, ref solutionExplorerGuid, out IVsWindowFrame solutionExplorerFrame); if ((result != VSConstants.S_OK) || (solutionExplorerFrame == null)) { - _log.LogMessage("Failed to retrieve Solution Explorer toolwindow"); + _log.LogMessage("Failed to retrieve Solution Explorer toolwindow", LOG_CATEGORY); return false; } @@ -1993,7 +2003,7 @@ private bool SelectSolutionExplorerItem(ProjectItem item) result = solutionExplorerFrame.GetProperty((int)__VSFPROPID.VSFPROPID_DocView, out object obj); if (result != VSConstants.S_OK) { - _log.LogMessage("Failed to retrieve Solution Explorer hierarchy window"); + _log.LogMessage("Failed to retrieve Solution Explorer hierarchy window", LOG_CATEGORY); return false; } @@ -2014,7 +2024,7 @@ private bool SelectSolutionExplorerItem(ProjectItem item) { result = solutionExplorerWindow.ExpandItem(uiHierarchy, itemId, EXPANDFLAGS.EXPF_SelectItem); - _log.LogMessage($"Selected '{item.Name}' item: result - {result}"); + _log.LogMessage($"Selected '{item.Name}' item: result - {result}", LOG_CATEGORY); if (result == VSConstants.S_OK) return true; @@ -2022,7 +2032,7 @@ private bool SelectSolutionExplorerItem(ProjectItem item) } else { - _log.LogMessage("File must be a part of currently opened solution"); + _log.LogMessage("File must be a part of currently opened solution", LOG_CATEGORY); } return false; @@ -2071,9 +2081,9 @@ private void CollapseAllRecursively(UIHierarchy hierarchy, UIHierarchyItem paren } if (projectName != null) - _log.LogMessage($"Collapse all projects - project {projectName} won't be processed any further"); + _log.LogMessage($"Collapse all projects - project {projectName} won't be processed any further", LOG_CATEGORY); else - _log.LogMessage("Collapse all projects - project won't be processed any further"); + _log.LogMessage("Collapse all projects - project won't be processed any further", LOG_CATEGORY); } } } // project check @@ -2101,9 +2111,9 @@ private void CollapseAllRecursively(UIHierarchy hierarchy, UIHierarchyItem paren } if (itemName != null) - _log.LogMessage($"Collapse all projects - error processing {itemName} item"); + _log.LogMessage($"Collapse all projects - error processing {itemName} item", LOG_CATEGORY); else - _log.LogMessage("Collapse all projects - error processing item"); + _log.LogMessage("Collapse all projects - error processing item", LOG_CATEGORY); throw; } @@ -2173,11 +2183,11 @@ private string GetProjectLanguage(Project project, int waitMSecs) { if (ex is NotImplementedException) // This is an acceptable condition { - _log.LogMessage("Project doesn't implement code model"); + _log.LogMessage("Project doesn't implement code model", LOG_CATEGORY); return string.Empty; } - _log.LogMessage($"Project '{project.Name}' code model is not yet available."); + _log.LogMessage($"Project '{project.Name}' code model is not yet available.", LOG_CATEGORY); // Project could still be loading if (waitMSecs > 0) @@ -2188,7 +2198,7 @@ private string GetProjectLanguage(Project project, int waitMSecs) if ((codeModel == null) && IsWebProject(project)) { - _log.LogMessage($"Loading web project: {project.Name}"); + _log.LogMessage($"Loading web project: {project.Name}", LOG_CATEGORY); try { @@ -2198,12 +2208,12 @@ private string GetProjectLanguage(Project project, int waitMSecs) } catch (Exception ex) { - _log.LogMessage($"Project '{project.Name}' code model is not available.", ex); + _log.LogMessage($"Project '{project.Name}' code model is not available.", ex, LOG_CATEGORY); return string.Empty; } if (codeModel == null) - _log.LogMessage($"Project '{project.Name}' code model is not available."); + _log.LogMessage($"Project '{project.Name}' code model is not available.", LOG_CATEGORY); } if ((codeModel != null) && (codeModel.Language != null)) @@ -2381,7 +2391,7 @@ private void ActivateWindow(IExtensibilityItem item, bool alternativeView) } catch (Exception ex) { - _log.LogMessage($"File '{item.Name}' is not found", ex); + _log.LogMessage($"File '{item.Name}' is not found", ex, LOG_CATEGORY); return; } @@ -2442,6 +2452,38 @@ private IVsTextView GetTextView(string fileName) return textView; } + /// + /// Use a well know command in the Global scope to resolve scope's localized name. + /// + private string GetGlobalScopeName(DTE dte) + { + ThreadHelper.ThrowIfNotOnUIThread(); + + var scopeCommand = dte.Commands.Item("File.Exit", 1); + if (scopeCommand == null) + { + _log.LogMessage("Failed to retrieve scope command", LOG_CATEGORY); + return null; + } + + var scopes = (object[])scopeCommand.Bindings; + if ((scopes == null) || (scopes.Length == 0)) + { + _log.LogMessage("Scope command has no bindings", LOG_CATEGORY); + return null; + } + + var rawScope = scopes[0]?.ToString(); + if (rawScope == null) + { + _log.LogMessage("Scope command binding cannot be determined", LOG_CATEGORY); + return null; + } + + var scope = rawScope.Substring(0, rawScope.IndexOf("::")); + return scope; + } + #endregion } } \ No newline at end of file From f3e1a12654132a00e735710c9b96f797cd348603 Mon Sep 17 00:00:00 2001 From: Sergey M Date: Mon, 10 Aug 2020 08:32:57 -0400 Subject: [PATCH 3/4] Fixed bookmarks assignment/processing issue for Xaml files. --- DPackRx/Extensions/TextBufferExtensions.cs | 24 +++++++++++++++++++ .../Features/Bookmarks/BookmarksService.cs | 6 ++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/DPackRx/Extensions/TextBufferExtensions.cs b/DPackRx/Extensions/TextBufferExtensions.cs index de9753a..259530a 100644 --- a/DPackRx/Extensions/TextBufferExtensions.cs +++ b/DPackRx/Extensions/TextBufferExtensions.cs @@ -1,4 +1,5 @@ using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Projection; namespace DPackRx.Extensions { @@ -11,6 +12,27 @@ public static class TextBufferExtensions /// Custom: returns service from the text buffer. /// public static T GetService(this ITextBuffer textBuffer) + { + T service = TryGetService(textBuffer); + if (service != null) + return service; + + if (textBuffer is IProjectionBufferBase projectionBuffer) + { + foreach (ITextBuffer sourceTextBuffer in projectionBuffer.SourceBuffers) + { + service = TryGetService(sourceTextBuffer); + if (service != null) + return service; + } + } + + return default; + } + + #region Private Methods + + private static T TryGetService(this ITextBuffer textBuffer) { T service = default; var result = textBuffer.Properties?.TryGetProperty(typeof(T), out service); @@ -19,5 +41,7 @@ public static T GetService(this ITextBuffer textBuffer) else return default; } + + #endregion } } \ No newline at end of file diff --git a/DPackRx/Features/Bookmarks/BookmarksService.cs b/DPackRx/Features/Bookmarks/BookmarksService.cs index c2b822c..6abd26e 100644 --- a/DPackRx/Features/Bookmarks/BookmarksService.cs +++ b/DPackRx/Features/Bookmarks/BookmarksService.cs @@ -110,7 +110,7 @@ public void RegisterCallback(IBookmarkCallbackClient client, string fileName) if (_bookmarkCallbacks.ContainsKey(fileName) || _bookmarkCallbacks.ContainsValue(client)) { - _log.LogMessage("Callback client has already been registered", LOG_CATEGORY); + _log.LogMessage($"Callback client has already been registered: {Path.GetFileName(fileName)}", LOG_CATEGORY); return; } @@ -251,7 +251,11 @@ public bool GoToBookmark(int number) return false; if (!_bookmarks.ContainsKey(fileName)) + { + _shellStatusBarService.SetStatusBarText($"Bookmark {number} not found"); + _log.LogMessage($"Bookmark # {number} is not found", LOG_CATEGORY); return false; + } _log.LogMessage($"Looking for '{fileName}' bookmark # {number}", LOG_CATEGORY); var bookmarks = _bookmarks[fileName]; From aec6fe1ef2fc8c8cbf62c4c02a4400a70823e8d7 Mon Sep 17 00:00:00 2001 From: Sergey M Date: Mon, 10 Aug 2020 08:33:08 -0400 Subject: [PATCH 4/4] Beta version bump. --- DPackRx/Package/Beta.cs | 2 +- DPackRx/source.extension.vsixmanifest | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DPackRx/Package/Beta.cs b/DPackRx/Package/Beta.cs index e791ef9..e8ef3d7 100644 --- a/DPackRx/Package/Beta.cs +++ b/DPackRx/Package/Beta.cs @@ -8,7 +8,7 @@ namespace DPackRx.Package /// internal static class Beta { - public static readonly DateTime ExpirationDate = new DateTime(2020, 10, 5).AddHours(12); + public static readonly DateTime ExpirationDate = new DateTime(2020, 10, 19).AddHours(12); } #endif } \ No newline at end of file diff --git a/DPackRx/source.extension.vsixmanifest b/DPackRx/source.extension.vsixmanifest index 398499c..ea78ebd 100644 --- a/DPackRx/source.extension.vsixmanifest +++ b/DPackRx/source.extension.vsixmanifest @@ -1,7 +1,7 @@  - + DPack Rx FREE tools collection designed to greatly increase developer's productivity, automate repetitive processes and expand upon some of Microsoft Visual Studio features. Visual Studio 2017 and 2019 are supported. https://github.com/usysware/dpack