diff --git a/CHANGELOG.md b/CHANGELOG.md index 866c3ae0..c55edabe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,32 @@ # Changelog -## vNext (TBD) +## vNext (10.2) -These changes have not been released to the official Visual Studio extension gallery, but (if checked) are available in preview within the [CI build](http://vsixgallery.com/extension/4c82e17d-927e-42d2-8460-b473ac7df316/). +These changes have not been released to the Visual Studio marketplace, but (if checked) are available in preview within the [CI build](http://vsixgallery.com/extension/4c82e17d-927e-42d2-8460-b473ac7df316/). -- [ ] TBD +- [x] Features + +- [x] Fixes ## Previous Releases -These are the changes to each version that has been released to the official Visual Studio extension gallery. +These are the changes to each version that has been released to the Visual Studio marketplace. + +## 10.2 + +**2017-01-01** + +- [x] Features + - [x] [#284](https://github.com/codecadwallader/codemaid/issues/284) - Performance improvements to compiling regular expressions - thanks [flagbug](https://github.com/flagbug)! + - [x] [#298](https://github.com/codecadwallader/codemaid/issues/298) - First class support for VB regions (viewing, inserting and removing) + - [x] [#337](https://github.com/codecadwallader/codemaid/issues/337) - Reorganizing: Add option to put explicit interface implementations after other members - thanks [samcragg](https://github.com/samcragg)! + - [x] [#371](https://github.com/codecadwallader/codemaid/issues/371) - Support for VS2017 RC + +- [x] Fixes + - [x] [#290](https://github.com/codecadwallader/codemaid/issues/290) - Finding: When track active item is enabled an error can be displayed on invocation + - [x] [#315](https://github.com/codecadwallader/codemaid/issues/315) - Reorganizing: Explicit interface implementations may take multiple passes to get in stable order - thanks [samcragg](https://github.com/samcragg)! + - [x] [#326](https://github.com/codecadwallader/codemaid/issues/326) - Digging: VB comments were not visible + - [x] [#342](https://github.com/codecadwallader/codemaid/issues/342) - Digging: VB regions were not visible - thanks [aeab13](https://github.com/aeab13)! ## 10.1 diff --git a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/RemoveAndSortUsingStatements.cs b/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/RemoveAndSortUsingStatements.cs new file mode 100644 index 00000000..d85b0c6e --- /dev/null +++ b/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/RemoveAndSortUsingStatements.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System; + +namespace SteveCadwallader.CodeMaid.IntegrationTests.Cleaning.VisualStudio.Data +{ + public class Class + { + public String String { get; set; } + public StringBuilder StringBuilder { get; set; } + } +} \ No newline at end of file diff --git a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/RemoveAndSortUsingStatements_Cleaned.cs b/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/RemoveAndSortUsingStatements_Cleaned.cs new file mode 100644 index 00000000..ab2b8247 --- /dev/null +++ b/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/RemoveAndSortUsingStatements_Cleaned.cs @@ -0,0 +1,11 @@ +using System; +using System.Text; + +namespace SteveCadwallader.CodeMaid.IntegrationTests.Cleaning.VisualStudio.Data +{ + public class Class + { + public String String { get; set; } + public StringBuilder StringBuilder { get; set; } + } +} \ No newline at end of file diff --git a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/RemoveUnusedUsingStatements.cs b/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/RemoveUnusedUsingStatements.cs deleted file mode 100644 index 58dfb59c..00000000 --- a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/RemoveUnusedUsingStatements.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SteveCadwallader.CodeMaid.IntegrationTests.Cleaning.VisualStudio.Data -{ -} \ No newline at end of file diff --git a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/RemoveUnusedUsingStatements_Cleaned.cs b/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/RemoveUnusedUsingStatements_Cleaned.cs deleted file mode 100644 index 424e7cba..00000000 --- a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/RemoveUnusedUsingStatements_Cleaned.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace SteveCadwallader.CodeMaid.IntegrationTests.Cleaning.VisualStudio.Data -{ -} \ No newline at end of file diff --git a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/SortUsingStatements.cs b/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/SortUsingStatements.cs deleted file mode 100644 index f8a93d28..00000000 --- a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/SortUsingStatements.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; -using System; -using System.Collections.Generic; -using System.Text; -using System.Linq; - -namespace SteveCadwallader.CodeMaid.IntegrationTests.Cleaning.VisualStudio.Data -{ -} \ No newline at end of file diff --git a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/SortUsingStatements_Cleaned.cs b/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/SortUsingStatements_Cleaned.cs deleted file mode 100644 index 58dfb59c..00000000 --- a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/Data/SortUsingStatements_Cleaned.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SteveCadwallader.CodeMaid.IntegrationTests.Cleaning.VisualStudio.Data -{ -} \ No newline at end of file diff --git a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/ReinsertAfterRemoveUnusedUsingStatementsTests.cs b/CodeMaid.IntegrationTests/Cleaning/VisualStudio/ReinsertAfterRemoveUnusedUsingStatementsTests.cs index ab364c8f..eedbe2b1 100644 --- a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/ReinsertAfterRemoveUnusedUsingStatementsTests.cs +++ b/CodeMaid.IntegrationTests/Cleaning/VisualStudio/ReinsertAfterRemoveUnusedUsingStatementsTests.cs @@ -45,7 +45,7 @@ public void TestCleanup() [HostType("VS IDE")] public void CleaningVisualStudioReinsertAfterRemoveUnusedUsingStatements_RunsAsExpected() { - Settings.Default.Cleaning_RunVisualStudioRemoveUnusedUsingStatements = true; + Settings.Default.Cleaning_RunVisualStudioRemoveAndSortUsingStatements = true; Settings.Default.Cleaning_UsingStatementsToReinsertWhenRemovedExpression = "using System;||using System.Linq;"; TestOperations.ExecuteCommandAndVerifyResults(RunRemoveUnusedUsingStatements, _projectItem, @"Data\ReinsertAfterRemoveUnusedUsingStatements_Cleaned.cs"); @@ -55,7 +55,7 @@ public void CleaningVisualStudioReinsertAfterRemoveUnusedUsingStatements_RunsAsE [HostType("VS IDE")] public void CleaningVisualStudioReinsertAfterRemoveUnusedUsingStatements_DoesNothingWhenSettingIsDisabled() { - Settings.Default.Cleaning_RunVisualStudioRemoveUnusedUsingStatements = false; + Settings.Default.Cleaning_RunVisualStudioRemoveAndSortUsingStatements = false; Settings.Default.Cleaning_UsingStatementsToReinsertWhenRemovedExpression = "using System;||using System.Linq;"; TestOperations.ExecuteCommandAndVerifyNoChanges(RunRemoveUnusedUsingStatements, _projectItem); @@ -67,7 +67,7 @@ public void CleaningVisualStudioReinsertAfterRemoveUnusedUsingStatements_DoesNot private static void RunRemoveUnusedUsingStatements(Document document) { - _usingStatementCleanupLogic.RemoveUnusedUsingStatements(document.GetTextDocument()); + _usingStatementCleanupLogic.RemoveAndSortUsingStatements(document.GetTextDocument()); } #endregion Helpers diff --git a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/RemoveUnusedUsingStatementsTests.cs b/CodeMaid.IntegrationTests/Cleaning/VisualStudio/RemoveAndSortUsingStatementsTests.cs similarity index 58% rename from CodeMaid.IntegrationTests/Cleaning/VisualStudio/RemoveUnusedUsingStatementsTests.cs rename to CodeMaid.IntegrationTests/Cleaning/VisualStudio/RemoveAndSortUsingStatementsTests.cs index ec99c509..bb49da41 100644 --- a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/RemoveUnusedUsingStatementsTests.cs +++ b/CodeMaid.IntegrationTests/Cleaning/VisualStudio/RemoveAndSortUsingStatementsTests.cs @@ -8,9 +8,9 @@ namespace SteveCadwallader.CodeMaid.IntegrationTests.Cleaning.VisualStudio { [TestClass] - [DeploymentItem(@"Cleaning\VisualStudio\Data\RemoveUnusedUsingStatements.cs", "Data")] - [DeploymentItem(@"Cleaning\VisualStudio\Data\RemoveUnusedUsingStatements_Cleaned.cs", "Data")] - public class RemoveUnusedUsingStatementsTests + [DeploymentItem(@"Cleaning\VisualStudio\Data\RemoveAndSortUsingStatements.cs", "Data")] + [DeploymentItem(@"Cleaning\VisualStudio\Data\RemoveAndSortUsingStatements_Cleaned.cs", "Data")] + public class RemoveAndSortUsingStatementsTests { #region Setup @@ -28,7 +28,7 @@ public static void ClassInitialize(TestContext testContext) public void TestInitialize() { TestEnvironment.CommonTestInitialize(); - _projectItem = TestEnvironment.LoadFileIntoProject(@"Data\RemoveUnusedUsingStatements.cs"); + _projectItem = TestEnvironment.LoadFileIntoProject(@"Data\RemoveAndSortUsingStatements.cs"); } [TestCleanup] @@ -43,38 +43,38 @@ public void TestCleanup() [TestMethod] [HostType("VS IDE")] - public void CleaningVisualStudioRemoveUnusedUsingStatements_RunsAsExpected() + public void CleaningVisualStudioRemoveAndSortUsingStatements_RunsAsExpected() { - Settings.Default.Cleaning_RunVisualStudioRemoveUnusedUsingStatements = true; + Settings.Default.Cleaning_RunVisualStudioRemoveAndSortUsingStatements = true; - TestOperations.ExecuteCommandAndVerifyResults(RunRemoveUnusedUsingStatements, _projectItem, @"Data\RemoveUnusedUsingStatements_Cleaned.cs"); + TestOperations.ExecuteCommandAndVerifyResults(RunRemoveAndSortUsingStatements, _projectItem, @"Data\RemoveAndSortUsingStatements_Cleaned.cs"); } [TestMethod] [HostType("VS IDE")] - public void CleaningVisualStudioRemoveUnusedUsingStatements_DoesNothingOnSecondPass() + public void CleaningVisualStudioRemoveAndSortUsingStatements_DoesNothingOnSecondPass() { - Settings.Default.Cleaning_RunVisualStudioRemoveUnusedUsingStatements = true; + Settings.Default.Cleaning_RunVisualStudioRemoveAndSortUsingStatements = true; - TestOperations.ExecuteCommandTwiceAndVerifyNoChangesOnSecondPass(RunRemoveUnusedUsingStatements, _projectItem); + TestOperations.ExecuteCommandTwiceAndVerifyNoChangesOnSecondPass(RunRemoveAndSortUsingStatements, _projectItem); } [TestMethod] [HostType("VS IDE")] - public void CleaningVisualStudioRemoveUnusedUsingStatements_DoesNothingWhenSettingIsDisabled() + public void CleaningVisualStudioRemoveAndSortUsingStatements_DoesNothingWhenSettingIsDisabled() { - Settings.Default.Cleaning_RunVisualStudioRemoveUnusedUsingStatements = false; + Settings.Default.Cleaning_RunVisualStudioRemoveAndSortUsingStatements = false; - TestOperations.ExecuteCommandAndVerifyNoChanges(RunRemoveUnusedUsingStatements, _projectItem); + TestOperations.ExecuteCommandAndVerifyNoChanges(RunRemoveAndSortUsingStatements, _projectItem); } #endregion Tests #region Helpers - private static void RunRemoveUnusedUsingStatements(Document document) + private static void RunRemoveAndSortUsingStatements(Document document) { - _usingStatementCleanupLogic.RemoveUnusedUsingStatements(document.GetTextDocument()); + _usingStatementCleanupLogic.RemoveAndSortUsingStatements(document.GetTextDocument()); } #endregion Helpers diff --git a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/SortUsingStatementsTests.cs b/CodeMaid.IntegrationTests/Cleaning/VisualStudio/SortUsingStatementsTests.cs deleted file mode 100644 index 95a26724..00000000 --- a/CodeMaid.IntegrationTests/Cleaning/VisualStudio/SortUsingStatementsTests.cs +++ /dev/null @@ -1,81 +0,0 @@ -using EnvDTE; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SteveCadwallader.CodeMaid.IntegrationTests.Helpers; -using SteveCadwallader.CodeMaid.Logic.Cleaning; -using SteveCadwallader.CodeMaid.Properties; - -namespace SteveCadwallader.CodeMaid.IntegrationTests.Cleaning.VisualStudio -{ - [TestClass] - [DeploymentItem(@"Cleaning\VisualStudio\Data\SortUsingStatements.cs", "Data")] - [DeploymentItem(@"Cleaning\VisualStudio\Data\SortUsingStatements_Cleaned.cs", "Data")] - public class SortUsingStatementsTests - { - #region Setup - - private static UsingStatementCleanupLogic _usingStatementCleanupLogic; - private ProjectItem _projectItem; - - [ClassInitialize] - public static void ClassInitialize(TestContext testContext) - { - _usingStatementCleanupLogic = UsingStatementCleanupLogic.GetInstance(TestEnvironment.Package); - Assert.IsNotNull(_usingStatementCleanupLogic); - } - - [TestInitialize] - public void TestInitialize() - { - TestEnvironment.CommonTestInitialize(); - _projectItem = TestEnvironment.LoadFileIntoProject(@"Data\SortUsingStatements.cs"); - } - - [TestCleanup] - public void TestCleanup() - { - TestEnvironment.RemoveFromProject(_projectItem); - } - - #endregion Setup - - #region Tests - - [TestMethod] - [HostType("VS IDE")] - public void CleaningVisualStudioSortUsingStatements_RunsAsExpected() - { - Settings.Default.Cleaning_RunVisualStudioSortUsingStatements = true; - - TestOperations.ExecuteCommandAndVerifyResults(RunSortUsingStatements, _projectItem, @"Data\SortUsingStatements_Cleaned.cs"); - } - - [TestMethod] - [HostType("VS IDE")] - public void CleaningVisualStudioSortUsingStatements_DoesNothingOnSecondPass() - { - Settings.Default.Cleaning_RunVisualStudioSortUsingStatements = true; - - TestOperations.ExecuteCommandTwiceAndVerifyNoChangesOnSecondPass(RunSortUsingStatements, _projectItem); - } - - [TestMethod] - [HostType("VS IDE")] - public void CleaningVisualStudioSortUsingStatements_DoesNothingWhenSettingIsDisabled() - { - Settings.Default.Cleaning_RunVisualStudioSortUsingStatements = false; - - TestOperations.ExecuteCommandAndVerifyNoChanges(RunSortUsingStatements, _projectItem); - } - - #endregion Tests - - #region Helpers - - private static void RunSortUsingStatements(Document document) - { - _usingStatementCleanupLogic.SortUsingStatements(); - } - - #endregion Helpers - } -} \ No newline at end of file diff --git a/CodeMaid.IntegrationTests/CodeMaid.IntegrationTests.csproj b/CodeMaid.IntegrationTests/CodeMaid.IntegrationTests.csproj index b0edf899..43f24d47 100644 --- a/CodeMaid.IntegrationTests/CodeMaid.IntegrationTests.csproj +++ b/CodeMaid.IntegrationTests/CodeMaid.IntegrationTests.csproj @@ -243,16 +243,10 @@ - + PreserveNewest - - PreserveNewest - - - PreserveNewest - - + PreserveNewest @@ -284,8 +278,7 @@ - - + diff --git a/CodeMaid.UnitTests/CodeMaid.UnitTests.csproj b/CodeMaid.UnitTests/CodeMaid.UnitTests.csproj index 05829ade..76d3c141 100644 --- a/CodeMaid.UnitTests/CodeMaid.UnitTests.csproj +++ b/CodeMaid.UnitTests/CodeMaid.UnitTests.csproj @@ -80,11 +80,35 @@ False ..\lib\Microsoft.VSSDK.UnitTestLibrary.dll + + ..\packages\NSubstitute.1.10.0.0\lib\net45\NSubstitute.dll + True + + + + {80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2} + 8 + 0 + 0 + primary + False + False + + + {1A31287A-4D7D-413E-8E32-3B374931BD89} + 8 + 0 + 0 + primary + False + False + + Properties\GlobalAssemblyInfo.cs @@ -97,6 +121,7 @@ + @@ -116,6 +141,7 @@ Properties\CodeMaid.snk + diff --git a/CodeMaid.UnitTests/Helpers/CodeItemTypeComparerTests.cs b/CodeMaid.UnitTests/Helpers/CodeItemTypeComparerTests.cs new file mode 100644 index 00000000..f8471836 --- /dev/null +++ b/CodeMaid.UnitTests/Helpers/CodeItemTypeComparerTests.cs @@ -0,0 +1,98 @@ +using EnvDTE80; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NSubstitute; +using SteveCadwallader.CodeMaid.Helpers; +using SteveCadwallader.CodeMaid.Model.CodeItems; +using SteveCadwallader.CodeMaid.Properties; + +namespace SteveCadwallader.CodeMaid.UnitTests.Helpers +{ + [TestClass] + public class CodeItemTypeComparerTests + { + [TestInitialize] + public void TestInitialize() + { + Settings.Default.Reset(); + } + + [TestMethod] + public void ShouldSortItemsOfTheSameTypeByName() + { + BaseCodeItem itemB = Create("b", 1); + BaseCodeItem itemA = Create("a", 2); + var comparer = new CodeItemTypeComparer(sortByName: true); + + int result = comparer.Compare(itemA, itemB); + + Assert.IsTrue(result < 0); + } + + [TestMethod] + public void ShouldSortItemsOfTheSameTypeByOffset() + { + BaseCodeItem itemB = Create("b", 1); + BaseCodeItem itemA = Create("a", 2); + var comparer = new CodeItemTypeComparer(sortByName: false); + + int result = comparer.Compare(itemA, itemB); + + Assert.IsTrue(result > 0); + } + + [TestMethod] + public void ShouldSortByGroupType() + { + BaseCodeItem method = Create("a", 1); + BaseCodeItem field = Create("z", 2); + var comparer = new CodeItemTypeComparer(sortByName: true); + + int result = comparer.Compare(field, method); + + Assert.IsTrue(result < 0); + } + + [TestMethod] + public void ShouldSortByExplicitInterfaceMemberName() + { + CodeItemMethod methodZ = CreateExplicitMethod("Interface", "Z", 1); + BaseCodeItem methodX = Create("X", 2); + var comparer = new CodeItemTypeComparer(sortByName: true); + + Settings.Default.Reorganizing_ExplicitMembersAtEnd = false; + int result = comparer.Compare(methodX, methodZ); + + Assert.IsTrue(result < 0); + } + + [TestMethod] + public void ShouldPlaceExplicitInterfaceMembersAtTheEndOfTheGroup() + { + CodeItemMethod methodA = CreateExplicitMethod("Interface", "A", 1); + BaseCodeItem methodB = Create("B", 2); + var comparer = new CodeItemTypeComparer(sortByName: true); + + Settings.Default.Reorganizing_ExplicitMembersAtEnd = true; + int result = comparer.Compare(methodB, methodA); + + Assert.IsTrue(result < 0); + } + + private static T Create(string name, int offset) where T : BaseCodeItem, new() + { + return new T + { + Name = name, + StartOffset = offset + }; + } + + private static CodeItemMethod CreateExplicitMethod(string interfaceName, string methodName, int offset) + { + CodeItemMethod method = Create(interfaceName + "." + methodName, offset); + method.CodeFunction = Substitute.For(); + method.CodeFunction.Name = method.Name; + return method; + } + } +} diff --git a/CodeMaid.UnitTests/SpadeTest.cs b/CodeMaid.UnitTests/SpadeTest.cs index ab608399..02f52f6a 100644 --- a/CodeMaid.UnitTests/SpadeTest.cs +++ b/CodeMaid.UnitTests/SpadeTest.cs @@ -6,6 +6,8 @@ namespace SteveCadwallader.CodeMaid.UnitTests { [TestClass] + [Ignore] + //TODO: Disabled while experimenting with VS2017 RC. public class SpadeTest { [TestMethod] diff --git a/CodeMaid.UnitTests/packages.config b/CodeMaid.UnitTests/packages.config new file mode 100644 index 00000000..04628968 --- /dev/null +++ b/CodeMaid.UnitTests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/CodeMaid.sln b/CodeMaid.sln index 74e667c6..c0232b9a 100644 --- a/CodeMaid.sln +++ b/CodeMaid.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.24720.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.25928.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{69127706-88D9-4314-B801-4FB2E615B700}" ProjectSection(SolutionItems) = preProject diff --git a/CodeMaid/CodeMaid.csproj b/CodeMaid/CodeMaid.csproj index cc83e37a..bdbca564 100644 --- a/CodeMaid/CodeMaid.csproj +++ b/CodeMaid/CodeMaid.csproj @@ -14,12 +14,13 @@ True ..\CodeMaid.snk v4.5 - 14.0 + 15.0 12.0 + false publish\ true Disk @@ -32,7 +33,6 @@ true 0 1.0.0.%2a - false false true @@ -194,6 +194,7 @@ + @@ -206,6 +207,7 @@ + diff --git a/CodeMaid/CodeMaid.csproj.user b/CodeMaid/CodeMaid.csproj.user index b82d1dcd..f8b1055c 100644 --- a/CodeMaid/CodeMaid.csproj.user +++ b/CodeMaid/CodeMaid.csproj.user @@ -2,7 +2,7 @@ Program - C:\Program Files %28x86%29\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe + C:\Program Files %28x86%29\Microsoft Visual Studio\2017\Community\Common7\IDE\devenv.exe /rootsuffix Exp diff --git a/CodeMaid/Helpers/CodeCommentHelper.cs b/CodeMaid/Helpers/CodeCommentHelper.cs index b050861e..d65e0018 100644 --- a/CodeMaid/Helpers/CodeCommentHelper.cs +++ b/CodeMaid/Helpers/CodeCommentHelper.cs @@ -141,7 +141,7 @@ internal static Regex GetCommentRegex(CodeLanguage codeLanguage, bool includePre } var pattern = string.Format(@"^{0}(?(?[\t ]*)(?[-=\*\+]+[ \t]*|\w+[\):][ \t]+|\d+\.[ \t]+)?((?[^\t\r\n ]+)*[\t ]*)*)[\r]*[\n]?$", prefix); - return new Regex(pattern, RegexOptions.Compiled | RegexOptions.ExplicitCapture | RegexOptions.Multiline); + return new Regex(pattern, RegexOptions.ExplicitCapture | RegexOptions.Multiline); } internal static int GetTabSize(CodeMaidPackage package, TextDocument document) @@ -163,7 +163,7 @@ internal static int GetTabSize(CodeMaidPackage package, TextDocument document) internal static bool IsCommentLine(EditPoint point) { - return LineMatchesRegex(point, GetCommentRegex(point.Parent.GetCodeLanguage())).Success; + return LineMatchesRegex(point, GetCommentRegex(point.GetCodeLanguage())).Success; } internal static Match LineMatchesRegex(EditPoint point, Regex regex) diff --git a/CodeMaid/Helpers/CodeItemTypeComparer.cs b/CodeMaid/Helpers/CodeItemTypeComparer.cs index 545303e9..891fd1e8 100644 --- a/CodeMaid/Helpers/CodeItemTypeComparer.cs +++ b/CodeMaid/Helpers/CodeItemTypeComparer.cs @@ -10,6 +10,25 @@ namespace SteveCadwallader.CodeMaid.Helpers /// public class CodeItemTypeComparer : Comparer { + #region Fields + + private readonly bool _sortByName; + + #endregion Fields + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// Determines whether a secondary sort by name is performed or not. + public CodeItemTypeComparer(bool sortByName) + { + _sortByName = sortByName; + } + + #endregion Constructors + #region Methods /// @@ -31,9 +50,9 @@ public override int Compare(BaseCodeItem x, BaseCodeItem y) if (first == second) { // Check if secondary sort by name should occur. - if (Settings.Default.Digging_SecondarySortTypeByName) + if (_sortByName) { - int nameComparison = x.Name.CompareTo(y.Name); + int nameComparison = NormalizeName(x).CompareTo(NormalizeName(y)); if (nameComparison != 0) { return nameComparison; @@ -47,15 +66,11 @@ public override int Compare(BaseCodeItem x, BaseCodeItem y) return first.CompareTo(second); } - /// - /// Calculates an ordered numeric representation of the specified code item. - /// - /// The code item. - /// A numeric representation. - public static int CalculateNumericRepresentation(BaseCodeItem codeItem) + private static int CalculateNumericRepresentation(BaseCodeItem codeItem) { int typeOffset = CalculateTypeOffset(codeItem); int accessOffset = CalculateAccessOffset(codeItem); + int explicitOffset = CalculateExplicitInterfaceOffset(codeItem); int constantOffset = CalculateConstantOffset(codeItem); int staticOffset = CalculateStaticOffset(codeItem); int readOnlyOffset = CalculateReadOnlyOffset(codeItem); @@ -64,16 +79,16 @@ public static int CalculateNumericRepresentation(BaseCodeItem codeItem) if (!Settings.Default.Reorganizing_PrimaryOrderByAccessLevel) { - calc += typeOffset * 10000; - calc += accessOffset * 1000; + calc += typeOffset * 100000; + calc += accessOffset * 10000; } else { - calc += accessOffset * 10000; - calc += typeOffset * 1000; + calc += accessOffset * 100000; + calc += typeOffset * 10000; } - calc += (constantOffset * 100) + (staticOffset * 10) + readOnlyOffset; + calc += (explicitOffset * 1000) + (constantOffset * 100) + (staticOffset * 10) + readOnlyOffset; return calc; } @@ -115,6 +130,20 @@ private static int CalculateAccessOffset(BaseCodeItem codeItem) } } + private static int CalculateExplicitInterfaceOffset(BaseCodeItem codeItem) + { + if (Settings.Default.Reorganizing_ExplicitMembersAtEnd) + { + var interfaceItem = codeItem as IInterfaceItem; + if ((interfaceItem != null) && interfaceItem.IsExplicitInterfaceImplementation) + { + return 1; + } + } + + return 0; + } + private static int CalculateConstantOffset(BaseCodeItem codeItem) { var codeItemField = codeItem as CodeItemField; @@ -139,6 +168,23 @@ private static int CalculateReadOnlyOffset(BaseCodeItem codeItem) return codeItemField.IsReadOnly ? 0 : 1; } + private static string NormalizeName(BaseCodeItem codeItem) + { + string name = codeItem.Name; + var interfaceItem = codeItem as IInterfaceItem; + if ((interfaceItem != null) && interfaceItem.IsExplicitInterfaceImplementation) + { + // Try to find where the interface ends and the method starts + int dot = name.LastIndexOf('.') + 1; + if (0 < dot && dot < name.Length) + { + return name.Substring(dot); + } + } + + return name; + } + #endregion Methods } } \ No newline at end of file diff --git a/CodeMaid/Helpers/CommandHelper.cs b/CodeMaid/Helpers/CommandHelper.cs index b8edf080..9127735b 100644 --- a/CodeMaid/Helpers/CommandHelper.cs +++ b/CodeMaid/Helpers/CommandHelper.cs @@ -1,4 +1,5 @@ -using EnvDTE; +using System; +using EnvDTE; using System.Linq; namespace SteveCadwallader.CodeMaid.Helpers @@ -56,6 +57,42 @@ public Command FindCommand(params string[] commandNames) return _package.IDE.Commands.OfType().FirstOrDefault(x => commandNames.Contains(x.Name)); } + /// + /// Finds a command by the specified guid/id pair. + /// + /// The command guid. + /// The command id. + /// The found command, otherwise null. + public Command FindCommand(string guid, int id) + { + return _package.IDE.Commands.OfType().FirstOrDefault(x => x.Guid == guid && x.ID == id); + } + + /// + /// Executes the specified command when available against the specified text document. + /// + /// The text document to cleanup. + /// The cleanup command name(s). + public void ExecuteCommand(TextDocument textDocument, params string[] commandNames) + { + try + { + var command = FindCommand(commandNames); + if (command != null && command.IsAvailable) + { + using (new CursorPositionRestorer(textDocument)) + { + _package.IDE.ExecuteCommand(command.Name, string.Empty); + } + } + } + catch (Exception ex) + { + // OK if fails, not available for some file types. + OutputWindowHelper.DiagnosticWriteLine($"Unable to execute command(s) {string.Join(",", commandNames)} on {textDocument.Parent.FullName}", ex); + } + } + #endregion Methods } } \ No newline at end of file diff --git a/CodeMaid/Helpers/EditPointExtensions.cs b/CodeMaid/Helpers/EditPointExtensions.cs index 02cc67ba..98dd7196 100644 --- a/CodeMaid/Helpers/EditPointExtensions.cs +++ b/CodeMaid/Helpers/EditPointExtensions.cs @@ -7,6 +7,16 @@ namespace SteveCadwallader.CodeMaid.Helpers /// internal static class EditPointExtensions { + /// + /// Gets the for this edit point. + /// + /// The edit point. + /// A . + internal static CodeLanguage GetCodeLanguage(this EditPoint editPoint) + { + return editPoint.Parent.GetCodeLanguage(); + } + /// /// Gets the text for the line where the edit point is located. /// diff --git a/CodeMaid/Helpers/RegionHelper.cs b/CodeMaid/Helpers/RegionHelper.cs new file mode 100644 index 00000000..f987097b --- /dev/null +++ b/CodeMaid/Helpers/RegionHelper.cs @@ -0,0 +1,82 @@ +using EnvDTE; +using System; + +namespace SteveCadwallader.CodeMaid.Helpers +{ + /// + /// A static helper class for working with regions. + /// + internal static class RegionHelper + { + #region Internal Methods + + internal static string GetRegionName(EditPoint editPoint, string regionText) + { + var codeLanguage = editPoint.GetCodeLanguage(); + switch (codeLanguage) + { + case CodeLanguage.CSharp: + return regionText.Substring(8).Trim(); + + case CodeLanguage.VisualBasic: + // Remove the leading/trailing double quote character. + var text = regionText.Substring(8).Trim(); + text = text.Substring(1, text.Length - 2); + return text; + + default: + throw new NotImplementedException($"Regions are not supported for '{codeLanguage}'."); + } + } + + internal static string GetRegionTagText(EditPoint editPoint, string name = null) + { + var codeLanguage = editPoint.GetCodeLanguage(); + switch (codeLanguage) + { + case CodeLanguage.CSharp: + return "#region " + + (name ?? string.Empty); + + case CodeLanguage.VisualBasic: + return "#Region " + + (name != null ? $"\"{name}\"" : string.Empty); + + default: + throw new NotImplementedException($"Regions are not supported for '{codeLanguage}'."); + } + } + + internal static string GetEndRegionTagText(EditPoint editPoint) + { + var codeLanguage = editPoint.GetCodeLanguage(); + switch (codeLanguage) + { + case CodeLanguage.CSharp: + return "#endregion"; + + case CodeLanguage.VisualBasic: + return "#End Region"; + + default: + throw new NotImplementedException($"Regions are not supported for '{codeLanguage}'."); + } + } + + internal static bool LanguageSupportsUpdatingEndRegionDirectives(EditPoint editPoint) + { + var codeLanguage = editPoint.GetCodeLanguage(); + + switch (codeLanguage) + { + case CodeLanguage.CSharp: + return true; + + default: + return false; + } + } + + #endregion Internal Methods + } +} \ No newline at end of file diff --git a/CodeMaid/Integration/Commands/FindInSolutionExplorerCommand.cs b/CodeMaid/Integration/Commands/FindInSolutionExplorerCommand.cs index 18b9918a..67841698 100644 --- a/CodeMaid/Integration/Commands/FindInSolutionExplorerCommand.cs +++ b/CodeMaid/Integration/Commands/FindInSolutionExplorerCommand.cs @@ -11,6 +11,12 @@ namespace SteveCadwallader.CodeMaid.Integration.Commands /// internal class FindInSolutionExplorerCommand : BaseCommand { + #region Fields + + private readonly CommandHelper _commandHelper; + + #endregion Fields + #region Constructors /// @@ -21,6 +27,7 @@ internal FindInSolutionExplorerCommand(CodeMaidPackage package) : base(package, new CommandID(PackageGuids.GuidCodeMaidCommandFindInSolutionExplorer, PackageIds.CmdIDCodeMaidFindInSolutionExplorer)) { + _commandHelper = CommandHelper.GetInstance(package); } #endregion Constructors @@ -50,12 +57,23 @@ protected override void OnExecute() ToggleSolutionFoldersOpenTemporarily(UIHierarchyHelper.GetTopUIHierarchyItem(Package)); } - //Note: Instead of directly invoking the command by name, we are using the GUID/ID pair. - // This is a workaround for the canonical name being undefined in Spanish versions of Visual Studio. - object customIn = null; - object customOut = null; - Package.IDE.Commands.Raise("{D63DB1F0-404E-4B21-9648-CA8D99245EC3}", 36, ref customIn, ref customOut); - //Package.IDE.ExecuteCommand("SolutionExplorer.SyncWithActiveDocument", String.Empty); + // Instead of directly using "SolutionExplorer.SyncWithActiveDocument" we are using + // the GUID/ID pair. This is a workaround for the canonical name being undefined in + // Spanish versions of Visual Studio. + var command = _commandHelper.FindCommand("{D63DB1F0-404E-4B21-9648-CA8D99245EC3}", 36); + if (command != null && command.IsAvailable) + { + object customIn = null; + object customOut = null; + Package.IDE.Commands.Raise(command.Guid, command.ID, ref customIn, ref customOut); + } + else + { + // The command will be unavailable if track active item is selected, and in those + // scenarios we just want to activate the solution explorer since the right item + // will already be highlighted. + Package.IDE.ExecuteCommand("View.SolutionExplorer", string.Empty); + } } } diff --git a/CodeMaid/Integration/Commands/SpadeContextInsertRegionCommand.cs b/CodeMaid/Integration/Commands/SpadeContextInsertRegionCommand.cs index 3d265b89..8baaf5a2 100644 --- a/CodeMaid/Integration/Commands/SpadeContextInsertRegionCommand.cs +++ b/CodeMaid/Integration/Commands/SpadeContextInsertRegionCommand.cs @@ -47,8 +47,9 @@ protected override void OnBeforeQueryStatus() var spade = Package.Spade; if (spade?.Document != null) { - visible = spade.Document.GetCodeLanguage() == CodeLanguage.CSharp && - spade.SelectedItems.Count() >= 2; + visible = spade.SelectedItems.Count() >= 2 && + (spade.Document.GetCodeLanguage() == CodeLanguage.CSharp || + spade.Document.GetCodeLanguage() == CodeLanguage.VisualBasic); } Visible = visible; @@ -80,6 +81,13 @@ protected override void OnExecute() // Highlight the line of text for renaming. var textDocument = spade.Document.GetTextDocument(); textDocument.Selection.EndOfLine(true); + + // Move back one character for VB to offset the double quote character. + if (textDocument.GetCodeLanguage() == CodeLanguage.VisualBasic) + { + textDocument.Selection.CharLeft(true); + } + textDocument.Selection.SwapAnchor(); }); diff --git a/CodeMaid/Integration/Images/about.png b/CodeMaid/Integration/Images/about.png index 5d2f7607..7b7ecea3 100644 Binary files a/CodeMaid/Integration/Images/about.png and b/CodeMaid/Integration/Images/about.png differ diff --git a/CodeMaid/Integration/Images/about.xcf b/CodeMaid/Integration/Images/about.xcf index d0a45210..02b18a14 100644 Binary files a/CodeMaid/Integration/Images/about.xcf and b/CodeMaid/Integration/Images/about.xcf differ diff --git a/CodeMaid/Logic/Cleaning/CodeCleanupManager.cs b/CodeMaid/Logic/Cleaning/CodeCleanupManager.cs index 44232c35..dd0f99c3 100644 --- a/CodeMaid/Logic/Cleaning/CodeCleanupManager.cs +++ b/CodeMaid/Logic/Cleaning/CodeCleanupManager.cs @@ -231,8 +231,7 @@ private void RunCodeCleanupCSharp(Document document) RunExternalFormatting(textDocument); if (!document.IsExternal()) { - _usingStatementCleanupLogic.RemoveUnusedUsingStatements(textDocument); - _usingStatementCleanupLogic.SortUsingStatements(); + _usingStatementCleanupLogic.RemoveAndSortUsingStatements(textDocument); } // Interpret the document into a collection of elements. @@ -444,7 +443,7 @@ private void RunVisualStudioFormatDocument(TextDocument textDocument) { if (!Settings.Default.Cleaning_RunVisualStudioFormatDocumentCommand) return; - ExecuteCommand(textDocument, "Edit.FormatDocument"); + _commandHelper.ExecuteCommand(textDocument, "Edit.FormatDocument"); } /// @@ -457,8 +456,7 @@ private void RunJetBrainsReSharperCleanup(TextDocument textDocument) // This command changed to include the leading 'ReSharper.' in version 2016.1. // Execute both commands for backwards compatibility. - ExecuteCommand(textDocument, "ReSharper_SilentCleanupCode"); - ExecuteCommand(textDocument, "ReSharper.ReSharper_SilentCleanupCode"); + _commandHelper.ExecuteCommand(textDocument, "ReSharper_SilentCleanupCode", "ReSharper.ReSharper_SilentCleanupCode"); } /// @@ -469,7 +467,7 @@ private void RunTelerikJustCodeCleanup(TextDocument textDocument) { if (!Settings.Default.ThirdParty_UseTelerikJustCodeCleanup) return; - ExecuteCommand(textDocument, "JustCode.JustCode_CleanCodeWithDefaultProfile"); + _commandHelper.ExecuteCommand(textDocument, "JustCode.JustCode_CleanCodeWithDefaultProfile"); } /// @@ -480,7 +478,7 @@ private void RunXAMLStylerCleanup(TextDocument textDocument) { if (!Settings.Default.ThirdParty_UseXAMLStylerCleanup) return; - ExecuteCommand(textDocument, "EditorContextMenus.XAMLEditor.BeautifyXaml", "EditorContextMenus.XAMLEditor.FormatXAML"); + _commandHelper.ExecuteCommand(textDocument, "EditorContextMenus.XAMLEditor.BeautifyXaml", "EditorContextMenus.XAMLEditor.FormatXAML"); } /// @@ -493,31 +491,7 @@ private void RunOtherCleanupCommands(TextDocument textDocument) foreach (var commandName in _otherCleaningCommands.Value) { - ExecuteCommand(textDocument, commandName); - } - } - - /// - /// Executes the specified cleanup command when available against the specified text document. - /// - /// The text document to cleanup. - /// The cleanup command name(s). - private void ExecuteCommand(TextDocument textDocument, params string[] commandNames) - { - try - { - var command = _commandHelper.FindCommand(commandNames); - if (command != null && command.IsAvailable) - { - using (new CursorPositionRestorer(textDocument)) - { - _package.IDE.ExecuteCommand(command.Name, string.Empty); - } - } - } - catch - { - // OK if fails, not available for some file types. + _commandHelper.ExecuteCommand(textDocument, commandName); } } diff --git a/CodeMaid/Logic/Cleaning/RemoveRegionLogic.cs b/CodeMaid/Logic/Cleaning/RemoveRegionLogic.cs index 2bb92e42..5c764d83 100644 --- a/CodeMaid/Logic/Cleaning/RemoveRegionLogic.cs +++ b/CodeMaid/Logic/Cleaning/RemoveRegionLogic.cs @@ -62,7 +62,8 @@ internal bool CanRemoveRegions(Document document) { return _package.IDE.Debugger.CurrentMode == dbgDebugMode.dbgDesignMode && document != null && - document.GetCodeLanguage() == CodeLanguage.CSharp; + (document.GetCodeLanguage() == CodeLanguage.CSharp || + document.GetCodeLanguage() == CodeLanguage.VisualBasic); } /// diff --git a/CodeMaid/Logic/Cleaning/UsingStatementCleanupLogic.cs b/CodeMaid/Logic/Cleaning/UsingStatementCleanupLogic.cs index 2dfee9fa..8e4448d7 100644 --- a/CodeMaid/Logic/Cleaning/UsingStatementCleanupLogic.cs +++ b/CodeMaid/Logic/Cleaning/UsingStatementCleanupLogic.cs @@ -14,6 +14,7 @@ internal class UsingStatementCleanupLogic #region Fields private readonly CodeMaidPackage _package; + private readonly CommandHelper _commandHelper; private readonly CachedSettingSet _usingStatementsToReinsertWhenRemoved = new CachedSettingSet(() => Settings.Default.Cleaning_UsingStatementsToReinsertWhenRemovedExpression, @@ -49,6 +50,8 @@ internal static UsingStatementCleanupLogic GetInstance(CodeMaidPackage package) private UsingStatementCleanupLogic(CodeMaidPackage package) { _package = package; + + _commandHelper = CommandHelper.GetInstance(_package); } #endregion Constructors @@ -56,13 +59,16 @@ private UsingStatementCleanupLogic(CodeMaidPackage package) #region Methods /// - /// Run the visual studio built-in remove unused using statements command. + /// Run the visual studio built-in remove and sort using statements command. /// + /// + /// Before VS2017 these were two separate commands. Starting in VS2017 they were merged into one. + /// /// The text document to update. - public void RemoveUnusedUsingStatements(TextDocument textDocument) + public void RemoveAndSortUsingStatements(TextDocument textDocument) { - if (!Settings.Default.Cleaning_RunVisualStudioRemoveUnusedUsingStatements) return; - if (_package.IsAutoSaveContext && Settings.Default.Cleaning_SkipRemoveUnusedUsingStatementsDuringAutoCleanupOnSave) return; + if (!Settings.Default.Cleaning_RunVisualStudioRemoveAndSortUsingStatements) return; + if (_package.IsAutoSaveContext && Settings.Default.Cleaning_SkipRemoveAndSortUsingStatementsDuringAutoCleanupOnSave) return; // Capture all existing using statements that should be re-inserted if removed. const string patternFormat = @"^[ \t]*{0}[ \t]*\r?\n"; @@ -78,7 +84,15 @@ from editPoint in TextDocumentHelper.FindMatches(textDocument, string.Format(pat point.editPoint.CharRight(); } - _package.IDE.ExecuteCommand("Edit.RemoveUnusedUsings", string.Empty); + if (_package.IDEVersion >= 15) + { + _commandHelper.ExecuteCommand(textDocument, "Edit.RemoveAndSort"); + } + else + { + _commandHelper.ExecuteCommand(textDocument, "Edit.RemoveUnusedUsings"); + _commandHelper.ExecuteCommand(textDocument, "Edit.SortUsings"); + } // Check each using statement point and re-insert it if removed. foreach (var point in points) @@ -93,17 +107,6 @@ from editPoint in TextDocumentHelper.FindMatches(textDocument, string.Format(pat } } - /// - /// Run the visual studio built-in sort using statements command. - /// - public void SortUsingStatements() - { - if (!Settings.Default.Cleaning_RunVisualStudioSortUsingStatements) return; - if (_package.IsAutoSaveContext && Settings.Default.Cleaning_SkipSortUsingStatementsDuringAutoCleanupOnSave) return; - - _package.IDE.ExecuteCommand("Edit.SortUsings", string.Empty); - } - #endregion Methods } } \ No newline at end of file diff --git a/CodeMaid/Logic/Reorganizing/CodeReorganizationManager.cs b/CodeMaid/Logic/Reorganizing/CodeReorganizationManager.cs index ada6b3ce..8a825a04 100644 --- a/CodeMaid/Logic/Reorganizing/CodeReorganizationManager.cs +++ b/CodeMaid/Logic/Reorganizing/CodeReorganizationManager.cs @@ -364,9 +364,8 @@ private void RecursivelyReorganize(IEnumerable codeItems, ICodeIte // Get the items in their current order and their desired order. var currentOrder = GetReorganizableCodeItemElements(codeItems); - var desiredOrder = currentOrder.OrderBy(CodeItemTypeComparer.CalculateNumericRepresentation) - .ThenBy(x => Settings.Default.Reorganizing_AlphabetizeMembersOfTheSameGroup ? (object)x.Name : (object)x.StartOffset) - .ToList(); + var desiredOrder = new List(currentOrder); + desiredOrder.Sort(new CodeItemTypeComparer(Settings.Default.Reorganizing_AlphabetizeMembersOfTheSameGroup)); // Iterate across the items in the desired order, moving them when necessary. for (int desiredIndex = 0; desiredIndex < desiredOrder.Count; desiredIndex++) diff --git a/CodeMaid/Logic/Reorganizing/GenerateRegionLogic.cs b/CodeMaid/Logic/Reorganizing/GenerateRegionLogic.cs index ecfef840..ae4698e1 100644 --- a/CodeMaid/Logic/Reorganizing/GenerateRegionLogic.cs +++ b/CodeMaid/Logic/Reorganizing/GenerateRegionLogic.cs @@ -177,7 +177,7 @@ public EditPoint InsertRegionTag(CodeItemRegion region, EditPoint startPoint) cursor.Insert(Environment.NewLine); } - cursor.Insert($"#region {region.Name}{Environment.NewLine}"); + cursor.Insert($"{RegionHelper.GetRegionTagText(cursor, region.Name)}{Environment.NewLine}"); startPoint.SmartFormat(cursor); @@ -209,9 +209,10 @@ public EditPoint InsertEndRegionTag(CodeItemRegion region, EditPoint endPoint) cursor.Insert(Environment.NewLine); } - cursor.Insert("#endregion"); + cursor.Insert(RegionHelper.GetEndRegionTagText(cursor)); - if (Settings.Default.Cleaning_UpdateEndRegionDirectives) + if (Settings.Default.Cleaning_UpdateEndRegionDirectives && + RegionHelper.LanguageSupportsUpdatingEndRegionDirectives(cursor)) { cursor.Insert(" " + region.Name); } diff --git a/CodeMaid/Model/CodeItems/CodeItemEvent.cs b/CodeMaid/Model/CodeItems/CodeItemEvent.cs index a57a2cc6..78003dc6 100644 --- a/CodeMaid/Model/CodeItems/CodeItemEvent.cs +++ b/CodeMaid/Model/CodeItems/CodeItemEvent.cs @@ -8,7 +8,7 @@ namespace SteveCadwallader.CodeMaid.Model.CodeItems /// /// The representation of a code event. /// - public class CodeItemEvent : BaseCodeItemElement + public class CodeItemEvent : BaseCodeItemElement, IInterfaceItem { #region Fields diff --git a/CodeMaid/Model/CodeItems/CodeItemMethod.cs b/CodeMaid/Model/CodeItems/CodeItemMethod.cs index 3993e0fa..d11909bf 100644 --- a/CodeMaid/Model/CodeItems/CodeItemMethod.cs +++ b/CodeMaid/Model/CodeItems/CodeItemMethod.cs @@ -10,7 +10,7 @@ namespace SteveCadwallader.CodeMaid.Model.CodeItems /// /// The representation of a code method. /// - public class CodeItemMethod : BaseCodeItemElement, ICodeItemComplexity, ICodeItemParameters + public class CodeItemMethod : BaseCodeItemElement, ICodeItemComplexity, ICodeItemParameters, IInterfaceItem { #region Fields diff --git a/CodeMaid/Model/CodeItems/CodeItemProperty.cs b/CodeMaid/Model/CodeItems/CodeItemProperty.cs index 67c29c27..8277b5c6 100644 --- a/CodeMaid/Model/CodeItems/CodeItemProperty.cs +++ b/CodeMaid/Model/CodeItems/CodeItemProperty.cs @@ -10,7 +10,7 @@ namespace SteveCadwallader.CodeMaid.Model.CodeItems /// /// The representation of a code property. /// - public class CodeItemProperty : BaseCodeItemElement, ICodeItemComplexity, ICodeItemParameters + public class CodeItemProperty : BaseCodeItemElement, ICodeItemComplexity, ICodeItemParameters, IInterfaceItem { #region Fields diff --git a/CodeMaid/Model/CodeItems/IInterfaceItem.cs b/CodeMaid/Model/CodeItems/IInterfaceItem.cs new file mode 100644 index 00000000..7a58cdb1 --- /dev/null +++ b/CodeMaid/Model/CodeItems/IInterfaceItem.cs @@ -0,0 +1,13 @@ +namespace SteveCadwallader.CodeMaid.Model.CodeItems +{ + /// + /// Represents an item that can implement an interface member. + /// + public interface IInterfaceItem + { + /// + /// Gets a flag indicating if this is an explicit interface implementation. + /// + bool IsExplicitInterfaceImplementation { get; } + } +} diff --git a/CodeMaid/Model/CodeModelHelper.cs b/CodeMaid/Model/CodeModelHelper.cs index 23224442..391cb320 100644 --- a/CodeMaid/Model/CodeModelHelper.cs +++ b/CodeMaid/Model/CodeModelHelper.cs @@ -146,7 +146,7 @@ internal CodeItemRegion RetrieveCodeRegionUnderCursor(TextDocument textDocument) /// /// Gets the regular expression pattern for region matching. /// - private string RegionPattern => @"^[ \t]*#(region|endregion)"; + private string RegionPattern => @"^[ \t]*#([Rr]egion|endregion|End Region)"; #endregion Private Properties @@ -167,12 +167,12 @@ private static IEnumerable RetrieveCodeRegions(IEnumerable RetrieveCodeRegions(IEnumerable 0) { diff --git a/CodeMaid/Model/CodeTree/CodeTreeBuilder.cs b/CodeMaid/Model/CodeTree/CodeTreeBuilder.cs index bea28655..0774c0eb 100644 --- a/CodeMaid/Model/CodeTree/CodeTreeBuilder.cs +++ b/CodeMaid/Model/CodeTree/CodeTreeBuilder.cs @@ -1,5 +1,6 @@ using SteveCadwallader.CodeMaid.Helpers; using SteveCadwallader.CodeMaid.Model.CodeItems; +using SteveCadwallader.CodeMaid.Properties; using System; using System.Collections.Generic; using System.Linq; @@ -155,7 +156,7 @@ private static SetCodeItems OrganizeCodeItemsByTypeSortOrder(SetCodeItems rawCod organizedCodeItems.AddRange(structuredCodeItems); // Sort the list of code items by type recursively. - RecursivelySort(organizedCodeItems, new CodeItemTypeComparer()); + RecursivelySort(organizedCodeItems, new CodeItemTypeComparer(Settings.Default.Digging_SecondarySortTypeByName)); // Group the list of code items by type recursively. foreach (var codeItem in organizedCodeItems.OfType()) diff --git a/CodeMaid/Properties/Settings.Designer.cs b/CodeMaid/Properties/Settings.Designer.cs index 2493a67e..d78828b2 100644 --- a/CodeMaid/Properties/Settings.Designer.cs +++ b/CodeMaid/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace SteveCadwallader.CodeMaid.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.0.0.0")] public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -950,48 +950,24 @@ public bool Cleaning_RunVisualStudioFormatDocumentCommand { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool Cleaning_RunVisualStudioRemoveUnusedUsingStatements { + public bool Cleaning_RunVisualStudioRemoveAndSortUsingStatements { get { - return ((bool)(this["Cleaning_RunVisualStudioRemoveUnusedUsingStatements"])); + return ((bool)(this["Cleaning_RunVisualStudioRemoveAndSortUsingStatements"])); } set { - this["Cleaning_RunVisualStudioRemoveUnusedUsingStatements"] = value; + this["Cleaning_RunVisualStudioRemoveAndSortUsingStatements"] = value; } } [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool Cleaning_RunVisualStudioSortUsingStatements { + public bool Cleaning_SkipRemoveAndSortUsingStatementsDuringAutoCleanupOnSave { get { - return ((bool)(this["Cleaning_RunVisualStudioSortUsingStatements"])); + return ((bool)(this["Cleaning_SkipRemoveAndSortUsingStatementsDuringAutoCleanupOnSave"])); } set { - this["Cleaning_RunVisualStudioSortUsingStatements"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool Cleaning_SkipRemoveUnusedUsingStatementsDuringAutoCleanupOnSave { - get { - return ((bool)(this["Cleaning_SkipRemoveUnusedUsingStatementsDuringAutoCleanupOnSave"])); - } - set { - this["Cleaning_SkipRemoveUnusedUsingStatementsDuringAutoCleanupOnSave"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool Cleaning_SkipSortUsingStatementsDuringAutoCleanupOnSave { - get { - return ((bool)(this["Cleaning_SkipSortUsingStatementsDuringAutoCleanupOnSave"])); - } - set { - this["Cleaning_SkipSortUsingStatementsDuringAutoCleanupOnSave"] = value; + this["Cleaning_SkipRemoveAndSortUsingStatementsDuringAutoCleanupOnSave"] = value; } } @@ -1679,6 +1655,18 @@ public bool Reorganizing_AlphabetizeMembersOfTheSameGroup { } } + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool Reorganizing_ExplicitMembersAtEnd { + get { + return ((bool)(this["Reorganizing_ExplicitMembersAtEnd"])); + } + set { + this["Reorganizing_ExplicitMembersAtEnd"] = value; + } + } + [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Configuration.DefaultSettingValueAttribute("True")] diff --git a/CodeMaid/Properties/Settings.settings b/CodeMaid/Properties/Settings.settings index 19b6b12e..1f348587 100644 --- a/CodeMaid/Properties/Settings.settings +++ b/CodeMaid/Properties/Settings.settings @@ -233,18 +233,12 @@ True - + True - + True - - True - - - False - False @@ -416,6 +410,9 @@ True + + False + True diff --git a/CodeMaid/UI/Converters/DocCommentToStringConverter.cs b/CodeMaid/UI/Converters/DocCommentToStringConverter.cs index 5e9d1832..2e247140 100644 --- a/CodeMaid/UI/Converters/DocCommentToStringConverter.cs +++ b/CodeMaid/UI/Converters/DocCommentToStringConverter.cs @@ -31,9 +31,16 @@ public object Convert(object value, Type targetType, object parameter, System.Gl try { + // In VB .NET the returned XML doesn't have a tag so we add it to avoid a crash + // with multiple documentation tags. + if (!str.StartsWith("")) + { + str = "" + str + ""; + } + var xElement = XElement.Parse(str); - var summaryTag = xElement.Descendants("summary").FirstOrDefault(); + var summaryTag = xElement.DescendantsAndSelf("summary").FirstOrDefault(); if (summaryTag == null) return string.Empty; // Get the Inner XML for the summary tag. diff --git a/CodeMaid/UI/Dialogs/About/AboutWindow.xaml b/CodeMaid/UI/Dialogs/About/AboutWindow.xaml index e2f19cc7..df2e1dbc 100644 --- a/CodeMaid/UI/Dialogs/About/AboutWindow.xaml +++ b/CodeMaid/UI/Dialogs/About/AboutWindow.xaml @@ -67,7 +67,7 @@ Click="OnWebsiteLinkClick" ToolTip="Launch CodeMaid's website" />