diff --git a/DPackRx.Tests/DPackRx.Tests.csproj b/DPackRx.Tests/DPackRx.Tests.csproj
index 5e7e87a..6029e08 100644
--- a/DPackRx.Tests/DPackRx.Tests.csproj
+++ b/DPackRx.Tests/DPackRx.Tests.csproj
@@ -52,9 +52,11 @@
+
+
@@ -93,10 +95,10 @@
13.0.1
- 3.13.2
+ 3.13.3
- 4.1.0
+ 4.3.1
17.0.31902.203
diff --git a/DPackRx.Tests/Features/SurroundWithFeatureTests.cs b/DPackRx.Tests/Features/SurroundWithFeatureTests.cs
index 09ea410..2a97089 100644
--- a/DPackRx.Tests/Features/SurroundWithFeatureTests.cs
+++ b/DPackRx.Tests/Features/SurroundWithFeatureTests.cs
@@ -1,8 +1,4 @@
using System;
-using System.Windows.Input;
-
-using Moq;
-using NUnit.Framework;
using DPackRx.CodeModel;
using DPackRx.Features;
@@ -12,6 +8,10 @@
using DPackRx.Package;
using DPackRx.Services;
+using Moq;
+
+using NUnit.Framework;
+
namespace DPackRx.Tests.Features
{
///
@@ -25,10 +25,9 @@ public class SurroundWithFeatureTests
private Mock _serviceProviderMock;
private Mock _logMock;
private Mock _optionsServiceMock;
- private Mock _shellHelperServiceMock;
private Mock _shellSelectionServiceMock;
private Mock _fileTypeResolverMock;
- private Mock _keyboardServiceMock;
+ private Mock _surroundWithFormatterServiceMock;
private LanguageSettings _settings;
#endregion
@@ -45,9 +44,6 @@ public void Setup()
_optionsServiceMock = new Mock();
- _shellHelperServiceMock = new Mock();
- _shellHelperServiceMock.Setup(s => s.ExecuteCommand(It.IsNotNull(), null)).Verifiable();
-
_shellSelectionServiceMock = new Mock();
_shellSelectionServiceMock.Setup(s => s.IsContextActive(It.IsAny())).Returns(true).Verifiable();
_shellSelectionServiceMock.Setup(s => s.GetActiveProject()).Returns(new object()).Verifiable();
@@ -57,9 +53,8 @@ public void Setup()
_fileTypeResolverMock = new Mock();
_fileTypeResolverMock.Setup(f => f.GetCurrentLanguage(It.IsAny
internal static class Beta
{
- public static readonly DateTime ExpirationDate = new DateTime(2023, 1, 16).AddHours(12);
+ public static readonly DateTime ExpirationDate = new DateTime(2023, 4, 3).AddHours(12);
}
#endif
}
\ No newline at end of file
diff --git a/DPackRx/Package/LanguageConsts.cs b/DPackRx/Package/LanguageConsts.cs
index 3e43cca..a787df8 100644
--- a/DPackRx/Package/LanguageConsts.cs
+++ b/DPackRx/Package/LanguageConsts.cs
@@ -34,5 +34,10 @@ public static class LanguageConsts
/// Fake solution items project language Guid.
///
public const string VS_LANGUAGE_SOLUTION_ITEMS = "{FFFFFFFF-0000-FFFF-FFFF-FFFFFFFFFFFF}";
+
+ ///
+ /// VS Sql project language Guid.
+ ///
+ public const string VS_LANGUAGE_SQL = "{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}";
}
}
\ No newline at end of file
diff --git a/DPackRx/Package/Registration/ProvideLanguageAttribute.cs b/DPackRx/Package/Registration/ProvideLanguageAttribute.cs
index a2e1b93..19c15da 100644
--- a/DPackRx/Package/Registration/ProvideLanguageAttribute.cs
+++ b/DPackRx/Package/Registration/ProvideLanguageAttribute.cs
@@ -72,6 +72,8 @@ public ProvideLanguageAttribute(string productName, string languageGuid, string
public string WebLanguage { get; set; }
+ public string Languages { get; set; }
+
public string[] Comments { get; set; }
public string XmlDoc { get; set; }
@@ -123,6 +125,8 @@ public override void Register(RegistrationContext context)
key.SetValue(nameof(this.ProjectGuid), this.ProjectGuid);
if (!string.IsNullOrEmpty(this.WebLanguage))
key.SetValue(nameof(this.WebLanguage), this.WebLanguage);
+ if ((this.Languages != null) && (this.Languages.Length > 0))
+ key.SetValue(nameof(this.Languages), string.Join(",", this.Languages));
if (!string.IsNullOrEmpty(this.XmlDoc))
key.SetValue(nameof(this.XmlDoc), this.XmlDoc);
if (this.XmlDocSurround)
diff --git a/DPackRx/Services/IKeyboardService.cs b/DPackRx/Services/IKeyboardService.cs
deleted file mode 100644
index 65508fc..0000000
--- a/DPackRx/Services/IKeyboardService.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System.Windows.Input;
-
-namespace DPackRx.Services
-{
- ///
- /// Keyboard auto-entry service.
- ///
- public interface IKeyboardService
- {
- ///
- /// Types the specified text.
- ///
- void Type(string text);
-
- ///
- /// Presses and releases the specified key.
- ///
- void Type(Key key);
- }
-}
\ No newline at end of file
diff --git a/DPackRx/Services/ISurroundWithFormatterService.cs b/DPackRx/Services/ISurroundWithFormatterService.cs
new file mode 100644
index 0000000..71766e7
--- /dev/null
+++ b/DPackRx/Services/ISurroundWithFormatterService.cs
@@ -0,0 +1,15 @@
+using DPackRx.Features.SurroundWith;
+
+namespace DPackRx.Services
+{
+ ///
+ /// Surround with formatter.
+ ///
+ public interface ISurroundWithFormatterService
+ {
+ ///
+ /// Formats surround with according to provided model.
+ ///
+ void Format(SurroundWithLanguageModel model);
+ }
+}
\ No newline at end of file
diff --git a/DPackRx/Services/KeyboardService.cs b/DPackRx/Services/KeyboardService.cs
deleted file mode 100644
index e1b833f..0000000
--- a/DPackRx/Services/KeyboardService.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System;
-using System.Windows.Input;
-
-using DPackRx.Helpers;
-
-namespace DPackRx.Services
-{
- ///
- /// Keyboard auto-entry service.
- ///
- public class KeyboardService : IKeyboardService
- {
- #region IKeyboardService Members
-
- ///
- /// Types the specified text.
- ///
- public void Type(string text)
- {
- if (string.IsNullOrEmpty(text))
- throw new ArgumentNullException(nameof(text));
-
- KeyboardHelper.Type(text);
- }
-
- ///
- /// Presses and releases the specified key.
- ///
- public void Type(Key key)
- {
- KeyboardHelper.Type(key);
- }
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/DPackRx/Services/ShellService.cs b/DPackRx/Services/ShellService.cs
index 914288f..acfbebf 100644
--- a/DPackRx/Services/ShellService.cs
+++ b/DPackRx/Services/ShellService.cs
@@ -1129,9 +1129,12 @@ public string GetNoCodeModelProjectLanguage(object project)
var dteProject = GetProjectInternal(project);
- // Solution items project has no code model
- if (dteProject.Kind.Equals(EnvDTE.Constants.vsProjectKindSolutionItems, StringComparison.OrdinalIgnoreCase))
+ // Solution items project has no code model; workaround for other project types - should come up with more generic way of handling that
+ var kind = dteProject.Kind;
+ if (kind.Equals(EnvDTE.Constants.vsProjectKindSolutionItems, StringComparison.OrdinalIgnoreCase))
return _languageService.GetLanguage(LanguageType.SolutionItems)?.Language;
+ else if (kind.Equals(LanguageConsts.VS_LANGUAGE_SQL, StringComparison.OrdinalIgnoreCase))
+ return _languageService.GetLanguage(LanguageType.Sql)?.Language;
if (IsKnownNoCodeModelProject(dteProject))
return string.Empty;
diff --git a/DPackRx/Services/SurroundWithFormatterService.cs b/DPackRx/Services/SurroundWithFormatterService.cs
new file mode 100644
index 0000000..f548a81
--- /dev/null
+++ b/DPackRx/Services/SurroundWithFormatterService.cs
@@ -0,0 +1,134 @@
+using System;
+using System.Runtime.InteropServices;
+
+using DPackRx.Features.SurroundWith;
+
+using EnvDTE;
+
+using Microsoft.VisualStudio.Shell;
+
+namespace DPackRx.Services
+{
+ ///
+ /// Surround with formatter.
+ ///
+ public class SurroundWithFormatterService : ISurroundWithFormatterService
+ {
+ #region Fields
+
+ private readonly IShellSelectionService _shellSelectionService;
+ private readonly IShellHelperService _shellHelperService;
+
+ private const int E_ABORT = -2147467260;
+ private const string COMMAND_NEXT_WORD = "Edit.WordNext";
+ private const string COMMAND_SELECT_WORD = "Edit.SelectCurrentWord";
+
+ #endregion
+
+ public SurroundWithFormatterService(IShellSelectionService shellSelectionService, IShellHelperService shellHelperService)
+ {
+ _shellSelectionService = shellSelectionService;
+ _shellHelperService = shellHelperService;
+ }
+
+ #region ISurroundWithFormatterService Members
+
+ ///
+ /// Formats surround with according to provided model.
+ ///
+ public void Format(SurroundWithLanguageModel model)
+ {
+ ThreadHelper.ThrowIfNotOnUIThread();
+
+ if (model == null)
+ throw new ArgumentNullException(nameof(model));
+
+ Document activeDocument = _shellSelectionService.GetActiveDocument() as Document;
+ if (activeDocument == null)
+ return;
+
+ TextSelection selection = activeDocument.Selection as TextSelection;
+ if (selection == null)
+ return;
+
+ TextRanges colRanges = selection.TextRanges;
+ TextRange textRangeStart = colRanges.Item(1);
+ TextRange textRangeEnd = colRanges.Item(colRanges.Count);
+ EditPoint ptSelectionStart;
+ EditPoint ptSelectionEnd;
+ bool addLastLineBreak;
+ string firstLinePrefix;
+
+ try
+ {
+ if ((selection.TopPoint.Line == selection.BottomPoint.Line) &&
+ (selection.TopPoint.LineCharOffset == selection.BottomPoint.LineCharOffset))
+ {
+ // No selection case
+ firstLinePrefix = string.Empty;
+
+ EditPoint ptWork = textRangeStart.StartPoint.CreateEditPoint();
+ ptWork.EndOfLine();
+ if (ptWork.LineLength != 0)
+ ptWork.Insert(Environment.NewLine);
+ ptSelectionStart = ptWork.CreateEditPoint();
+
+ ptWork.Insert(model.StartingCode);
+ if (!model.StartingCode.EndsWith(Environment.NewLine))
+ ptWork.Insert(Environment.NewLine);
+ ptWork.Insert(model.EndingCode);
+ ptSelectionEnd = ptWork.CreateEditPoint();
+ addLastLineBreak = (!ptSelectionEnd.AtEndOfLine);
+ }
+ else
+ {
+ ptSelectionStart = textRangeStart.StartPoint.CreateEditPoint();
+ ptSelectionEnd = textRangeEnd.EndPoint;
+ if ((textRangeEnd.StartPoint.Line == ptSelectionEnd.Line) &&
+ (textRangeEnd.StartPoint.LineCharOffset == ptSelectionEnd.LineCharOffset))
+ addLastLineBreak = true;
+ else
+ addLastLineBreak = false;
+
+ textRangeStart.StartPoint.Insert(model.StartingCode);
+ if (!model.StartingCode.EndsWith(Environment.NewLine))
+ textRangeStart.StartPoint.Insert(Environment.NewLine);
+ if ((ptSelectionEnd.AtEndOfLine) && (!ptSelectionEnd.AtStartOfLine))
+ ptSelectionEnd.Insert(Environment.NewLine);
+ ptSelectionEnd.Insert(model.EndingCode);
+ }
+
+ if (addLastLineBreak)
+ ptSelectionEnd.Insert(Environment.NewLine);
+ }
+ catch (Exception ex)
+ {
+ if ((ex is COMException comEx) && (comEx.ErrorCode == E_ABORT))
+ return;
+ else
+ throw;
+ }
+
+ selection.MoveToPoint(ptSelectionStart, false);
+ selection.MoveToPoint(ptSelectionEnd, true);
+ selection.SmartFormat();
+
+ // Jump to the element first line/column
+ selection.MoveToPoint(ptSelectionStart, false);
+ selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText, false);
+
+ // Select a word to be filled out
+ if (model.WordOffset > 0)
+ {
+ for (int i = 1; i <= model.WordOffset; i++)
+ {
+ _shellHelperService.ExecuteCommand(COMMAND_NEXT_WORD, string.Empty);
+ }
+
+ _shellHelperService.ExecuteCommand(COMMAND_SELECT_WORD, string.Empty);
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/DPackRx/source.extension.vsixmanifest b/DPackRx/source.extension.vsixmanifest
index de749a0..11fafdd 100644
--- a/DPackRx/source.extension.vsixmanifest
+++ b/DPackRx/source.extension.vsixmanifest
@@ -1,13 +1,14 @@
-
+
DPack Rx 2022
FREE tools collection designed to greatly increase developer's productivity, automate repetitive processes and expand upon some of Microsoft Visual Studio features.
https://github.com/sergey-visual-studio/dpack
Resources\Package.ico
Resources\Preview.png
Code, Coding, Tools, Productivity, DPack
+ true