├── TidyCSharp ├── Key.snk ├── Resources │ ├── icon.png │ └── Preview.png ├── Menus │ ├── Cleanup │ │ ├── CommandRunners │ │ │ ├── _Infra │ │ │ │ ├── ICodeCleaner.cs │ │ │ │ ├── CodeCleaner.cs │ │ │ │ ├── ICleanupOption.cs │ │ │ │ ├── CodeCleanerHost.cs │ │ │ │ └── OptionsBase.cs │ │ │ ├── SimplyAsyncCall │ │ │ │ └── Option │ │ │ │ │ ├── CleanupTypes.cs │ │ │ │ │ └── Options.cs │ │ │ ├── CamelCasedClassFields │ │ │ │ ├── Option │ │ │ │ │ ├── Options.cs │ │ │ │ │ └── CleanupTypes.cs │ │ │ │ └── CamelCasedFields.cs │ │ │ ├── PrivateModifierRemover │ │ │ │ ├── Option │ │ │ │ │ ├── Options.cs │ │ │ │ │ └── CleanupTypes.cs │ │ │ │ └── PrivateModifierRemover.cs │ │ │ ├── CamelCasedMethodVariable │ │ │ │ ├── Option │ │ │ │ │ ├── CleanupTypes.cs │ │ │ │ │ └── Options.cs │ │ │ │ └── CamelCasedLocalVariable.cs │ │ │ ├── Whitespace │ │ │ │ ├── Option │ │ │ │ │ ├── Options.cs │ │ │ │ │ └── CleanupTypes.cs │ │ │ │ ├── EndOFLineRewriter.cs │ │ │ │ ├── BlankLineRewriter.cs │ │ │ │ └── WhiteSpaceNormalizer.cs │ │ │ ├── RemoveExtraThisQualification │ │ │ │ ├── Option │ │ │ │ │ ├── Options.cs │ │ │ │ │ └── CleanupTypes.cs │ │ │ │ └── RemoveExtraThisQualification.cs │ │ │ ├── SimplifyClassFieldDeclarations │ │ │ │ └── Option │ │ │ │ │ ├── Options.cs │ │ │ │ │ └── CleanupTypes.cs │ │ │ ├── ConvertMembersToExpressionBodied │ │ │ │ └── Option │ │ │ │ │ ├── Options.cs │ │ │ │ │ └── CleanupTypes.cs │ │ │ ├── UsingDirectiveOrganizer.cs │ │ │ ├── ZebbleCleaner.cs │ │ │ ├── RemoveAttributeKeywork.cs │ │ │ ├── SimplifyVariableDeclarations.cs │ │ │ ├── SortClassMembers.cs │ │ │ └── ConvertFullNameTypesToBuiltInTypes.cs │ │ ├── TokenRemovers │ │ │ ├── IPrivateModiferTokenRemover.cs │ │ │ ├── FieldTokenRemover.cs │ │ │ ├── MethodTokenRemover.cs │ │ │ ├── PropertyTokenRemover.cs │ │ │ └── NestedClassTokenRemover.cs │ │ ├── CommandsHandlers │ │ │ ├── Infra │ │ │ │ ├── UI │ │ │ │ │ ├── CustomCheckBox.cs │ │ │ │ │ ├── CustomCheckListBox.Designer.cs │ │ │ │ │ ├── CustomCheckListBox.cs │ │ │ │ │ └── CleanupItemUserControl.Designer.cs │ │ │ │ ├── CheckBoxItemInfo.cs │ │ │ │ ├── IMainCleanup.cs │ │ │ │ ├── CleanupItemAttribute.cs │ │ │ │ ├── BaseCodeCleanupCommand.cs │ │ │ │ ├── ReadOnly │ │ │ │ │ └── ReadOnlyMainCleanup.cs │ │ │ │ ├── ExtendedBaseCodeCleanupCommand.cs │ │ │ │ └── CodeCleanerType.cs │ │ │ ├── ActionCustomCodeCleanup.cs │ │ │ ├── CodeCleanerFactory.cs │ │ │ ├── CleanupOptions.cs │ │ │ └── CleanupOptionForm.cs │ │ ├── SyntaxNodeTypeConverter │ │ │ └── SyntaxNodeConverter.cs │ │ ├── SyntaxNodeExtractors │ │ │ ├── ISyntaxTreeMemberExtractor.cs │ │ │ ├── VariableDeclaratorSyntaxExtractor.cs │ │ │ ├── SyntaxTriviaExtractor.cs │ │ │ ├── ArgumentListSyntaxExtractor.cs │ │ │ ├── FieldExtractor.cs │ │ │ ├── MethodExtractor.cs │ │ │ ├── PropertyExtractor.cs │ │ │ ├── NestedClassExtractor.cs │ │ │ ├── SyntaxNodeExtractor.cs │ │ │ └── InvocationExpressionExtractor.cs │ │ ├── Utils │ │ │ ├── RenameHelper │ │ │ │ ├── Renamer.RenameOutput.cs │ │ │ │ ├── Lib │ │ │ │ │ ├── ISyntaxWrapper.cs │ │ │ │ │ ├── SyntaxKindEx.cs │ │ │ │ │ ├── VariableDesignationSyntaxWrapper.cs │ │ │ │ │ ├── SyntaxWrapper.cs │ │ │ │ │ ├── SingleVariableDesignationSyntaxWrapper.cs │ │ │ │ │ └── Extensions.cs │ │ │ │ ├── ParameterRenamer.cs │ │ │ │ ├── VariableRenamer.cs │ │ │ │ ├── FieldRenamer.cs │ │ │ │ ├── CONSTRenamer.cs │ │ │ │ └── VariableRenamingBase.cs │ │ │ ├── ActiveDocument.cs │ │ │ ├── CleanupCSharpSyntaxRewriter.cs │ │ │ └── TypesMapItem.cs │ │ └── SyntaxNodeValidators │ │ │ ├── ExpressionStatementValidator.cs │ │ │ ├── ArgumentListSyntaxValidator.cs │ │ │ ├── MemberAccessExpressionValidator.cs │ │ │ ├── ClassDeclarationValidator.cs │ │ │ └── InvocationExpressionValidator.cs │ └── ActionsOnCSharp │ │ ├── CSharpActionDelegate.cs │ │ ├── DteServiceProvider.cs │ │ ├── ActionCSharpOnProjectItem.cs │ │ ├── ActionCSharpOnSolution.cs │ │ ├── ActionCSharpOnProject.cs │ │ └── ActionCSharpOnAnyWhere.cs ├── CommandConstants │ ├── PkgCmdID.cs │ └── Guids.cs ├── OptionsPage.cs ├── Properties │ ├── Settings.settings │ ├── AssemblyInfo.cs │ └── Settings.Designer.cs ├── TidyCSharp.GeneratedMSBuildEditorConfig.editorconfig ├── Utility │ ├── ProcessActions.cs │ ├── MessageBoxDisplay.cs │ ├── SolutionActions.cs │ └── Utils.cs ├── GlobalSuppressions.cs ├── Definition │ └── UsingsCommands.cs ├── Extensions │ ├── FileExtensions.cs │ ├── DteExtensions.cs │ └── RunCodeAnalysisRulesCommand.cs ├── Environment │ ├── App.cs │ └── ErrorList.cs ├── Settings │ └── GlobalSettings.cs ├── app.config ├── source.extension.vsixmanifest ├── ErrorNotification │ └── ErrorNotification.cs ├── Resources.Designer.cs └── TidyCSharp.vsct ├── README.md ├── GCop.json ├── TidyCSharp.sln ├── .gitattributes └── .gitignore /TidyCSharp/Key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geeksltd/VSIX.TidyCSharp/HEAD/TidyCSharp/Key.snk -------------------------------------------------------------------------------- /TidyCSharp/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geeksltd/VSIX.TidyCSharp/HEAD/TidyCSharp/Resources/icon.png -------------------------------------------------------------------------------- /TidyCSharp/Resources/Preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Geeksltd/VSIX.TidyCSharp/HEAD/TidyCSharp/Resources/Preview.png -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/_Infra/ICodeCleaner.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | 3 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 4 | { 5 | public interface ICodeCleaner 6 | { 7 | void Run(ProjectItem item); 8 | } 9 | } -------------------------------------------------------------------------------- /TidyCSharp/CommandConstants/PkgCmdID.cs: -------------------------------------------------------------------------------- 1 | // PkgCmdID.cs 2 | // MUST match PkgCmdID.h 3 | 4 | namespace Geeks.GeeksProductivityTools 5 | { 6 | static class PkgCmdIDList 7 | { 8 | public const uint CmdCustomUpAllActions = 0x0138; 9 | }; 10 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/TokenRemovers/IPrivateModiferTokenRemover.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | 3 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 4 | { 5 | public interface IPrivateModiferTokenRemover 6 | { 7 | SyntaxNode Remove(SyntaxNode root); 8 | } 9 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/Infra/UI/CustomCheckBox.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.CommandsHandlers 4 | { 5 | public partial class CustomCheckBox : CheckBox 6 | { 7 | public CleanerItemUIInfo Info { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeTypeConverter/SyntaxNodeConverter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | 3 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeTypeConverter 4 | { 5 | public static class SyntaxNodeConverter 6 | { 7 | public static T As(this SyntaxNode node) where T : class 8 | => node as T; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/ActionsOnCSharp/CSharpActionDelegate.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using Geeks.VSIX.TidyCSharp.Cleanup.CommandsHandlers; 3 | 4 | namespace Geeks.GeeksProductivityTools.Menus.ActionsOnCSharp 5 | { 6 | public class CSharpAction 7 | { 8 | public delegate void TargetAction(ProjectItem item, CleanupOptions cleanupOptions, bool fileWindowMustBeOpend = false); 9 | } 10 | } -------------------------------------------------------------------------------- /TidyCSharp/OptionsPage.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.Shell; 2 | using System.ComponentModel; 3 | 4 | namespace Geeks.GeeksProductivityTools 5 | { 6 | public class OptionsPage : DialogPage 7 | { 8 | [DisplayName("Disable Open M# module")] 9 | [Description("Disables open M#m odule by Ctrl click")] 10 | public bool DisableShiftClick { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeExtractors/ISyntaxTreeMemberExtractor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using System.Collections.Generic; 4 | 5 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 6 | { 7 | public interface ISyntaxTreeMemberExtractor 8 | { 9 | List Extraxt(SyntaxNode root, SyntaxKind kind); 10 | } 11 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/SimplyAsyncCall/Option/CleanupTypes.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | using System; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Cleanup.SimplyAsyncCall 5 | { 6 | [Flags] 7 | public enum CleanupTypes 8 | { 9 | [CleanupItem(Title = "Remove unnecessary async / await pair (simply return the task).")] 10 | SingleExpression = 0x02, 11 | } 12 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/ActionsOnCSharp/DteServiceProvider.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using EnvDTE80; 3 | using Microsoft.VisualStudio.Shell; 4 | 5 | namespace Geeks.GeeksProductivityTools.Menus.ActionsOnCSharp 6 | { 7 | public class DteServiceProvider 8 | { 9 | static DTE2 _dteServiceProvider; 10 | public static DTE2 Instance => _dteServiceProvider ?? ServiceProvider.GlobalProvider.GetService(typeof(DTE)) as DTE2; 11 | } 12 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/RenameHelper/Renamer.RenameOutput.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | 3 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 4 | { 5 | abstract partial class Renamer 6 | { 7 | public class RenameResult 8 | { 9 | public SyntaxNode Node { get; set; } 10 | public Solution Solution { get; set; } 11 | public Document Document { get; set; } 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/SimplyAsyncCall/Option/Options.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | 3 | namespace Geeks.VSIX.TidyCSharp.Cleanup.SimplyAsyncCall 4 | { 5 | public class Options : OptionsBase, ICleanupOption 6 | { 7 | public CleanupTypes? CleanupItems => (CleanupTypes?)CleanupItemsInteger; 8 | 9 | public override CodeCleanerType GetCodeCleanerType() => CodeCleanerType.SimplyAsyncCalls; 10 | } 11 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/Infra/CheckBoxItemInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.CommandsHandlers 2 | { 3 | public class CleanerItemUIInfo 4 | { 5 | public string Name { get; set; } 6 | public int CleanerType { get; set; } 7 | public int Order { get; set; } 8 | 9 | public bool ShouldBeSelectedByDefault { get; set; } 10 | 11 | public override string ToString() => Name; 12 | } 13 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/CamelCasedClassFields/Option/Options.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | 3 | namespace Geeks.VSIX.TidyCSharp.Cleanup.CamelCasedClassFields 4 | { 5 | public class Options : OptionsBase, ICleanupOption 6 | { 7 | public CleanupTypes? CleanupItems => (CleanupTypes?)CleanupItemsInteger; 8 | 9 | public override CodeCleanerType GetCodeCleanerType() => CodeCleanerType.CamelCasedFields; 10 | } 11 | } -------------------------------------------------------------------------------- /TidyCSharp/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/PrivateModifierRemover/Option/Options.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | 3 | namespace Geeks.VSIX.TidyCSharp.Cleanup.RemovePrivateModifier 4 | { 5 | public class Options : OptionsBase, ICleanupOption 6 | { 7 | public CleanupTypes? CleanupItems => (CleanupTypes?)CleanupItemsInteger; 8 | 9 | public override CodeCleanerType GetCodeCleanerType() => CodeCleanerType.PrivateAccessModifier; 10 | } 11 | } -------------------------------------------------------------------------------- /TidyCSharp/TidyCSharp.GeneratedMSBuildEditorConfig.editorconfig: -------------------------------------------------------------------------------- 1 | is_global = true 2 | build_property.TargetFramework = 3 | build_property.TargetPlatformMinVersion = 4 | build_property.UsingMicrosoftNETSdkWeb = 5 | build_property.ProjectTypeGuids = {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 6 | build_property.PublishSingleFile = 7 | build_property.IncludeAllContentForSelfExtract = 8 | build_property._SupportedPlatformList = 9 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/CamelCasedMethodVariable/Option/CleanupTypes.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | using System; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Cleanup.CamelCasedMethodVariable 5 | { 6 | [Flags] 7 | public enum CleanupTypes 8 | { 9 | [CleanupItem(Title = "Method parameters")] 10 | MethodParameter = 0x01, 11 | 12 | [CleanupItem(Title = "Local variable declarations")] 13 | LocalVariable = 0x02, 14 | } 15 | } -------------------------------------------------------------------------------- /TidyCSharp/CommandConstants/Guids.cs: -------------------------------------------------------------------------------- 1 | // Guids.cs 2 | // MUST match guids.h 3 | using System; 4 | 5 | namespace Geeks.GeeksProductivityTools 6 | { 7 | static class GuidList 8 | { 9 | public const string GuidGeeksProductivityToolsPkgString = "c6176957-c61c-4beb-8dd8-e7c0170b0bf3"; 10 | 11 | const string guidCleanupCmdSetString = "53366ba1-1788-42c8-922a-034d6dc89b12"; 12 | // 13 | 14 | public static readonly Guid GuidCleanupCmdSet = new Guid(guidCleanupCmdSetString); 15 | }; 16 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/CamelCasedClassFields/Option/CleanupTypes.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | using System; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Cleanup.CamelCasedClassFields 5 | { 6 | [Flags] 7 | public enum CleanupTypes 8 | { 9 | [CleanupItem(Title = "Class fields: Change _something -> Something or something")] 10 | NormalFields = 0x01, 11 | 12 | [CleanupItem(Title = "Const fields: USE_THIS_FORMAT")] 13 | ConstFields = 0x02, 14 | } 15 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/CamelCasedMethodVariable/Option/Options.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | 3 | namespace Geeks.VSIX.TidyCSharp.Cleanup.CamelCasedMethodVariable 4 | { 5 | public class Options : OptionsBase, ICleanupOption 6 | { 7 | public CleanupTypes? CleanupItems => (CleanupTypes?)CleanupItemsInteger; 8 | 9 | public override CodeCleanerType GetCodeCleanerType() 10 | { 11 | return CodeCleanerType.CamelCasedMethodVariable; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/Whitespace/Option/Options.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | 3 | namespace Geeks.VSIX.TidyCSharp.Cleanup.NormalizeWhiteSpace 4 | { 5 | public class Options : OptionsBase, ICleanupOption 6 | { 7 | public const int Block_Single_Statement_Max_Length = 80; 8 | 9 | public CleanupTypes? CleanupItems => (CleanupTypes?)CleanupItemsInteger; 10 | 11 | public override CodeCleanerType GetCodeCleanerType() => CodeCleanerType.NormalizeWhiteSpaces; 12 | } 13 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/RenameHelper/Lib/ISyntaxWrapper.cs: -------------------------------------------------------------------------------- 1 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup.Renaming 2 | { 3 | using Microsoft.CodeAnalysis; 4 | 5 | internal interface ISyntaxWrapper 6 | where T : SyntaxNode 7 | { 8 | /// 9 | /// Gets the wrapped syntax node. 10 | /// 11 | /// 12 | /// The wrapped syntax node. 13 | /// 14 | T SyntaxNode 15 | { 16 | get; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/ActiveDocument.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using System.IO; 3 | 4 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 5 | { 6 | public class ActiveDocument 7 | { 8 | public static bool IsValid(ProjectItem item) 9 | { 10 | if (item == null) return false; 11 | 12 | var path = item.Properties.Item("FullPath").Value.ToString(); 13 | 14 | if (string.IsNullOrEmpty(path) || !File.Exists(path)) 15 | return false; 16 | 17 | return true; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/Infra/IMainCleanup.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup; 2 | 3 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.CommandsHandlers 4 | { 5 | public interface IMainCleanup 6 | { 7 | bool IsMainObjectSelected { get; } 8 | CodeCleanerType MainCleanupItemType { get; } 9 | bool HasSubitems { get; } 10 | CleanerItemUIInfo[] GetSelectedSubitems(); 11 | void SetItemsCheckState(int value, bool checkedState); 12 | void SetMainItemCheckState(bool isSelected); 13 | void ResetItemsCheckState(); 14 | } 15 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeExtractors/VariableDeclaratorSyntaxExtractor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp.Syntax; 3 | using Microsoft.CodeAnalysis.Text; 4 | 5 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors 6 | { 7 | public static class VariableDeclaratorSyntaxExtractor 8 | { 9 | public static FileLinePositionSpan GetFileLinePosSpan(this VariableDeclaratorSyntax node) 10 | { 11 | return node.SyntaxTree.GetLineSpan(new TextSpan(node.Span.Start, node.Span.Length)); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/RemoveExtraThisQualification/Option/Options.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | 3 | namespace Geeks.VSIX.TidyCSharp.Cleanup.RemoveExtraThisKeyword 4 | { 5 | public class Options : OptionsBase, ICleanupOption 6 | { 7 | public const int MaxFieldDeclarationLength = 80; 8 | 9 | public CleanupTypes? CleanupItems => (CleanupTypes?)CleanupItemsInteger; 10 | 11 | public override CodeCleanerType GetCodeCleanerType() 12 | { 13 | return CodeCleanerType.RemoveExtraThisQualification; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /TidyCSharp/Utility/ProcessActions.cs: -------------------------------------------------------------------------------- 1 | namespace Geeks.GeeksProductivityTools.Utils 2 | { 3 | public class ProcessActions 4 | { 5 | public static void GeeksProductivityToolsProcess() 6 | { 7 | var visualStudioProcesses = System.Diagnostics.Process.GetProcessesByName("devenv"); 8 | 9 | foreach (var process in visualStudioProcesses) 10 | { 11 | if (!process.MainWindowTitle.Contains("GeeksProductivityTools")) continue; 12 | 13 | process.Kill(); 14 | break; 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/SimplifyClassFieldDeclarations/Option/Options.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | 3 | namespace Geeks.VSIX.TidyCSharp.Cleanup.SimplifyClassFieldDeclaration 4 | { 5 | public class Options : OptionsBase, ICleanupOption 6 | { 7 | public const int MaxFieldDeclarationLength = 80; 8 | 9 | public CleanupTypes? CleanupItems => (CleanupTypes?)CleanupItemsInteger; 10 | 11 | public override CodeCleanerType GetCodeCleanerType() 12 | { 13 | return CodeCleanerType.SimplifyClassFieldDeclarations; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/ConvertMembersToExpressionBodied/Option/Options.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | 3 | namespace Geeks.VSIX.TidyCSharp.Cleanup.MembersToExpressionBodied 4 | { 5 | public class Options : OptionsBase, ICleanupOption 6 | { 7 | public const int MaxExpressionBodiedMemberLength = 90; 8 | 9 | public CleanupTypes? CleanupItems => (CleanupTypes?)CleanupItemsInteger; 10 | 11 | public override CodeCleanerType GetCodeCleanerType() 12 | { 13 | return CodeCleanerType.ConvertMembersToExpressionBodied; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeExtractors/SyntaxTriviaExtractor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.Text; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors 5 | { 6 | public static class SyntaxTriviaExtractor 7 | { 8 | public static string GetFilePath(this SyntaxTrivia trivia) => trivia.SyntaxTree.FilePath; 9 | 10 | public static FileLinePositionSpan GetFileLinePosSpan(this SyntaxTrivia trivia) 11 | { 12 | return trivia.SyntaxTree.GetLineSpan(new TextSpan(trivia.Span.Start, trivia.Span.Length)); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /TidyCSharp/Utility/MessageBoxDisplay.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace Geeks.GeeksProductivityTools.Utility 4 | { 5 | public class MessageBoxDisplay 6 | { 7 | public struct MessageBoxArgs 8 | { 9 | public string Message { get; set; } 10 | public string Caption { get; set; } 11 | public MessageBoxButtons Button { get; set; } 12 | public MessageBoxIcon Icon { get; set; } 13 | } 14 | 15 | public static DialogResult Show(MessageBoxArgs args) => MessageBox.Show(args.Message, args.Caption, args.Button, args.Icon); 16 | } 17 | } -------------------------------------------------------------------------------- /TidyCSharp/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | // This file is used by Code Analysis to maintain SuppressMessage 2 | // attributes that are applied to this project. Project-level 3 | // suppressions either have no target or are given a specific target 4 | // and scoped to a namespace, type, member, etc. 5 | // 6 | // To add a suppression to this file, right-click the message in the 7 | // Error List, point to "Suppress Message(s)", and click "In Project 8 | // Suppression File". You do not need to add suppressions to this 9 | // file manually. 10 | 11 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1017:MarkAssembliesWithComVisible")] -------------------------------------------------------------------------------- /TidyCSharp/Definition/UsingsCommands.cs: -------------------------------------------------------------------------------- 1 | namespace Geeks.GeeksProductivityTools.Definition 2 | { 3 | public static class UsingsCommands 4 | { 5 | public const string RemoveAndSortVS15 = "EditorContextMenus.CodeWindow.OrganizeUsings.RemoveAndSort"; 6 | 7 | public const string RemoveAndSortVS17 = "EditorContextMenus.CodeWindow.RemoveAndSort"; 8 | 9 | public const string RemoveAndSortCommandName = "Edit.RemoveAndSort"; 10 | 11 | public const string SystemNamespace = "using System;"; 12 | 13 | public const string LinqNamespace = "using System.Linq;"; 14 | 15 | public const string GenericNamespace = "using System.Collections.Generic;"; 16 | } 17 | } -------------------------------------------------------------------------------- /TidyCSharp/Extensions/FileExtensions.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using System; 3 | 4 | namespace Geeks.GeeksProductivityTools.Extensions 5 | { 6 | public static class FileExtensions 7 | { 8 | public static bool IsCsharpFile(this ProjectItem projectItem) 9 | { 10 | return projectItem.Kind == Constants.vsProjectItemKindPhysicalFile && projectItem.Name.EndsWith(".cs"); 11 | } 12 | 13 | public static bool IsCSharpDesignerFile(this ProjectItem projectItem) 14 | { 15 | return projectItem.Kind == Constants.vsProjectItemKindPhysicalFile 16 | && projectItem.Name.EndsWith(".designer.cs", StringComparison.OrdinalIgnoreCase); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/Infra/CleanupItemAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Geeks.VSIX.TidyCSharp.Cleanup.Infra 4 | { 5 | [System.AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)] 6 | public sealed class CleanupItemAttribute : Attribute 7 | { 8 | public string Title { get; set; } = null; 9 | public int FirstOrder { get; set; } = int.MaxValue; 10 | public bool SelectedByDefault { get; set; } = true; 11 | 12 | public int? Order => FirstOrder == int.MaxValue ? (int?)null : FirstOrder; 13 | public Type SubitemType { get; set; } 14 | 15 | public CleanupItemAttribute() 16 | { 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/_Infra/CodeCleaner.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | 3 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 4 | { 5 | public class CodeCleaner 6 | { 7 | // TODO: By Alireza => To return Syntax node and pass syntaxNode no next clean up function and dont close windows for each cleanup , just for something like organize usings 8 | // public ICodeCleaner Cleaner { get; private set; } 9 | ICodeCleaner Cleaner; 10 | ProjectItem Item; 11 | 12 | public CodeCleaner(ICodeCleaner cleaner, ProjectItem item) 13 | { 14 | Cleaner = cleaner; 15 | Item = item; 16 | } 17 | 18 | public void Run() => Cleaner.Run(Item); 19 | } 20 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/RemoveExtraThisQualification/Option/CleanupTypes.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | using System; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Cleanup.RemoveExtraThisKeyword 5 | { 6 | [Flags] 7 | public enum CleanupTypes 8 | { 9 | [CleanupItem(Title = "Remove from method calls")] 10 | RemoveFromMethodCall = 0x01, 11 | 12 | // [CleanupItem(Title = "Remove From virual Method Call")] 13 | // Remove_From_virual_Method_Call = 0x02, 14 | 15 | [CleanupItem(Title = "Remove from field calls")] 16 | RemoveFromFieldsCall = 0x04, 17 | 18 | [CleanupItem(Title = "Remove from property calls")] 19 | RemoveFromPropertiesCall = 0x08, 20 | } 21 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/RenameHelper/ParameterRenamer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp.Syntax; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 7 | { 8 | class ParameterRenamer : VariableRenamer 9 | { 10 | public ParameterRenamer(Document document) : base(document) 11 | { 12 | } 13 | 14 | protected override IEnumerable GetItemsToRename(SyntaxNode currentNode) 15 | { 16 | return 17 | (currentNode as MethodDeclarationSyntax) 18 | .ParameterList 19 | .Parameters 20 | .Select(x => x.Identifier); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/ActionsOnCSharp/ActionCSharpOnProjectItem.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using Geeks.VSIX.TidyCSharp.Cleanup.CommandsHandlers; 3 | using static Geeks.GeeksProductivityTools.Menus.ActionsOnCSharp.CSharpAction; 4 | 5 | namespace Geeks.GeeksProductivityTools.Menus.ActionsOnCSharp 6 | { 7 | public class ActionCSharpOnProjectItem 8 | { 9 | public static void Action(ProjectItem item, TargetAction targetAction, CleanupOptions cleanupOptions) 10 | { 11 | targetAction(item, cleanupOptions); 12 | 13 | if (item.ProjectItems == null) return; 14 | 15 | for (var i = 1; i <= item.ProjectItems.Count; i++) 16 | 17 | Action(item.ProjectItems.Item(i), targetAction, cleanupOptions); 18 | 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/PrivateModifierRemover/Option/CleanupTypes.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | using System; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Cleanup.RemovePrivateModifier 5 | { 6 | [Flags] 7 | public enum CleanupTypes 8 | { 9 | [CleanupItem(Title = "Remove 'private' from nested classes")] 10 | RemoveNestedClassPrivateModifier = 0x02, 11 | 12 | [CleanupItem(Title = "Remove 'private' from fields")] 13 | RemoveClassFieldsPrivateModifier = 0x04, 14 | 15 | [CleanupItem(Title = "Remove 'private' from methods")] 16 | RemoveClassMethodsPrivateModifier = 0x08, 17 | 18 | [CleanupItem(Title = "Remove 'private' from properties")] 19 | RemoveClassPropertiesPrivateModifier = 0x10, 20 | } 21 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeExtractors/ArgumentListSyntaxExtractor.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeTypeConverter; 2 | using Microsoft.CodeAnalysis.CSharp.Syntax; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors 5 | { 6 | public static class ArgumentListSyntaxExtractor 7 | { 8 | public static BlockSyntax GetBlockSyntaxOfFirstArgument(this ArgumentListSyntax node) 9 | { 10 | return node.Arguments.FirstOrDefault() 11 | .Expression.As() 12 | ?.Body.As(); 13 | } 14 | 15 | public static ArgumentSyntax FirstArgument(this ArgumentListSyntax node) 16 | { 17 | return node.Arguments.FirstOrDefault(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/SimplifyClassFieldDeclarations/Option/CleanupTypes.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | using System; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Cleanup.SimplifyClassFieldDeclaration 5 | { 6 | [Flags] 7 | public enum CleanupTypes 8 | { 9 | [CleanupItem(Title = "Remove unnecessary explicit \"=0\" or \"=false\" from class fields.")] 10 | RemoveClassFieldsInitializerLiteral = 0x01, 11 | 12 | [CleanupItem(Title = "Remove unnecessary explicit \"=null\" from class fields.")] 13 | RemoveClassFieldsInitializerNull = 0x02, 14 | 15 | [CleanupItem(Title = "Declare multiple class fields [with the same type] on the same line (if total size < 80 chars)", SelectedByDefault = false)] 16 | GroupAndMergeClassFields = 0x04, 17 | } 18 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/_Infra/ICleanupOption.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.CommandsHandlers; 2 | 3 | namespace Geeks.VSIX.TidyCSharp.Cleanup.Infra 4 | { 5 | public interface ICleanupOption 6 | { 7 | int? CleanupItemsInteger { get; } 8 | 9 | void Accept(IMainCleanup mainCleanup); 10 | 11 | CodeCleanerType GetCodeCleanerType(); 12 | } 13 | public static class ICleanupOptionHelper 14 | { 15 | public static bool Should(this ICleanupOption options, int? optionItem) 16 | { 17 | if (options == null) return true; 18 | if (options.CleanupItemsInteger == null) return true; 19 | if (optionItem == null) return true; 20 | 21 | return (options.CleanupItemsInteger & optionItem) == optionItem; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeExtractors/FieldExtractor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 8 | { 9 | public class FieldExtractor : ISyntaxTreeMemberExtractor 10 | { 11 | public List Extraxt(SyntaxNode root, SyntaxKind kind) 12 | { 13 | return root.DescendantNodes().OfType() 14 | .Where(fld => fld.Modifiers.Any(m => m.IsKind(kind))) 15 | .SelectMany(method => method.Modifiers.Where(m => m.IsKind(kind))) 16 | .ToList(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeExtractors/MethodExtractor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 8 | { 9 | public class MethodExtractor : ISyntaxTreeMemberExtractor 10 | { 11 | public List Extraxt(SyntaxNode root, SyntaxKind kind) 12 | { 13 | return root.DescendantNodes().OfType() 14 | .Where(mth => mth.Modifiers.Any(m => m.IsKind(kind))) 15 | .SelectMany(method => method.Modifiers.Where(m => m.IsKind(kind))) 16 | .ToList(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeExtractors/PropertyExtractor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 8 | { 9 | public class PropertyExtractor : ISyntaxTreeMemberExtractor 10 | { 11 | public List Extraxt(SyntaxNode root, SyntaxKind kind) 12 | { 13 | return root.DescendantNodes().OfType() 14 | .Where(prp => prp.Modifiers.Any(m => m.IsKind(kind))) 15 | .SelectMany(method => method.Modifiers.Where(m => m.IsKind(kind))) 16 | .ToList(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeExtractors/NestedClassExtractor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 8 | { 9 | public class NestedClassExtractor : ISyntaxTreeMemberExtractor 10 | { 11 | public List Extraxt(SyntaxNode root, SyntaxKind kind) 12 | { 13 | return root.DescendantNodes().OfType() 14 | .Where(cls => cls.Modifiers.Any(m => m.IsKind(kind))) 15 | .SelectMany(method => method.Modifiers.Where(m => m.IsKind(kind))) 16 | .ToList(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeValidators/ExpressionStatementValidator.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors; 2 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeTypeConverter; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | 5 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeValidators 6 | { 7 | public static class ExpressionStatementValidator 8 | { 9 | public static bool MethodNameShouldBe(this ExpressionStatementSyntax node, string checkArg) 10 | { 11 | return checkArg.Equals(node.Expression.As()?.Name.ToString()); 12 | } 13 | 14 | public static bool IdentifierShouldBe(this ExpressionStatementSyntax node, string checkArg) 15 | { 16 | return checkArg.Equals(node.FirstDescendantNode().Expression.ToString()); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeValidators/ArgumentListSyntaxValidator.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.CSharp.Syntax; 2 | using System.Linq; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeValidators 5 | { 6 | public static class ArgumentListValidator 7 | { 8 | public static bool ArgumentsCountShouldBe(this ArgumentListSyntax node, int count) 9 | { 10 | return node.Arguments.Count() == count; 11 | } 12 | 13 | public static bool FirstArgumentShouldBe(this ArgumentListSyntax node, string checkArg) 14 | { 15 | return checkArg.Equals(node.Arguments.FirstOrDefault().Expression.ToString()); 16 | } 17 | 18 | public static bool FirstArgumentShouldContains(this ArgumentListSyntax node, string checkArg) 19 | { 20 | return node.Arguments.FirstOrDefault().Expression.ToString().Contains(checkArg); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/_Infra/CodeCleanerHost.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using Geeks.VSIX.TidyCSharp; 3 | using Geeks.VSIX.TidyCSharp.Cleanup; 4 | using Geeks.VSIX.TidyCSharp.Cleanup.CommandsHandlers; 5 | 6 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 7 | { 8 | public class CodeCleanerHost 9 | { 10 | public static void Run(ProjectItem item, CodeCleanerType command, CleanupOptions cleanupOptions, bool isReportOnly = false) 11 | { 12 | if (!ActiveDocument.IsValid(item)) 13 | ErrorNotification.EmailError(Resources.PrivateModifierCleanUpFailed); 14 | 15 | else 16 | { 17 | var instance = CodeCleanerFactory.Create(command, cleanupOptions, isReportOnly); 18 | new CodeCleaner(instance, item).Run(); 19 | } 20 | } 21 | 22 | public static void GenerateMessages() => CodeCleanerCommandRunnerBase.GenerateMessages(); 23 | } 24 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/ConvertMembersToExpressionBodied/Option/CleanupTypes.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | using System; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Cleanup.MembersToExpressionBodied 5 | { 6 | [Flags] 7 | public enum CleanupTypes 8 | { 9 | [CleanupItem(Title = "Convert Methods => Method with only a single return statement and lenth less than 100 chars(length of its signature and its single statement)")] 10 | ConvertMethods = 0x01, 11 | 12 | [CleanupItem(Title = "Convert ReadOnly Property => ReadOnly Property with only a single return statement and lenth less than 100 chars(length of its Defenition and its single statement)")] 13 | ConvertReadOnlyProperty = 0x02, 14 | 15 | [CleanupItem(Title = "Convert Constructors => Method with only a single return statement and lenth less than 100 chars(length of its signature and its single statement)")] 16 | ConvertConstructors = 0x03, 17 | } 18 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeValidators/MemberAccessExpressionValidator.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.CSharp.Syntax; 2 | using System.Linq; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeValidators 5 | { 6 | public static class MemberAccessExpressionValidator 7 | { 8 | public static bool MethodNameShouldBe(this MemberAccessExpressionSyntax node, string checkArg) 9 | { 10 | return checkArg.Equals(node.Name.Identifier.ToString()); 11 | } 12 | 13 | public static bool MethodNameShouldBeIn(this MemberAccessExpressionSyntax node, string[] checkArgs) 14 | { 15 | return checkArgs.Any(x => 16 | x.Equals(node.Name.Identifier.ToString())); 17 | } 18 | 19 | public static bool LeftSideShouldBeIdentifier(this MemberAccessExpressionSyntax node, bool shouldBe = true) 20 | { 21 | return node.Expression 22 | is IdentifierNameSyntax == shouldBe; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VSIX.TidyCSharp 2 | 3 | A Visual Studio extension that adds a few enhancements to improve C# code development. It provides a list of automatic refactorig tools for cleaner C# code. 4 | 5 | [learn more](https://marketplace.visualstudio.com/items?itemName=Paymon.TidyC): 6 | ## Build and running the code 7 | 8 | ### Prerequisites 9 | 10 | 1. Visual Studio with Visual Studio extensible tools and features installed. 11 | 2. GIT for Windows ([install from here](http://gitforwindows.org/)) 12 | 13 | ## Contributing 14 | 15 | As this solution is an opensource project, so any kind of contributions are welcome! Just fork the repo, do your changes then make a merge request. 16 | We'll review your code ASAP and we will do the merge if everything was just fine. If there was any kind of issues, post it at [issues](https://github.com/Geeksltd/VSIX.TidyCSharp/issues) section. 17 | 18 | ## Authors 19 | 20 | This project is maintained and supported by the Geeks Ltd. 21 | 22 | See also the list of [contributors](https://github.com/Geeksltd/VSIX.TidyCSharp/contributors) who participated in this project. 23 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeValidators/ClassDeclarationValidator.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeTypeConverter; 2 | using Microsoft.CodeAnalysis; 3 | using Microsoft.CodeAnalysis.CSharp; 4 | using Microsoft.CodeAnalysis.CSharp.Syntax; 5 | using System.Linq; 6 | 7 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeValidators 8 | { 9 | public static class ClassDeclarationValidator 10 | { 11 | public static bool ClassShouldHaveBase(this ClassDeclarationSyntax node) 12 | { 13 | return node.BaseList != null; 14 | } 15 | 16 | public static bool ClassShouldHaveGenericBase(this ClassDeclarationSyntax node) 17 | { 18 | return node.BaseList.Types.Any(x => x.Type.IsKind(SyntaxKind.GenericName)); 19 | } 20 | 21 | public static bool GenericClassShouldInheritFrom(this ClassDeclarationSyntax node, string baseClass) 22 | { 23 | return node.BaseList.Types.Any(x => x.As()? 24 | .Type.As()? 25 | .Identifier.Text == baseClass); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/_Infra/OptionsBase.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.CommandsHandlers; 2 | using System.Linq; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Cleanup.Infra 5 | { 6 | public abstract class OptionsBase : ICleanupOption 7 | { 8 | public virtual int? CleanupItemsInteger { get; private set; } 9 | 10 | public abstract CodeCleanerType GetCodeCleanerType(); 11 | 12 | public void Accept(IMainCleanup mainCleanup) 13 | { 14 | if (mainCleanup.MainCleanupItemType == GetCodeCleanerType()) 15 | { 16 | var selectedItems = mainCleanup.GetSelectedSubitems().Select(x => x.CleanerType).ToArray(); 17 | 18 | CleanupItemsInteger = selectedItems.FirstOrDefault(); 19 | 20 | foreach (var item in selectedItems) 21 | CleanupItemsInteger |= item; 22 | } 23 | } 24 | 25 | public override string ToString() 26 | { 27 | return $"{(CleanupItemsInteger ?? 0).ToString()}"; 28 | // return $"{(int)GetCodeCleanerType()}:{(CleanupItemsInteger ?? 0).ToString()}"; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /TidyCSharp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Resources; 4 | using System.Runtime.InteropServices; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("Geeks Productivity Tools")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("Geeks")] 13 | [assembly: AssemblyProduct("Geeks Productivity Tools")] 14 | [assembly: AssemblyCopyright("")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: ComVisible(false)] 18 | [assembly: CLSCompliant(false)] 19 | [assembly: NeutralResourcesLanguage("en-US")] 20 | 21 | // Version information for an assembly consists of the following four values: 22 | // 23 | // Major Version 24 | // Minor Version 25 | // Build Number 26 | // Revision 27 | // 28 | // You can specify all the values or you can default the Revision and Build Numbers 29 | // by using the '*' as shown below: 30 | 31 | [assembly: AssemblyVersion("1.0.0.0")] 32 | [assembly: AssemblyFileVersion("1.0.0.0")] 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /GCop.json: -------------------------------------------------------------------------------- 1 | { 2 | "ReadMe": "To learn how to configure this, see:http://gcop.co/doc/config", 3 | "Projects": [], 4 | "DomainProjectNames": "", 5 | "General": [ 6 | { 7 | "Path": "*.g.i.cs", 8 | "Exclude": "*" 9 | }, 10 | { 11 | "Path": "*\\DAL\\*", 12 | "Exclude": "*" 13 | }, 14 | { 15 | "Path": "*\\Pages\\*", 16 | "Exclude": "*" 17 | }, 18 | { 19 | "Path": "*\\Entities\\*", 20 | "Exclude": "*" 21 | }, 22 | { 23 | "Path": "*\\@Modules\\*", 24 | "Exclude": "*" 25 | }, 26 | { 27 | "Path": "*\\Modules\\*", 28 | "Exclude": "*" 29 | }, 30 | { 31 | "Path": "*\\Controller.cs", 32 | "Exclude": "*" 33 | }, 34 | { 35 | "Path": "*\\Test\\*", 36 | "Exclude": "*" 37 | }, 38 | { 39 | "Path": "*\\TaskManager.cs", 40 | "Exclude": "*" 41 | } 42 | ], 43 | "Report": { 44 | "Enabled": true, 45 | "AnalyzerErrorInterval": 30, 46 | "AnalyzerPerformanceInterval": 30, 47 | "ProjectInfoInterval": 30 48 | }, 49 | "Diagnostics": { 50 | "Enabled": false, 51 | "URL": null 52 | }, 53 | "Logging": { 54 | "LogExceptionsToFile": false, 55 | "LogExceptionsToOutputWindow": false 56 | } 57 | } -------------------------------------------------------------------------------- /TidyCSharp/Environment/App.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using EnvDTE80; 3 | using Microsoft.VisualStudio.Shell; 4 | using Microsoft.VisualStudio.Shell.Interop; 5 | using System; 6 | 7 | namespace Geeks.GeeksProductivityTools 8 | { 9 | public static class App 10 | { 11 | public static DTE Dte { get;private set;} 12 | public static GlobalSettings Settings { get;set;} 13 | 14 | public static void Initialize(OptionsPage optionsPage) 15 | { 16 | ThreadHelper.JoinableTaskFactory 17 | .Run(async delegate 18 | { 19 | await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); 20 | }); 21 | 22 | AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(GlobalExceptionHandlerEvent); 23 | 24 | Dte = (DTE2)TidyCSharpPackage.GetGlobalService(typeof(SDTE)); 25 | Settings = new GlobalSettings(); 26 | Settings.Load(); 27 | } 28 | 29 | static void GlobalExceptionHandlerEvent(object sender, UnhandledExceptionEventArgs args) 30 | { 31 | ErrorNotification.WriteErrorToFile((Exception)args.ExceptionObject); 32 | ErrorNotification.WriteErrorToOutputWindow((Exception)args.ExceptionObject); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeExtractors/SyntaxNodeExtractor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.Text; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | 7 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors 8 | { 9 | public static class SyntaxNodeExtractor 10 | { 11 | public static IEnumerable DescendantNodesOfType(this SyntaxNode node) where T : class 12 | { 13 | return node.DescendantNodes().OfType(); 14 | } 15 | 16 | public static IEnumerable DescendantNodesAndSelfOfType(this SyntaxNode node) where T : class 17 | { 18 | return node.DescendantNodesAndSelf().OfType(); 19 | } 20 | 21 | public static T FirstDescendantNode(this SyntaxNode node) where T : class 22 | { 23 | return node.DescendantNodes().OfType().FirstOrDefault(); 24 | } 25 | 26 | public static FileLinePositionSpan GetFileLinePosSpan(this SyntaxNode node) 27 | { 28 | return node.SyntaxTree.GetLineSpan(new TextSpan(node.Span.Start, node.Span.Length)); 29 | } 30 | 31 | public static string GetFileName(this SyntaxNode node) 32 | { 33 | return Path.GetFileName(node.SyntaxTree.FilePath); 34 | } 35 | 36 | public static string GetFilePath(this SyntaxNode node) => node.SyntaxTree.FilePath; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/Infra/BaseCodeCleanupCommand.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.Shell; 2 | using System; 3 | using System.ComponentModel.Design; 4 | 5 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 6 | { 7 | public abstract class BaseCodeCleanupCommand 8 | { 9 | protected OleMenuCommandService Menu { get; private set; } 10 | protected uint CommandId { get; private set; } 11 | protected BaseCodeCleanupCommand(OleMenuCommandService menu, uint commandId) 12 | { 13 | Menu = menu; 14 | CommandId = commandId; 15 | } 16 | 17 | protected abstract void Callback(object sender, EventArgs e); 18 | 19 | protected void Item_BeforeQueryStatus(object sender, EventArgs e) 20 | { 21 | var cmd = sender as OleMenuCommand; 22 | var activeDoc = App.Dte.ActiveDocument; 23 | 24 | if (null != cmd && activeDoc != null) 25 | { 26 | var fileName = App.Dte.ActiveDocument.FullName.ToUpper(); 27 | cmd.Visible = true; 28 | } 29 | } 30 | 31 | public virtual void SetupCommands() 32 | { 33 | var menuCommandID = new CommandID(GuidList.GuidCleanupCmdSet, (int)CommandId); 34 | var menuItem = new OleMenuCommand(Callback, menuCommandID); 35 | menuItem.BeforeQueryStatus += Item_BeforeQueryStatus; 36 | Menu.AddCommand(menuItem); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/ActionsOnCSharp/ActionCSharpOnSolution.cs: -------------------------------------------------------------------------------- 1 | using Geeks.GeeksProductivityTools.Utils; 2 | using Geeks.VSIX.TidyCSharp.Cleanup.CommandsHandlers; 3 | using System; 4 | using static Geeks.GeeksProductivityTools.Menus.ActionsOnCSharp.CSharpAction; 5 | 6 | namespace Geeks.GeeksProductivityTools.Menus.ActionsOnCSharp 7 | { 8 | public class ActionCSharpOnSolution 9 | { 10 | public static void Invoke(TargetAction action, CleanupOptions cleanupOptions) 11 | { 12 | try 13 | { 14 | var projects = SolutionActions.FindProjects(DteServiceProvider.Instance); 15 | 16 | for (var i = 0; i < projects.Count; i++) 17 | { 18 | var currentProject = projects[i]; 19 | if (currentProject.ProjectItems == null) continue; 20 | if (currentProject.FullName.EndsWith(".shproj", StringComparison.OrdinalIgnoreCase)) continue; 21 | 22 | for (var j = 1; j < currentProject.ProjectItems.Count; j++) 23 | ActionCSharpOnProjectItem.Action(currentProject.ProjectItems.Item(j), action, cleanupOptions); 24 | } 25 | } 26 | catch (Exception e) 27 | { 28 | ErrorNotification.WriteErrorToFile(e); 29 | ErrorNotification.WriteErrorToOutputWindow(e); 30 | ProcessActions.GeeksProductivityToolsProcess(); 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/TokenRemovers/FieldTokenRemover.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 2 | using Microsoft.CodeAnalysis; 3 | using Microsoft.CodeAnalysis.CSharp; 4 | 5 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 6 | { 7 | public class FieldTokenRemover : CleanupCSharpSyntaxRewriter, IPrivateModiferTokenRemover 8 | { 9 | public FieldTokenRemover(bool isReportOnlyMode) 10 | : base(isReportOnlyMode, null) 11 | { } 12 | public SyntaxNode Remove(SyntaxNode root) 13 | { 14 | var fields = new FieldExtractor().Extraxt(root, SyntaxKind.PrivateKeyword); 15 | 16 | if (isReportOnlyMode) 17 | { 18 | foreach (var field in fields) 19 | { 20 | var lineSpan = field.GetFileLinePosSpan(); 21 | 22 | AddReport(new ChangesReport(root) 23 | { 24 | LineNumber = lineSpan.StartLinePosition.Line, 25 | Column = lineSpan.StartLinePosition.Character, 26 | Message = "private fields --> private can be removed", 27 | Generator = nameof(FieldTokenRemover) 28 | }); 29 | } 30 | } 31 | 32 | // TODO: 1. Fix the issue with touching the namespaces 2.Remove the conditional operator 33 | return fields.Count == 0 ? null : root.RemovePrivateTokens(fields); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/TokenRemovers/MethodTokenRemover.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 2 | using Microsoft.CodeAnalysis; 3 | using Microsoft.CodeAnalysis.CSharp; 4 | 5 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 6 | { 7 | public class MethodTokenRemover : CleanupCSharpSyntaxRewriter, IPrivateModiferTokenRemover 8 | { 9 | public MethodTokenRemover(bool isReportOnlyMode) 10 | : base(isReportOnlyMode, null) 11 | { } 12 | public SyntaxNode Remove(SyntaxNode root) 13 | { 14 | var methods = new MethodExtractor().Extraxt(root, SyntaxKind.PrivateKeyword); 15 | 16 | if (isReportOnlyMode) 17 | { 18 | foreach (var method in methods) 19 | { 20 | var lineSpan = method.GetFileLinePosSpan(); 21 | 22 | AddReport(new ChangesReport(root) 23 | { 24 | LineNumber = lineSpan.StartLinePosition.Line, 25 | Column = lineSpan.StartLinePosition.Character, 26 | Message = "private method --> private can be removed", 27 | Generator = nameof(MethodTokenRemover) 28 | }); 29 | } 30 | } 31 | 32 | // TODO: 1. Fix the issue with touching the namespaces 2.Remove the conditional operator 33 | return methods.Count == 0 ? null : root.RemovePrivateTokens(methods); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/Whitespace/EndOFLineRewriter.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors; 2 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 3 | using Microsoft.CodeAnalysis; 4 | using Microsoft.CodeAnalysis.CSharp; 5 | 6 | namespace Geeks.VSIX.TidyCSharp.Cleanup.NormalizeWhiteSpace 7 | { 8 | public class EndOFLineRewriter : CSharpSyntaxRewriterBase 9 | { 10 | public EndOFLineRewriter(SyntaxNode initialSource, 11 | bool isReadOnlyMode, Options options) 12 | : base(initialSource, isReadOnlyMode, options) 13 | { } 14 | 15 | public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia) 16 | { 17 | if (trivia.IsKind(SyntaxKind.EndOfLineTrivia) && trivia.ToFullString() == "\r\n") 18 | { 19 | if (isReportOnlyMode) 20 | { 21 | var lineSpan = trivia.GetFileLinePosSpan(); 22 | 23 | AddReport(new ChangesReport(trivia) 24 | { 25 | LineNumber = lineSpan.StartLinePosition.Line, 26 | Column = lineSpan.StartLinePosition.Character, 27 | Message = "\\r\\n should be \\n", 28 | Generator = nameof(EndOFLineRewriter) 29 | }); 30 | } 31 | 32 | return base.VisitTrivia(SyntaxFactory.EndOfLine("\n")); 33 | } 34 | 35 | return base.VisitTrivia(trivia); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/TokenRemovers/PropertyTokenRemover.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 2 | using Microsoft.CodeAnalysis; 3 | using Microsoft.CodeAnalysis.CSharp; 4 | 5 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 6 | { 7 | public class PropertyTokenRemover : CleanupCSharpSyntaxRewriter, IPrivateModiferTokenRemover 8 | { 9 | public PropertyTokenRemover(bool isReportOnlyMode) 10 | : base(isReportOnlyMode, null) 11 | { } 12 | public SyntaxNode Remove(SyntaxNode root) 13 | { 14 | var properties = new PropertyExtractor().Extraxt(root, SyntaxKind.PrivateKeyword); 15 | 16 | if (isReportOnlyMode) 17 | { 18 | foreach (var prop in properties) 19 | { 20 | var lineSpan = prop.GetFileLinePosSpan(); 21 | 22 | AddReport(new ChangesReport(root) 23 | { 24 | LineNumber = lineSpan.StartLinePosition.Line, 25 | Column = lineSpan.StartLinePosition.Character, 26 | Message = "private property --> private can be removed", 27 | Generator = nameof(PropertyTokenRemover) 28 | }); 29 | } 30 | } 31 | 32 | // TODO: 1. Fix the issue with touching the namespaces 2.Remove the conditional operator 33 | return properties.Count == 0 ? null : root.RemovePrivateTokens(properties); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/TokenRemovers/NestedClassTokenRemover.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 2 | using Microsoft.CodeAnalysis; 3 | using Microsoft.CodeAnalysis.CSharp; 4 | 5 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 6 | { 7 | public class NestedClassTokenRemover : CleanupCSharpSyntaxRewriter, IPrivateModiferTokenRemover 8 | { 9 | public NestedClassTokenRemover(bool isReportOnlyMode) 10 | : base(isReportOnlyMode, null) 11 | { } 12 | public SyntaxNode Remove(SyntaxNode root) 13 | { 14 | var nestedClasses = new NestedClassExtractor().Extraxt(root, SyntaxKind.PrivateKeyword); 15 | 16 | if (isReportOnlyMode) 17 | { 18 | foreach (var nestedClass in nestedClasses) 19 | { 20 | var lineSpan = nestedClass.GetFileLinePosSpan(); 21 | 22 | AddReport(new ChangesReport(root) 23 | { 24 | LineNumber = lineSpan.StartLinePosition.Line, 25 | Column = lineSpan.StartLinePosition.Character, 26 | Message = "private nested class --> private can be removed", 27 | Generator = nameof(NestedClassTokenRemover) 28 | }); 29 | } 30 | } 31 | 32 | // TODO: 1. Fix the issue with touching the namespaces 2.Remove the conditional operator 33 | return nestedClasses.Count == 0 ? null : root.RemovePrivateTokens(nestedClasses); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/ActionCustomCodeCleanup.cs: -------------------------------------------------------------------------------- 1 | using Geeks.GeeksProductivityTools.Menus.Cleanup.CommandsHandlers.Infra; 2 | using Geeks.GeeksProductivityTools.Utility; 3 | using Geeks.VSIX.TidyCSharp; 4 | using Microsoft.VisualStudio.Shell; 5 | using System; 6 | using System.Windows.Forms; 7 | 8 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 9 | { 10 | public class ActionCustomCodeCleanup : BaseCodeCleanupCommand 11 | { 12 | public ActionCustomCodeCleanup(OleMenuCommandService menu) 13 | : base(menu, PkgCmdIDList.CmdCustomUpAllActions) 14 | { } 15 | 16 | protected override void Callback(object sender, EventArgs e) 17 | { 18 | var messageBoxResult = MessageBoxDisplay.Show(new MessageBoxDisplay.MessageBoxArgs 19 | { 20 | Message = Resources.WarnOnCodeCleanUp, 21 | Caption = Resources.WarningCaptionCleanup, 22 | Button = MessageBoxButtons.OKCancel, 23 | Icon = MessageBoxIcon.Warning 24 | }); 25 | 26 | if (CleanupOptionForm.Instance.ShowDialog() == DialogResult.Cancel) return; 27 | 28 | ActionsOnCSharp.CSharpAction.TargetAction desiredAction = ActionsOnCSharp.ActionsCSharpOnFile.DoCleanup; 29 | 30 | if (CleanupOptionForm.Instance.CleanupOptions != null) 31 | { 32 | ActionsOnCSharp.ActionCSharpOnAnywhere.Invoke(desiredAction, CleanupOptionForm.Instance.CleanupOptions); 33 | TidyCSharpPackage.Instance.SaveSolutionChanges(); 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/RenameHelper/Lib/SyntaxKindEx.cs: -------------------------------------------------------------------------------- 1 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup.Renaming 2 | { 3 | using Microsoft.CodeAnalysis.CSharp; 4 | 5 | internal static class SyntaxKindEx 6 | { 7 | public const SyntaxKind UnderscoreToken = (SyntaxKind)8491; 8 | public const SyntaxKind IsPatternExpression = (SyntaxKind)8657; 9 | public const SyntaxKind DefaultLiteralExpression = (SyntaxKind)8755; 10 | public const SyntaxKind LocalFunctionStatement = (SyntaxKind)8830; 11 | public const SyntaxKind TupleType = (SyntaxKind)8924; 12 | public const SyntaxKind TupleElement = (SyntaxKind)8925; 13 | public const SyntaxKind TupleExpression = (SyntaxKind)8926; 14 | public const SyntaxKind SingleVariableDesignation = (SyntaxKind)8927; 15 | public const SyntaxKind ParenthesizedVariableDesignation = (SyntaxKind)8928; 16 | public const SyntaxKind ForEachVariableStatement = (SyntaxKind)8929; 17 | public const SyntaxKind DeclarationPattern = (SyntaxKind)9000; 18 | public const SyntaxKind ConstantPattern = (SyntaxKind)9002; 19 | public const SyntaxKind CasePatternSwitchLabel = (SyntaxKind)9009; 20 | public const SyntaxKind WhenClause = (SyntaxKind)9013; 21 | public const SyntaxKind DiscardDesignation = (SyntaxKind)9014; 22 | public const SyntaxKind DeclarationExpression = (SyntaxKind)9040; 23 | public const SyntaxKind RefExpression = (SyntaxKind)9050; 24 | public const SyntaxKind RefType = (SyntaxKind)9051; 25 | public const SyntaxKind ThrowExpression = (SyntaxKind)9052; 26 | } 27 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/RenameHelper/VariableRenamer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp.Syntax; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 7 | { 8 | class VariableRenamer : Renamer 9 | { 10 | public VariableRenamer(Document document) : base(document) 11 | { 12 | } 13 | 14 | protected override IEnumerable GetItemsToRename(SyntaxNode currentNode) 15 | { 16 | return 17 | currentNode 18 | .DescendantNodes() 19 | .OfType() 20 | .Where(v => (v?.Parent?.Parent as LocalDeclarationStatementSyntax)?.Modifiers.Any(m => m.IsKind(Microsoft.CodeAnalysis.CSharp.SyntaxKind.ConstKeyword)) == false) 21 | .Select(x => x.Identifier); 22 | } 23 | 24 | protected override string[] GetNewName(string currentName) 25 | { 26 | if (currentName.StartsWith("_")) 27 | { 28 | currentName = currentName.TrimStart('_'); 29 | if (currentName.Length == 0) return null; 30 | 31 | if (char.IsLetter(currentName[0])) 32 | { 33 | return new[] { GetCamelCased(currentName) }; 34 | } 35 | } 36 | else if (char.IsLetter(currentName[0]) && char.IsUpper(currentName[0])) 37 | { 38 | return new[] { GetCamelCased(currentName) }; 39 | } 40 | 41 | return null; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /TidyCSharp/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Geeks.VSIX.TidyCSharp.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.0.3.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("")] 29 | public string CleanupChoices { 30 | get { 31 | return ((string)(this["CleanupChoices"])); 32 | } 33 | set { 34 | this["CleanupChoices"] = value; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/ActionsOnCSharp/ActionCSharpOnProject.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using Geeks.GeeksProductivityTools.Utils; 3 | using Geeks.VSIX.TidyCSharp.Cleanup.CommandsHandlers; 4 | using System; 5 | using System.Windows; 6 | using static Geeks.GeeksProductivityTools.Menus.ActionsOnCSharp.CSharpAction; 7 | 8 | namespace Geeks.GeeksProductivityTools.Menus.ActionsOnCSharp 9 | { 10 | public class ActionCSharpOnProject 11 | { 12 | public static void Invoke(TargetAction action, CleanupOptions cleanupOptions) 13 | { 14 | try 15 | { 16 | var projects = DteServiceProvider.Instance.ActiveSolutionProjects as Array; 17 | var currentProject = projects.GetValue(0) as Project; 18 | 19 | if (currentProject.ProjectItems == null) return; 20 | 21 | if (currentProject.FullName.EndsWith(".shproj", StringComparison.OrdinalIgnoreCase)) 22 | { 23 | System.Windows.MessageBox 24 | .Show("Clean up can't be called direlctly on Shared Project", "Error", MessageBoxButton.OK, MessageBoxImage.Error); 25 | return; 26 | } 27 | 28 | for (var i = 1; i <= currentProject.ProjectItems.Count; i++) 29 | ActionCSharpOnProjectItem.Action(currentProject.ProjectItems.Item(i), action, cleanupOptions); 30 | } 31 | catch (Exception e) 32 | { 33 | ErrorNotification.WriteErrorToOutputWindow(e); 34 | ErrorNotification.WriteErrorToFile(e); 35 | ProcessActions.GeeksProductivityToolsProcess(); 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/Infra/ReadOnly/ReadOnlyMainCleanup.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup; 2 | using System; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.CommandsHandlers 5 | { 6 | public class ReadOnlyMainCleanup : IMainCleanup 7 | { 8 | public bool IsMainObjectSelected { get; private set; } 9 | public CodeCleanerType MainCleanupItemType { get; private set; } 10 | public bool HasSubitems { get; private set; } 11 | public CleanerItemUIInfo[] CleanerItemUIInfos { get; private set; } 12 | 13 | public ReadOnlyMainCleanup(CodeCleanerType mainCleanupItemType, 14 | bool isMainObjectSelected = true) 15 | { 16 | MainCleanupItemType = mainCleanupItemType; 17 | IsMainObjectSelected = isMainObjectSelected; 18 | } 19 | 20 | public ReadOnlyMainCleanup(CodeCleanerType mainCleanupItemType, CleanerItemUIInfo[] cleanerItemUIInfos, 21 | bool isMainObjectSelected = true) 22 | { 23 | MainCleanupItemType = mainCleanupItemType; 24 | CleanerItemUIInfos = cleanerItemUIInfos; 25 | IsMainObjectSelected = isMainObjectSelected; 26 | } 27 | 28 | public CleanerItemUIInfo[] GetSelectedSubitems() => CleanerItemUIInfos; 29 | 30 | public void ResetItemsCheckState() 31 | { 32 | throw new NotImplementedException(); 33 | } 34 | 35 | public void SetItemsCheckState(int value, bool checkedState) 36 | { 37 | throw new NotImplementedException(); 38 | } 39 | 40 | public void SetMainItemCheckState(bool isSelected) => IsMainObjectSelected = isSelected; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /TidyCSharp.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 16 3 | VisualStudioVersion = 16.0.31129.286 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TidyCSharp", "TidyCSharp\TidyCSharp.csproj", "{7B708065-1213-49BD-94B6-A67A786FAC5E}" 6 | EndProject 7 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EB802F83-E581-4C4B-9B16-7D00D66C9329}" 8 | ProjectSection(SolutionItems) = preProject 9 | GCop.json = GCop.json 10 | EndProjectSection 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Debug-ReadonlyMode|Any CPU = Debug-ReadonlyMode|Any CPU 16 | Release|Any CPU = Release|Any CPU 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {7B708065-1213-49BD-94B6-A67A786FAC5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {7B708065-1213-49BD-94B6-A67A786FAC5E}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {7B708065-1213-49BD-94B6-A67A786FAC5E}.Debug-ReadonlyMode|Any CPU.ActiveCfg = Debug-ReadonlyMode|Any CPU 22 | {7B708065-1213-49BD-94B6-A67A786FAC5E}.Debug-ReadonlyMode|Any CPU.Build.0 = Debug-ReadonlyMode|Any CPU 23 | {7B708065-1213-49BD-94B6-A67A786FAC5E}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {7B708065-1213-49BD-94B6-A67A786FAC5E}.Release|Any CPU.Build.0 = Release|Any CPU 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | GlobalSection(ExtensibilityGlobals) = postSolution 30 | SolutionGuid = {86AC6B91-6491-4172-89DC-BBDDF3303274} 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/RenameHelper/FieldRenamer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 8 | { 9 | class FieldRenamer : Renamer 10 | { 11 | public FieldRenamer(Document document) : base(document) 12 | { 13 | } 14 | 15 | protected override IEnumerable GetItemsToRename(SyntaxNode currentNode) 16 | { 17 | var output = new List(); 18 | 19 | var selectedFields = 20 | (currentNode as ClassDeclarationSyntax) 21 | .Members.OfType() 22 | .Where( 23 | x => 24 | IsPrivate(x) && 25 | x.Modifiers.Any(m => m.IsKind(SyntaxKind.ConstKeyword)) == false 26 | ); 27 | 28 | foreach (var item in selectedFields) 29 | output.AddRange(item.Declaration.Variables); 30 | 31 | return output.Select(x => x.Identifier); 32 | } 33 | 34 | protected override string[] GetNewName(string currentName) 35 | { 36 | if (currentName.StartsWith("_")) 37 | { 38 | currentName = currentName.TrimStart('_'); 39 | 40 | if (char.IsLetter(currentName[0])) 41 | { 42 | return new[] { GetCamelCased(currentName), GetPascalCased(currentName) }; 43 | } 44 | } 45 | 46 | return null; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/CleanupCSharpSyntaxRewriter.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors; 3 | using Microsoft.CodeAnalysis; 4 | using Microsoft.CodeAnalysis.CSharp; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils 10 | { 11 | public abstract class CleanupCSharpSyntaxRewriter : CSharpSyntaxRewriter 12 | { 13 | protected ICleanupOption Options { get; private set; } 14 | protected IEnumerable ChangesReport { get; set; } 15 | protected bool isReportOnlyMode { get; set; } 16 | 17 | protected bool CheckOption(int? o) => Options.Should(o); 18 | 19 | protected CleanupCSharpSyntaxRewriter(bool isReportOnlyMode, ICleanupOption options) 20 | { 21 | this.isReportOnlyMode = isReportOnlyMode; 22 | ChangesReport = new List(); 23 | Options = options; 24 | } 25 | public virtual ChangesReport[] GetReport() => ChangesReport.ToArray(); 26 | 27 | public void AddReport(ChangesReport changesReports) 28 | { 29 | if (changesReports.FileName.HasValue()) 30 | ChangesReport = ChangesReport.Append(changesReports); 31 | } 32 | } 33 | 34 | public class ChangesReport 35 | { 36 | public ChangesReport(SyntaxNode node) => FileName = node.GetFilePath(); 37 | 38 | public ChangesReport(SyntaxTrivia trivia) => FileName = trivia.GetFilePath(); 39 | public string Message { get; set; } 40 | public long LineNumber { get; set; } 41 | public string FileName { get; private set; } 42 | public string Generator { get; set; } 43 | public long Column { get; set; } 44 | } 45 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/Infra/UI/CustomCheckListBox.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.CommandsHandlers.Infra 2 | { 3 | partial class CustomChecklistBox 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.SuspendLayout(); 32 | // 33 | // CustomCheckListBox 34 | // 35 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 36 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 37 | this.AutoSize = true; 38 | this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; 39 | this.Name = "CustomCheckListBox"; 40 | this.Size = new System.Drawing.Size(0, 0); 41 | this.MaximumSize = new System.Drawing.Size(360, 0); 42 | this.ResumeLayout(false); 43 | 44 | } 45 | 46 | #endregion 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeExtractors/InvocationExpressionExtractor.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeTypeConverter; 2 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeValidators; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System.Linq; 5 | 6 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors 7 | { 8 | public static class InvocationExpressionExtractor 9 | { 10 | public static string GetLeftSideIdentifier(this InvocationExpressionSyntax node) 11 | { 12 | return node.Expression.As()?.Expression.ToString(); 13 | } 14 | 15 | public static ExpressionSyntax GetLeftSideExpression(this InvocationExpressionSyntax node) 16 | { 17 | return node.Expression.As()?.Expression; 18 | } 19 | 20 | public static SimpleNameSyntax GetRightSideNameSyntax(this InvocationExpressionSyntax node) 21 | { 22 | return node.Expression.As()?.Name; 23 | } 24 | 25 | public static ArgumentListSyntax GetArgumentsOfMethod(this InvocationExpressionSyntax node, string methodName) 26 | { 27 | // var d1 = node.DescendantNodesAndSelfOfType(); 28 | // var d2 = d1.Where(x => x.MethodNameShouldBe(methodName)); 29 | // var d3 = d2.FirstOrDefault().ArgumentList; 30 | return node.DescendantNodesAndSelfOfType() 31 | .Where(x => x.MethodNameShouldBe(methodName))?.FirstOrDefault()?.ArgumentList; 32 | } 33 | 34 | public static ArgumentSyntax FirstArgument(this InvocationExpressionSyntax node) 35 | { 36 | return node.ArgumentList.Arguments.FirstOrDefault(); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /TidyCSharp/Settings/GlobalSettings.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.IO; 3 | 4 | namespace Geeks.GeeksProductivityTools 5 | { 6 | public class GlobalSettings 7 | { 8 | const string SETTINGS_FILE_NAME = "geeks.settings.json"; 9 | 10 | public GlobalSettings() 11 | { 12 | } 13 | 14 | // --------------------------------------- 15 | 16 | string FilePath 17 | { 18 | get 19 | { 20 | var solutionPath = GetSolutionFilePath(); 21 | if (solutionPath == null) return string.Empty; 22 | 23 | return Path.Combine(solutionPath, SETTINGS_FILE_NAME); 24 | } 25 | } 26 | 27 | string GetSolutionFilePath() 28 | { 29 | var solution = App.Dte.Solution; 30 | 31 | if (solution == null || string.IsNullOrEmpty(solution.FullName)) 32 | return null; 33 | 34 | return Path.GetDirectoryName(solution.FullName); 35 | } 36 | 37 | // --------------------------------------- 38 | 39 | public GlobalSettings Load() 40 | { 41 | if (!File.Exists(FilePath)) 42 | return new GlobalSettings(); 43 | 44 | var json = File.ReadAllText(FilePath); 45 | Geeks.GeeksProductivityTools.App.Settings = JsonConvert.DeserializeObject(json); 46 | 47 | return App.Settings; 48 | } 49 | 50 | public void Save() 51 | { 52 | var json = JsonConvert.SerializeObject(App.Settings, Formatting.Indented); 53 | 54 | File.WriteAllText(FilePath, json); 55 | 56 | // Add file to solution items folder 57 | GeeksAddin.DteExtensions.GetSolutionItemsProject().ProjectItems.AddFromFile(FilePath); 58 | 59 | // Reload once saved 60 | Load(); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/Infra/ExtendedBaseCodeCleanupCommand.cs: -------------------------------------------------------------------------------- 1 | using Geeks.GeeksProductivityTools.Menus.ActionsOnCSharp; 2 | using Geeks.GeeksProductivityTools.Utility; 3 | using Geeks.VSIX.TidyCSharp; 4 | using Geeks.VSIX.TidyCSharp.Cleanup; 5 | using Microsoft.VisualStudio.Shell; 6 | using System; 7 | using System.Windows.Forms; 8 | 9 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 10 | { 11 | public abstract class ExtendedBaseCodeCleanupCommand : BaseCodeCleanupCommand 12 | { 13 | protected CodeCleanerType CleanerType { get; private set; } 14 | 15 | protected ExtendedBaseCodeCleanupCommand(OleMenuCommandService menu, uint commandId, CodeCleanerType cleanerType) 16 | : base(menu, commandId) 17 | { 18 | CleanerType = cleanerType; 19 | } 20 | 21 | protected override void Callback(object sender, EventArgs e) 22 | { 23 | var messageBoxResult = MessageBoxDisplay.Show(new MessageBoxDisplay.MessageBoxArgs 24 | { 25 | Message = Resources.WarnOnCodeCleanUp, 26 | Caption = Resources.WarningCaptionCleanup, 27 | Button = MessageBoxButtons.OKCancel, 28 | Icon = MessageBoxIcon.Warning 29 | }); 30 | 31 | if (messageBoxResult != DialogResult.OK) return; 32 | 33 | CSharpAction.TargetAction desiredAction = ActionsCSharpOnFile.DoCleanup; 34 | var commandGuid = (sender as OleMenuCommand).CommandID.Guid; 35 | 36 | if (commandGuid == GuidList.GuidCleanupCmdSet) 37 | { 38 | ActionCSharpOnAnywhere.Invoke(desiredAction, 39 | new VSIX.TidyCSharp.Cleanup.CommandsHandlers.CleanupOptions 40 | { 41 | //ActionTypes = new[] { CleanerType } 42 | } 43 | ); 44 | 45 | TidyCSharpPackage.Instance.SaveSolutionChanges(); 46 | } 47 | else return; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/SyntaxNodeValidators/InvocationExpressionValidator.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeTypeConverter; 2 | using Microsoft.CodeAnalysis; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System.Linq; 5 | 6 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeValidators 7 | { 8 | public static class InvocationExpressionValidator 9 | { 10 | public static bool ArgumentsCountShouldBe(this InvocationExpressionSyntax node, int count) 11 | { 12 | return node.ArgumentList.Arguments.Count() == count; 13 | } 14 | 15 | public static bool FirstArgumentShouldBeIn(this InvocationExpressionSyntax node, string[] checkArgs) 16 | { 17 | return checkArgs.Any(x => 18 | x.Equals(node.ArgumentList.Arguments.FirstOrDefault().ToString())); 19 | } 20 | 21 | public static bool FirstArgumentShouldBe(this InvocationExpressionSyntax node, string checkArg) 22 | { 23 | return checkArg.Equals(node.ArgumentList.Arguments.FirstOrDefault().ToString()); 24 | } 25 | 26 | public static bool LastArgumentShouldBe(this InvocationExpressionSyntax node, string checkArg) 27 | { 28 | return checkArg.Equals(node.ArgumentList.Arguments.LastOrDefault().ToString()); 29 | } 30 | 31 | public static bool MethodNameShouldBeIn(this InvocationExpressionSyntax node, string[] checkArgs) 32 | { 33 | return checkArgs.Any(x => 34 | x.Equals(node.Expression.As()?.Name.Identifier.ToString())); 35 | } 36 | 37 | public static bool MethodNameShouldBe(this InvocationExpressionSyntax node, string checkArg) 38 | { 39 | return checkArg.Equals(node.Expression.As()?.Name.Identifier.Text); 40 | } 41 | 42 | public static bool LeftSideShouldBeIdentifier(this InvocationExpressionSyntax node, bool shouldBe = true) 43 | { 44 | return node.Expression.As()?.Expression 45 | is IdentifierNameSyntax == shouldBe; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/RenameHelper/Lib/VariableDesignationSyntaxWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup.Renaming 4 | { 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using System.Reflection; 8 | 9 | internal static partial class RenameHelper 10 | { 11 | internal struct VariableDesignationSyntaxWrapper : ISyntaxWrapper 12 | { 13 | const string VariableDesignationSyntaxTypeName = "Microsoft.CodeAnalysis.CSharp.Syntax.VariableDesignationSyntax"; 14 | static readonly Type VariableDesignationSyntaxType; 15 | 16 | readonly CSharpSyntaxNode node; 17 | 18 | static VariableDesignationSyntaxWrapper() 19 | { 20 | VariableDesignationSyntaxType = typeof(CSharpSyntaxNode).GetTypeInfo().Assembly.GetType(VariableDesignationSyntaxTypeName); 21 | } 22 | private VariableDesignationSyntaxWrapper(CSharpSyntaxNode node) => this.node = node; 23 | 24 | public CSharpSyntaxNode SyntaxNode => node; 25 | 26 | public static explicit operator VariableDesignationSyntaxWrapper(SyntaxNode node) 27 | { 28 | if (node == null) 29 | { 30 | return default(VariableDesignationSyntaxWrapper); 31 | } 32 | 33 | if (!IsInstance(node)) 34 | { 35 | throw new InvalidCastException($"Cannot cast '{node.GetType().FullName}' to '{VariableDesignationSyntaxTypeName}'"); 36 | } 37 | 38 | return new VariableDesignationSyntaxWrapper((CSharpSyntaxNode)node); 39 | } 40 | 41 | public static implicit operator CSharpSyntaxNode(VariableDesignationSyntaxWrapper wrapper) 42 | { 43 | return wrapper.node; 44 | } 45 | 46 | public static bool IsInstance(SyntaxNode node) 47 | { 48 | return node != null && LightupHelpers.CanWrapNode(node, VariableDesignationSyntaxType); 49 | } 50 | 51 | internal static VariableDesignationSyntaxWrapper FromUpcast(CSharpSyntaxNode node) 52 | { 53 | return new VariableDesignationSyntaxWrapper(node); 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /TidyCSharp/Utility/SolutionActions.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using EnvDTE80; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace Geeks.GeeksProductivityTools.Utils 7 | { 8 | public class SolutionActions 9 | { 10 | public static List FindProjects(DTE2 dteServiceProvider) 11 | { 12 | var projects = dteServiceProvider.Solution.Projects; 13 | var result = new List(); 14 | var item = projects.GetEnumerator(); 15 | 16 | while (item.MoveNext()) 17 | { 18 | var project = item.Current as Project; 19 | if (project == null) continue; 20 | 21 | if (project.Kind == ProjectKinds.vsProjectKindSolutionFolder) 22 | result.AddRange(GetSolutionFolderProjects(project)); 23 | 24 | else result.Add(project); 25 | } 26 | 27 | return result; 28 | } 29 | 30 | static IEnumerable GetSolutionFolderProjects(Project solutionFolder) 31 | { 32 | try 33 | { 34 | if (solutionFolder.ProjectItems == null) return null; 35 | 36 | var result = new List(); 37 | 38 | for (var i = 1; i <= solutionFolder.ProjectItems.Count; i++) 39 | { 40 | var subProject = solutionFolder.ProjectItems.Item(i).SubProject; 41 | if (subProject == null) continue; 42 | 43 | // another solution folder 44 | if (subProject.Kind == ProjectKinds.vsProjectKindSolutionFolder) 45 | { 46 | var solutionFolderProjects = GetSolutionFolderProjects(subProject); 47 | 48 | if (solutionFolder != null) 49 | result.AddRange(GetSolutionFolderProjects(subProject)); 50 | } 51 | 52 | else result.Add(subProject); 53 | } 54 | 55 | return result; 56 | } 57 | catch (Exception e) 58 | { 59 | ErrorNotification.WriteErrorToFile(e); 60 | ErrorNotification.WriteErrorToOutputWindow(e); 61 | ProcessActions.GeeksProductivityToolsProcess(); 62 | return null; 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/Infra/UI/CustomCheckListBox.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Windows.Forms; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.CommandsHandlers.Infra 5 | { 6 | public partial class CustomChecklistBox : UserControl 7 | { 8 | public CustomChecklistBox() => InitializeComponent(); 9 | 10 | public void AddItem(CleanerItemUIInfo itemInfo) 11 | { 12 | //var newControl = 13 | // new CustomCheckBox() 14 | // { 15 | // Text = itemInfo.Name, 16 | // Info = itemInfo, 17 | // Margin = new Padding(0), 18 | // Padding = new Padding(0), 19 | // MaximumSize = new System.Drawing.Size(460, 0), 20 | // AutoSize = true, 21 | // Dock = DockStyle.Top, 22 | // }; 23 | 24 | Controls.Add(new CustomCheckBox() 25 | { 26 | Text = itemInfo.Name, 27 | Info = itemInfo, 28 | Margin = new Padding(0), 29 | Padding = new Padding(0), 30 | MaximumSize = new System.Drawing.Size(460, 0), 31 | AutoSize = true, 32 | Dock = DockStyle.Top, 33 | }); 34 | } 35 | 36 | public CleanerItemUIInfo[] GetCheckedItems() 37 | { 38 | var selectedTypes = Controls.OfType().Where(x => x.Checked).Select(x => x.Info); 39 | return selectedTypes.OrderBy(x => x.Order).ToArray(); 40 | } 41 | 42 | public bool HasItems => Controls.OfType().Any(); 43 | 44 | public CleanerItemUIInfo[] GetItems() 45 | { 46 | return Controls.OfType().Select(x => x.Info).ToArray(); 47 | } 48 | 49 | public void SetItemsChecked(int value, bool checkedState) 50 | { 51 | foreach (var item in Controls.OfType()) 52 | { 53 | if (item.Info != null && ((item.Info.CleanerType & value) == item.Info.CleanerType)) 54 | { 55 | item.Checked = checkedState; 56 | } 57 | } 58 | } 59 | 60 | public void ResetItemsCheckState() 61 | { 62 | foreach (var item in Controls.OfType()) 63 | item.Checked = item.Info.ShouldBeSelectedByDefault; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/RenameHelper/Lib/SyntaxWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup.Renaming 4 | { 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using System.Linq; 8 | using System.Linq.Expressions; 9 | using System.Reflection; 10 | 11 | internal abstract class SyntaxWrapper 12 | { 13 | public static SyntaxWrapper Default { get; } = FindDefaultSyntaxWrapper(); 14 | 15 | public abstract TNode Wrap(SyntaxNode node); 16 | 17 | public abstract SyntaxNode Unwrap(TNode node); 18 | 19 | static SyntaxWrapper FindDefaultSyntaxWrapper() 20 | { 21 | if (typeof(SyntaxNode).GetTypeInfo().IsAssignableFrom(typeof(TNode).GetTypeInfo())) 22 | { 23 | return new DirectCastSyntaxWrapper(); 24 | } 25 | 26 | return new ConversionSyntaxWrapper(); 27 | } 28 | 29 | sealed class DirectCastSyntaxWrapper : SyntaxWrapper 30 | { 31 | public override SyntaxNode Unwrap(TNode node) => (SyntaxNode)(object)node; 32 | 33 | public override TNode Wrap(SyntaxNode node) => (TNode)(object)node; 34 | } 35 | 36 | sealed class ConversionSyntaxWrapper : SyntaxWrapper 37 | { 38 | readonly Func unwrapAccessor; 39 | readonly Func wrapAccessor; 40 | 41 | public ConversionSyntaxWrapper() 42 | { 43 | unwrapAccessor = LightupHelpers.CreateSyntaxPropertyAccessor(typeof(TNode), nameof(ISyntaxWrapper.SyntaxNode)); 44 | 45 | var explicitOperator = typeof(TNode).GetTypeInfo().GetDeclaredMethods("op_Explicit") 46 | .Single(m => m.ReturnType == typeof(TNode) && m.GetParameters()[0].ParameterType == typeof(SyntaxNode)); 47 | 48 | var syntaxParameter = Expression.Parameter(typeof(SyntaxNode), "syntax"); 49 | 50 | var wrapAccessorExpression = 51 | Expression.Lambda>( 52 | Expression.Call(explicitOperator, syntaxParameter), 53 | syntaxParameter); 54 | 55 | wrapAccessor = wrapAccessorExpression.Compile(); 56 | } 57 | 58 | public override SyntaxNode Unwrap(TNode node) => unwrapAccessor(node); 59 | 60 | public override TNode Wrap(SyntaxNode node) => wrapAccessor(node); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/Whitespace/Option/CleanupTypes.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | using System; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Cleanup.NormalizeWhiteSpace 5 | { 6 | [Flags] 7 | public enum CleanupTypes 8 | { 9 | [CleanupItem(FirstOrder = 1, Title = "Trim the file")] 10 | TrimTheFile = 0x80, 11 | 12 | [CleanupItem(FirstOrder = 1, Title = "No duplicate blank lines between namespace members")] 13 | RemoveDuplicateBetweenNamespaceMembers = 0x04, 14 | 15 | [CleanupItem(FirstOrder = 1, Title = "No duplicate blank lines between class members")] 16 | RemoveDuplicateBetweenClassMembers = 0x02, 17 | 18 | [CleanupItem(FirstOrder = 1, Title = "No duplicate blank lines between method statement")] 19 | RemoveDuplicateBetweenMethodsStatements = 0x01, 20 | 21 | [CleanupItem(FirstOrder = 1, Title = "No duplicate blank lines between comments")] 22 | RemoveDuplicateInsideComments = 0x08, 23 | 24 | [CleanupItem(FirstOrder = 1, Title = "No duplicate blank lines between \"Usings ..\"")] 25 | RemoveDuplicateInsideUsings = 0x10, 26 | 27 | [CleanupItem(FirstOrder = 1, Title = "No blank lines immediately after { and immediately before }")] 28 | RemoveBlankAfterOpenBracketAndBeforeCloseBrackets = 0x20, 29 | 30 | /// 31 | /// Insert_one_space_between_the_comment_delimiter_and_the_comment_text, 32 | /// 33 | [CleanupItem(FirstOrder = 1, Title = "Space before comment text: //TODO: => // TODO:")] 34 | Insert_Space_Before_Comment_Text = 0x40, 35 | 36 | [CleanupItem(FirstOrder = 1, Title = "Blank line between methods.")] 37 | Adding_Blank_After_Method_Close_Bracket = 0x100, 38 | 39 | [CleanupItem(FirstOrder = 1, Title = "Blank line between } and the next statement.")] 40 | Adding_Blank_After_Block_Close_Bracket = 0x200, 41 | 42 | [CleanupItem(FirstOrder = 1, Title = "No { and } for short blocks (single statement and < 80 chars)")] 43 | Remove_Brackets_Of_Block_That_Has_Only_One_Statement_With_Length_Shorter_Than_80_Chars = 0x400, 44 | 45 | [CleanupItem(FirstOrder = 1, Title = "Add Blank line between Statements more that one line")] 46 | Add_Blank_Line_Between_Statements_More_Than_One_Line = 0x500, 47 | 48 | [CleanupItem(FirstOrder = 1, Title = "Use \\n instead of \\r\\n")] 49 | Use_Slash_Instead_Of_Slash_Slash = 0x600, 50 | 51 | [CleanupItem(FirstOrder = 1, Title = "Add an empty line after using statements")] 52 | Add_An_Empty_Line_After_Using_Statements = 0x700, 53 | } 54 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/ActionsOnCSharp/ActionCSharpOnAnyWhere.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using Geeks.GeeksProductivityTools.Utils; 3 | using Geeks.VSIX.TidyCSharp.Cleanup.CommandsHandlers; 4 | using System; 5 | using static Geeks.GeeksProductivityTools.Menus.ActionsOnCSharp.CSharpAction; 6 | 7 | namespace Geeks.GeeksProductivityTools.Menus.ActionsOnCSharp 8 | { 9 | public sealed class ActionCSharpOnAnywhere 10 | { 11 | private ActionCSharpOnAnywhere() { } 12 | public static void Invoke(TargetAction action, CleanupOptions cleanupOptions) 13 | { 14 | try 15 | { 16 | var ideSelectedItems = DteServiceProvider.Instance.SelectedItems; 17 | 18 | for (int itemIndex = 1; itemIndex <= ideSelectedItems.Count; itemIndex++) 19 | { 20 | var selectItem = ideSelectedItems.Item(itemIndex); 21 | 22 | var selectedProjectItem = selectItem.ProjectItem; 23 | 24 | if (selectedProjectItem != null) 25 | { 26 | if (selectedProjectItem.ProjectItems == null || selectedProjectItem.ProjectItems.Count == 0 && action != null) 27 | { 28 | action(selectedProjectItem, cleanupOptions, true); 29 | } 30 | else 31 | { 32 | ActionCSharpOnProjectItem.Action(selectedProjectItem, action, cleanupOptions); 33 | } 34 | } 35 | else if (selectItem.Project != null) 36 | { 37 | ActionCSharpOnProject.Invoke(action, cleanupOptions); 38 | } 39 | else 40 | { 41 | ActionCSharpOnSolution.Invoke(action, cleanupOptions); 42 | } 43 | } 44 | } 45 | catch (Exception e) 46 | { 47 | ErrorNotification.WriteErrorToFile(e); 48 | ErrorNotification.WriteErrorToOutputWindow(e); 49 | ProcessActions.GeeksProductivityToolsProcess(); 50 | } 51 | } 52 | 53 | //static void DoActionForItems(ProjectItems projectItems, TargetAction action, CleanupOptions cleanupOptions) 54 | //{ 55 | // for (int subItemIndex = 1; subItemIndex <= projectItems.Count; subItemIndex++) 56 | // { 57 | // var subItem = projectItems.Item(subItemIndex); 58 | // ActionCSharpOnProjectItem.Action(subItem, action, cleanupOptions); 59 | // } 60 | //} 61 | } 62 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/Whitespace/BlankLineRewriter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System.Linq; 5 | 6 | namespace Geeks.VSIX.TidyCSharp.Cleanup.NormalizeWhiteSpace 7 | { 8 | public class BlankLineRewriter : CSharpSyntaxRewriterBase 9 | { 10 | SemanticModel semanticModel; 11 | public BlankLineRewriter(SyntaxNode node, bool isReadOnlyMode, SemanticModel semanticModel) : 12 | base(node, isReadOnlyMode, null) => this.semanticModel = semanticModel; 13 | public override SyntaxNode VisitBlock(BlockSyntax node) 14 | { 15 | var writeTrailing = false; 16 | 17 | node = node.ReplaceNodes(node.Statements, (nde1, nde2) => 18 | { 19 | if (nde1.WithoutLeadingTrivia().WithoutTrailingTrivia() 20 | .DescendantTrivia().Any(x => x.IsKind(SyntaxKind.EndOfLineTrivia))) 21 | { 22 | var leading = nde1.GetLeadingTrivia(); 23 | var trailing = nde1.GetTrailingTrivia(); 24 | 25 | var leadingTrivias = new SyntaxTriviaList(SyntaxFactory.EndOfLine("\n")); 26 | 27 | if (nde1.Equals(node.Statements.FirstOrDefault()) || writeTrailing || 28 | nde1.GetLeadingTrivia().Count(x => x.IsKind(SyntaxKind.EndOfLineTrivia)) > 0) 29 | { 30 | leadingTrivias = new SyntaxTriviaList(); 31 | writeTrailing = false; 32 | } 33 | 34 | var trailingTrivias = new SyntaxTriviaList(); 35 | 36 | leadingTrivias = leadingTrivias.AddRange(leading); 37 | 38 | trailingTrivias = trailingTrivias.AddRange(trailing); 39 | 40 | if (!nde1.Equals(node.Statements.LastOrDefault()) && 41 | (node.Statements.IndexOf(nde1) + 1 < node.Statements.Count() && 42 | node.Statements[node.Statements.IndexOf(nde1) + 1] 43 | .GetLeadingTrivia().Count(x => x.IsKind(SyntaxKind.EndOfLineTrivia)) < 1)) 44 | { 45 | writeTrailing = true; 46 | trailingTrivias = trailingTrivias.Add(SyntaxFactory.EndOfLine("\n")); 47 | } 48 | 49 | return nde2.WithTrailingTrivia(trailingTrivias) 50 | .WithLeadingTrivia(leadingTrivias); 51 | } 52 | 53 | writeTrailing = false; 54 | return nde2; 55 | }); 56 | 57 | return base.VisitBlock(node); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/RenameHelper/CONSTRenamer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 9 | { 10 | class CONSTRenamer : Renamer 11 | { 12 | public CONSTRenamer(Document document) : base(document) 13 | { 14 | } 15 | 16 | protected override IEnumerable GetItemsToRename(SyntaxNode currentNode) 17 | { 18 | var output = new List(); 19 | 20 | { 21 | var selectedFields = 22 | (currentNode as ClassDeclarationSyntax) 23 | .Members.OfType() 24 | .Where( 25 | x => 26 | x.Modifiers.Any(m => m.IsKind(SyntaxKind.ConstKeyword)) && 27 | IsPrivate(x) 28 | ); 29 | 30 | foreach (var item in selectedFields) 31 | output.AddRange(item.Declaration.Variables); 32 | } 33 | 34 | { 35 | var selectedFields = 36 | (currentNode as ClassDeclarationSyntax) 37 | .DescendantNodes().OfType() 38 | .Where( 39 | x => 40 | x.Modifiers.Any(m => m.IsKind(SyntaxKind.ConstKeyword)) 41 | ); 42 | 43 | foreach (var item in selectedFields) 44 | output.AddRange(item.Declaration.Variables); 45 | } 46 | 47 | return output.Select(x => x.Identifier); 48 | } 49 | 50 | protected override string[] GetNewName(string currentName) 51 | { 52 | const char UNDERLINE = '_'; 53 | 54 | var newNameBuilder = new StringBuilder(); 55 | var lastCharIsLowwer = false; 56 | 57 | foreach (var c in currentName) 58 | { 59 | if (char.IsUpper(c)) 60 | { 61 | if (lastCharIsLowwer) 62 | { 63 | newNameBuilder.Append(UNDERLINE); 64 | } 65 | 66 | lastCharIsLowwer = false; 67 | } 68 | else if (c != UNDERLINE) lastCharIsLowwer = true; 69 | 70 | newNameBuilder.Append(c); 71 | } 72 | 73 | if (string.Compare(currentName, currentName.ToUpper(), false) == 0) return null; 74 | 75 | return new[] { newNameBuilder.ToString().ToUpper() }; 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /TidyCSharp/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | True 21 | 22 | 23 | True 24 | 25 | 26 | .gif;.jpg;.png;.bmp;.resx;.ico;.bat;.tif;.psd;.sln;.suo;.csproj;.user;.cd;.lic;_reset.css;.html;.jsm;.map;.cache;vsdoc;.dat;.force;.map;.md;.rtf;.tmp 27 | 28 | 29 | 30 | @Temp\Validation;@CuteSoft;@Coder.Meta;.svn;node_modules;bower_components;public;obj 31 | 32 | 33 | 34 | False 35 | 36 | 37 | True 38 | 39 | 40 | False 41 | 42 | 43 | False 44 | 45 | 46 | True 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /TidyCSharp/Environment/ErrorList.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.Shell; 2 | 3 | namespace Geeks.GeeksProductivityTools 4 | { 5 | public static class ErrorList 6 | { 7 | //static ErrorListProvider _errorListProvider; 8 | // static Dictionary ListOfErrors = new Dictionary(); 9 | 10 | // public static void AddOrOverrideError(string key, Microsoft.VisualStudio.Shell.Task task) 11 | // { 12 | // if (ListOfErrors.ContainsKey(key)) 13 | // { 14 | // ListOfErrors[key] = task; 15 | // } 16 | // else 17 | // { 18 | // ListOfErrors.Add(key, task); 19 | // } 20 | 21 | // if (task is ErrorTask) 22 | // { 23 | // WriteVisualStudioErrorList(task as ErrorTask); 24 | // } 25 | // } 26 | 27 | // public static void RemoveError(string key) 28 | // { 29 | // if (string.IsNullOrEmpty(key)) 30 | // return; 31 | 32 | // if (ListOfErrors.ContainsKey(key)) 33 | // { 34 | // var task = ListOfErrors[key]; 35 | // if (task == null) 36 | // return; 37 | 38 | // if (task is ErrorTask) 39 | // { 40 | // _errorListProvider.Tasks.Remove(task); 41 | // } 42 | 43 | // ListOfErrors.Remove(key); 44 | // } 45 | // } 46 | 47 | /// 48 | /// Write an entry to the Visual Studio Error List. 49 | /// 50 | // static void WriteVisualStudioErrorList(ErrorTask errorTask) 51 | // { 52 | // if (_errorListProvider == null) 53 | // { 54 | // _errorListProvider = new ErrorListProvider(TidyCSharpPackage.Instance); 55 | // } 56 | 57 | // // Check if this error is already in the error list, don't report more than once 58 | // var alreadyReported = false; 59 | // foreach (ErrorTask task in _errorListProvider.Tasks) 60 | // { 61 | // if (task.ErrorCategory == errorTask.ErrorCategory && 62 | // task.Document == errorTask.Document && 63 | // task.Line == errorTask.Line && 64 | // task.Column == errorTask.Column && 65 | // task.Text == errorTask.Text) 66 | // { 67 | // alreadyReported = true; 68 | // break; 69 | // } 70 | // } 71 | 72 | // if (!alreadyReported) 73 | // { 74 | // // Add error to task list 75 | // _errorListProvider.Tasks.Add(errorTask); 76 | // } 77 | // } 78 | } 79 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/PrivateModifierRemover/PrivateModifierRemover.cs: -------------------------------------------------------------------------------- 1 | using Geeks.GeeksProductivityTools.Menus.Cleanup; 2 | using Geeks.VSIX.TidyCSharp.Cleanup.RemovePrivateModifier; 3 | using Microsoft.CodeAnalysis; 4 | using System.Threading.Tasks; 5 | 6 | namespace Geeks.VSIX.TidyCSharp.Cleanup 7 | { 8 | public class PrivateModifierRemover : CodeCleanerCommandRunnerBase, ICodeCleaner 9 | { 10 | public override async Task CleanUpAsync(SyntaxNode initialSourceNode) 11 | { 12 | return RemoveExplicitPrivateModifiers(initialSourceNode); 13 | } 14 | 15 | SyntaxNode RemoveExplicitPrivateModifiers(SyntaxNode actualSourceCode) 16 | { 17 | var modifiedSourceNode = actualSourceCode; 18 | 19 | if (CheckOption((int)CleanupTypes.RemoveClassMethodsPrivateModifier)) 20 | { 21 | var remover = new MethodTokenRemover(IsReportOnlyMode); 22 | modifiedSourceNode = remover.Remove(modifiedSourceNode) ?? modifiedSourceNode; 23 | 24 | if (IsReportOnlyMode && !IsEquivalentToUNModified(modifiedSourceNode)) 25 | { 26 | CollectMessages(remover.GetReport()); 27 | } 28 | } 29 | 30 | if (CheckOption((int)CleanupTypes.RemoveClassFieldsPrivateModifier)) 31 | { 32 | var remover = new FieldTokenRemover(IsReportOnlyMode); 33 | modifiedSourceNode = remover.Remove(modifiedSourceNode) ?? modifiedSourceNode; 34 | 35 | if (IsReportOnlyMode && !IsEquivalentToUNModified(modifiedSourceNode)) 36 | { 37 | CollectMessages(remover.GetReport()); 38 | } 39 | } 40 | 41 | if (CheckOption((int)CleanupTypes.RemoveClassPropertiesPrivateModifier)) 42 | { 43 | var remover = new PropertyTokenRemover(IsReportOnlyMode); 44 | modifiedSourceNode = remover.Remove(modifiedSourceNode) ?? modifiedSourceNode; 45 | 46 | if (IsReportOnlyMode && !IsEquivalentToUNModified(modifiedSourceNode)) 47 | { 48 | CollectMessages(remover.GetReport()); 49 | } 50 | } 51 | 52 | if (CheckOption((int)CleanupTypes.RemoveNestedClassPrivateModifier)) 53 | { 54 | var remover = new NestedClassTokenRemover(IsReportOnlyMode); 55 | modifiedSourceNode = remover.Remove(modifiedSourceNode) ?? modifiedSourceNode; 56 | 57 | if (IsReportOnlyMode && !IsEquivalentToUNModified(modifiedSourceNode)) 58 | { 59 | CollectMessages(remover.GetReport()); 60 | } 61 | } 62 | 63 | if (IsReportOnlyMode) return actualSourceCode; 64 | return modifiedSourceNode; 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /TidyCSharp/source.extension.vsixmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tidy C# 6 | Clean up your C# code. 7 | http://geeks.ltd 8 | Resources\icon.png 9 | Resources\Preview.png 10 | extensions, geeks, geeks ltd, productivity tools, productivity 11 | 12 | 13 | 14 | x86 15 | 16 | 17 | amd64 18 | 19 | 20 | x86 21 | 22 | 23 | amd64 24 | 25 | 26 | x86 27 | 28 | 29 | amd64 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/UsingDirectiveOrganizer.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using Geeks.GeeksProductivityTools; 3 | using Geeks.GeeksProductivityTools.Definition; 4 | using Geeks.GeeksProductivityTools.Menus.Cleanup; 5 | using Geeks.GeeksProductivityTools.Utils; 6 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors; 7 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 8 | using Microsoft.CodeAnalysis; 9 | using Microsoft.CodeAnalysis.CSharp; 10 | using Microsoft.VisualStudio.Shell; 11 | using System; 12 | using System.Threading.Tasks; 13 | 14 | namespace Geeks.VSIX.TidyCSharp.Cleanup 15 | { 16 | public class UsingDirectiveOrganizer : CodeCleanerCommandRunnerBase, ICodeCleaner 17 | { 18 | public override async Task CleanUpAsync(SyntaxNode initialSourceNode) 19 | { 20 | var item = ProjectItemDetails.ProjectItem; 21 | 22 | try 23 | { 24 | await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); 25 | 26 | item.Open(Constants.vsViewKindCode); 27 | 28 | var document = item.Document; 29 | document.Activate(); 30 | 31 | try { document.DTE.ExecuteCommand(UsingsCommands.RemoveAndSortCommandName); } 32 | catch (Exception ex) 33 | { 34 | if (ex.Message != "Command \"Edit.RemoveAndSort\" is not available.") throw; 35 | 36 | document.Activate(); 37 | document.DTE.ExecuteCommand(UsingsCommands.RemoveAndSortCommandName); 38 | } 39 | 40 | var doc = (EnvDTE.TextDocument)(document.Object("TextDocument")); 41 | var p = doc.StartPoint.CreateEditPoint(); 42 | var s = p.GetText(doc.EndPoint); 43 | var modified = SyntaxFactory.ParseSyntaxTree(s); 44 | 45 | if (IsReportOnlyMode && 46 | !IsEquivalentToUNModified(await modified.GetRootAsync())) 47 | { 48 | CollectMessages(new ChangesReport(initialSourceNode) 49 | { 50 | LineNumber = 1, 51 | Column = 1, 52 | Message = "Your Using usage is not good", 53 | Generator = nameof(UsingDirectiveOrganizer) 54 | }); 55 | 56 | document.Undo(); 57 | return initialSourceNode; 58 | } 59 | 60 | document.Save(); 61 | } 62 | catch (Exception e) 63 | { 64 | ErrorNotification.WriteErrorToFile(e, initialSourceNode.GetFilePath()); 65 | ErrorNotification.WriteErrorToOutputWindow(e, initialSourceNode.GetFilePath()); 66 | ProcessActions.GeeksProductivityToolsProcess(); 67 | } 68 | 69 | return item.ToSyntaxNode(); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # MSTest test Results 19 | [Tt]est[Rr]esult*/ 20 | [Bb]uild[Ll]og.* 21 | 22 | *_i.c 23 | *_p.c 24 | *.ilk 25 | *.meta 26 | *.obj 27 | *.pch 28 | *.pdb 29 | *.pgc 30 | *.pgd 31 | *.rsp 32 | *.sbr 33 | *.tlb 34 | *.tli 35 | *.tlh 36 | *.tmp 37 | *.tmp_proj 38 | *.log 39 | *.vspscc 40 | *.vssscc 41 | .builds 42 | *.pidb 43 | *.log 44 | *.scc 45 | 46 | # Visual C++ cache files 47 | ipch/ 48 | *.aps 49 | *.ncb 50 | *.opensdf 51 | *.sdf 52 | *.cachefile 53 | 54 | # Visual Studio profiler 55 | *.psess 56 | *.vsp 57 | *.vspx 58 | 59 | # Guidance Automation Toolkit 60 | *.gpState 61 | 62 | # ReSharper is a .NET coding add-in 63 | _ReSharper*/ 64 | *.[Rr]e[Ss]harper 65 | 66 | # TeamCity is a build add-in 67 | _TeamCity* 68 | 69 | # DotCover is a Code Coverage Tool 70 | *.dotCover 71 | 72 | # NCrunch 73 | *.ncrunch* 74 | .*crunch*.local.xml 75 | 76 | # Installshield output folder 77 | [Ee]xpress/ 78 | 79 | # DocProject is a documentation generator add-in 80 | DocProject/buildhelp/ 81 | DocProject/Help/*.HxT 82 | DocProject/Help/*.HxC 83 | DocProject/Help/*.hhc 84 | DocProject/Help/*.hhk 85 | DocProject/Help/*.hhp 86 | DocProject/Help/Html2 87 | DocProject/Help/html 88 | 89 | # Click-Once directory 90 | publish/ 91 | 92 | # Publish Web Output 93 | *.Publish.xml 94 | *.pubxml 95 | 96 | # NuGet Packages Directory 97 | packages/ 98 | 99 | # Windows Azure Build Output 100 | csx 101 | *.build.csdef 102 | 103 | # Windows Store app package directory 104 | AppPackages/ 105 | 106 | # Others 107 | sql/ 108 | *.Cache 109 | ClientBin/ 110 | [Ss]tyle[Cc]op.* 111 | ~$* 112 | *~ 113 | *.dbmdl 114 | *.[Pp]ublish.xml 115 | *.pfx 116 | *.publishsettings 117 | 118 | # RIA/Silverlight projects 119 | Generated_Code/ 120 | 121 | # Backup & report files from converting an old project file to a newer 122 | # Visual Studio version. Backup files are not needed, because we have git ;-) 123 | _UpgradeReport_Files/ 124 | Backup*/ 125 | UpgradeLog*.XML 126 | UpgradeLog*.htm 127 | 128 | # SQL Server files 129 | App_Data/*.mdf 130 | App_Data/*.ldf 131 | 132 | 133 | #LightSwitch generated files 134 | GeneratedArtifacts/ 135 | _Pvt_Extensions/ 136 | ModelManifest.xml 137 | 138 | # ========================= 139 | # Windows detritus 140 | # ========================= 141 | 142 | # Windows image file caches 143 | Thumbs.db 144 | ehthumbs.db 145 | 146 | # Folder config file 147 | Desktop.ini 148 | 149 | # Recycle Bin used on file shares 150 | $RECYCLE.BIN/ 151 | 152 | # Mac desktop service store files 153 | .DS_Store 154 | .vs 155 | /GeeksProductivityBase 156 | /TidyCSharpTotall.sln 157 | /__temp 158 | /TestCase 159 | *.rar 160 | -------------------------------------------------------------------------------- /TidyCSharp/Extensions/DteExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace GeeksAddin 2 | { 3 | using EnvDTE; 4 | using EnvDTE80; 5 | using Geeks.GeeksProductivityTools; 6 | using System; 7 | using System.Linq; 8 | 9 | static class DteExtensions 10 | { 11 | /// 12 | /// Returns the selected text or null if selected text cannot be found 13 | /// 14 | // //public static string GetSelectedText(this DTE2 app) 15 | // //{ 16 | // // if (app.ActiveDocument != null) 17 | // // { 18 | // // dynamic selection = app.ActiveDocument.Selection; 19 | // // if (selection != null) 20 | // // { 21 | // // var selectedText = selection.Text as string; 22 | // // if (selectedText.HasValue()) 23 | // // return selectedText; 24 | // // } 25 | // // } 26 | 27 | // // return null; 28 | // //} 29 | 30 | // public static string GetCurrentProjectPath(this DTE2 app) 31 | // { 32 | // if (app.ActiveDocument == null) 33 | // return null; 34 | 35 | // var documentPath = app.ActiveDocument.Path.ToLower(); 36 | // var allProjectPaths = Utils.FindSolutionDirectories(app); 37 | 38 | // if (allProjectPaths == null) return documentPath; 39 | 40 | // return allProjectPaths.FirstOrDefault(p => documentPath.StartsWith(p.ToLower())); 41 | // } 42 | 43 | ///Gets the full paths to the currently selected item(s) in the Solution Explorer. 44 | // //public static IEnumerable GetSelectedItemPaths() 45 | // //{ 46 | // // var items = (Array)App.DTE.ToolWindows.SolutionExplorer.SelectedItems; 47 | // // foreach (UIHierarchyItem selItem in items) 48 | // // { 49 | 50 | // // if (selItem.Object is ProjectItem item) 51 | // // yield return item.Properties.Item("FullPath").Value.ToString(); 52 | // // } 53 | // //} 54 | 55 | // /////Gets the full paths to the currently selected item(s) in the Solution Explorer. 56 | // //public static IEnumerable GetRelativeItemPaths() 57 | // //{ 58 | // // return GetSelectedItemPaths().Select(fullPath => fullPath.Remove(System.IO.Path.GetDirectoryName(App.DTE.Solution.FullName))); 59 | // //} 60 | 61 | public const string SolutionItemsFolder = "Solution Items"; 62 | 63 | ///Gets the Solution Items solution folder in the current solution, creating it if it doesn't exist. 64 | public static Project GetSolutionItemsProject() 65 | { 66 | var solution = App.Dte.Solution as Solution2; 67 | 68 | return solution.Projects 69 | .OfType() 70 | .FirstOrDefault(p => p.Name.Equals(SolutionItemsFolder, StringComparison.OrdinalIgnoreCase)) 71 | ?? solution.AddSolutionFolder(SolutionItemsFolder); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /TidyCSharp/ErrorNotification/ErrorNotification.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.Shell; 2 | using Microsoft.VisualStudio.Shell.Interop; 3 | using System; 4 | using System.IO; 5 | 6 | namespace Geeks.GeeksProductivityTools 7 | { 8 | internal static class ErrorNotification 9 | { 10 | static IVsOutputWindowPane customPane; 11 | 12 | internal static void EmailError(string message) 13 | { 14 | 15 | } 16 | 17 | static ErrorNotification() 18 | { 19 | var outWindow = Package.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow; 20 | 21 | var customGuid = new Guid("0F44E2D1-F5FA-4d2d-AB30-22BE8ECD9789"); 22 | var customTitle = "TidyC# Debug Output"; 23 | outWindow.CreatePane(ref customGuid, customTitle, 1, 1); 24 | 25 | outWindow.GetPane(ref customGuid, out customPane); 26 | } 27 | internal static void WriteErrorToOutputWindow(Exception ex, string itemAddress = null) 28 | { 29 | customPane.OutputString(Newtonsoft.Json.JsonConvert.SerializeObject(new 30 | { 31 | FileAddress = itemAddress, 32 | Exception = ex 33 | }) + "\n"); 34 | 35 | customPane.Activate(); 36 | } 37 | 38 | internal static void WriteErrorToFile(Exception ex, string itemAddress = null) 39 | { 40 | File.AppendAllText(Path.GetDirectoryName(App.Dte.Solution.FileName) + "\\Tidy.Error.log", 41 | Newtonsoft.Json.JsonConvert.SerializeObject(new 42 | { 43 | FileAddress = itemAddress, 44 | Exception = ex, 45 | })); 46 | } 47 | 48 | //internal static void EmailError(Exception ex) 49 | //{ 50 | // // System.Windows.Forms.MessageBox.Show(ex.Message); 51 | 52 | // // TODO: Add feature to Settings for sending the error log to the dev team if requested by end users 53 | 54 | // // var message = new MailMessage("Geeks.Productivity.Tools@gmail.com", 55 | // // "ali.ashoori@geeks.ltd.uk", 56 | // // $"Error from Geeks Productivity Tools {DateTime.Now.Date}", GenerateErrorBody(ex)) 57 | // // { 58 | // // IsBodyHtml = true 59 | // // }; 60 | 61 | // // var client = new SmtpClient("smtp.gmail.com", 587) 62 | // // { 63 | // // Credentials = new NetworkCredential("Geeks.Productivity.Tools@gmail.com", "Espresso123"), 64 | // // EnableSsl = true 65 | // // }; 66 | // // client.Send(message); 67 | //} 68 | 69 | //static string GenerateErrorBody(Exception e) 70 | //{ 71 | // return "Message:" + "

" + e.Message + "

" + "
" + 72 | // "Inner exception message:" + "

" + e.InnerException?.Message + "

" + "
" + 73 | // "Stack Trace:" + "

" + e.StackTrace + "

"; 74 | //} 75 | } 76 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/Whitespace/WhiteSpaceNormalizer.cs: -------------------------------------------------------------------------------- 1 | using Geeks.GeeksProductivityTools; 2 | using Geeks.GeeksProductivityTools.Menus.Cleanup; 3 | using Geeks.VSIX.TidyCSharp.Cleanup.NormalizeWhiteSpace; 4 | using Microsoft.CodeAnalysis; 5 | using Microsoft.CodeAnalysis.Formatting; 6 | using System.Threading.Tasks; 7 | 8 | namespace Geeks.VSIX.TidyCSharp.Cleanup 9 | { 10 | public class WhiteSpaceNormalizer : CodeCleanerCommandRunnerBase, ICodeCleaner 11 | { 12 | public override async Task CleanUpAsync(SyntaxNode initialSourceNode) 13 | { 14 | return await NormalizeWhiteSpaceHelperAsync(initialSourceNode, Options); 15 | } 16 | 17 | public Options Options { get; set; } 18 | 19 | public async Task NormalizeWhiteSpaceHelperAsync(SyntaxNode initialSourceNode, Options options) 20 | { 21 | var modifiedSourceNode = initialSourceNode; 22 | 23 | if (TidyCSharpPackage.Instance != null) 24 | { 25 | modifiedSourceNode = Formatter.Format(modifiedSourceNode, TidyCSharpPackage.Instance.CleanupWorkingSolution.Workspace); 26 | } 27 | 28 | var blockRewriter = new BlockRewriter(modifiedSourceNode, IsReportOnlyMode, options); 29 | modifiedSourceNode = blockRewriter.Visit(modifiedSourceNode); 30 | 31 | if (IsReportOnlyMode) 32 | { 33 | CollectMessages(blockRewriter.GetReport()); 34 | } 35 | 36 | modifiedSourceNode = await RefreshResultAsync(modifiedSourceNode); 37 | 38 | if (CheckOption((int)CleanupTypes.Use_Slash_Instead_Of_Slash_Slash)) 39 | { 40 | var endoflineRewriter = new EndOFLineRewriter(modifiedSourceNode, IsReportOnlyMode, options); 41 | modifiedSourceNode = endoflineRewriter.Visit(modifiedSourceNode); 42 | modifiedSourceNode = await RefreshResultAsync(modifiedSourceNode); 43 | 44 | if (IsReportOnlyMode) 45 | { 46 | CollectMessages(endoflineRewriter.GetReport()); 47 | } 48 | } 49 | 50 | var whitespaceRewriter = new WhiteSpaceRewriter(modifiedSourceNode, IsReportOnlyMode, options); 51 | modifiedSourceNode = whitespaceRewriter.Apply(); 52 | 53 | if (IsReportOnlyMode) 54 | { 55 | CollectMessages(whitespaceRewriter.GetReport()); 56 | } 57 | 58 | if (CheckOption((int)CleanupTypes.Add_Blank_Line_Between_Statements_More_Than_One_Line)) 59 | { 60 | modifiedSourceNode = await RefreshResultAsync(modifiedSourceNode); 61 | var blRewriter = new BlankLineRewriter(modifiedSourceNode, IsReportOnlyMode, ProjectItemDetails.SemanticModel); 62 | modifiedSourceNode = blRewriter.Visit(modifiedSourceNode); 63 | 64 | if (IsReportOnlyMode) 65 | { 66 | CollectMessages(blRewriter.GetReport()); 67 | } 68 | } 69 | 70 | if (IsReportOnlyMode) return initialSourceNode; 71 | return modifiedSourceNode; 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/ZebbleCleaner.cs: -------------------------------------------------------------------------------- 1 | using Geeks.GeeksProductivityTools.Menus.Cleanup; 2 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 3 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors; 4 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using Microsoft.CodeAnalysis.CSharp.Syntax; 8 | using System.Linq; 9 | using System.Reflection; 10 | using System.Threading.Tasks; 11 | 12 | namespace Geeks.VSIX.TidyCSharp.Cleanup 13 | { 14 | public class ZebbleCleaner : CodeCleanerCommandRunnerBase, ICodeCleaner 15 | { 16 | public override async Task CleanUpAsync(SyntaxNode initialSourceNode) 17 | { 18 | if (ProjectItemDetails.SemanticModel is null) return initialSourceNode; 19 | 20 | var syntaxRewriter = new ReadOnlyRewriter(ProjectItemDetails.SemanticModel, IsReportOnlyMode, Options); 21 | var modifiedSourceNode = syntaxRewriter.Visit(initialSourceNode); 22 | 23 | if (IsReportOnlyMode) 24 | { 25 | CollectMessages(syntaxRewriter.GetReport()); 26 | return initialSourceNode; 27 | } 28 | 29 | return modifiedSourceNode; 30 | } 31 | 32 | class ReadOnlyRewriter : CleanupCSharpSyntaxRewriter 33 | { 34 | SemanticModel semanticModel; 35 | 36 | public ReadOnlyRewriter(SemanticModel semanticModel, bool isReportOnlyMode, ICleanupOption options) 37 | : base(isReportOnlyMode, options) 38 | { 39 | this.semanticModel = semanticModel; 40 | this.isReportOnlyMode = isReportOnlyMode; 41 | } 42 | public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) 43 | { 44 | if (node.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)) return node; 45 | if (semanticModel.GetTypeInfo(node.Declaration.Type).Type.Name != "Bindable") return node; 46 | if (!node.Declaration.Type.IsKind(SyntaxKind.GenericName)) return node; 47 | 48 | if (semanticModel.GetTypeInfo(node.Declaration.Type).Type.ContainingNamespace.Name != "Zebble" && 49 | semanticModel.GetTypeInfo(node.Declaration.Type).Type.ContainingNamespace.Name != "Olive") 50 | return node; 51 | 52 | if (isReportOnlyMode) 53 | { 54 | var lineSpan = node.GetFileLinePosSpan(); 55 | 56 | AddReport(new ChangesReport(node) 57 | { 58 | LineNumber = lineSpan.StartLinePosition.Line, 59 | Column = lineSpan.StartLinePosition.Character, 60 | Message = "Should Add Readonly Modifier", 61 | Generator = nameof(ZebbleCleaner) 62 | }); 63 | 64 | return node; 65 | } 66 | 67 | return node.AddModifiers( 68 | SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword) 69 | .WithTrailingTrivia(SyntaxFactory.ParseTrailingTrivia(" "))); 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/RenameHelper/VariableRenamingBase.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 3 | using Microsoft.CodeAnalysis; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 8 | { 9 | public abstract class VariableRenamingBase : CodeCleanerCommandRunnerBase, ICodeCleaner 10 | { 11 | const string SELECTED_METHOD_ANNOTATION = "SELECTED_METHOD_ANNOTATION"; 12 | 13 | Document WorkingDocument, orginalDocument; 14 | 15 | public override async Task CleanUpAsync(SyntaxNode initialSourceNode) 16 | { 17 | var annotationForSelectedNode = new SyntaxAnnotation(SELECTED_METHOD_ANNOTATION); 18 | orginalDocument = ProjectItemDetails.ProjectItemDocument; 19 | WorkingDocument = ProjectItemDetails.ProjectItemDocument; 20 | 21 | if (orginalDocument == null) return initialSourceNode; 22 | 23 | SyntaxNode workingNode; 24 | var annotatedRoot = initialSourceNode; 25 | 26 | do 27 | { 28 | workingNode = GetWorkingNode(annotatedRoot, annotationForSelectedNode); 29 | 30 | if (workingNode == null) continue; 31 | 32 | var annotatedNode = workingNode.WithAdditionalAnnotations(annotationForSelectedNode); 33 | annotatedRoot = annotatedRoot.ReplaceNode(workingNode, annotatedNode); 34 | WorkingDocument = WorkingDocument.WithSyntaxRoot(annotatedRoot); 35 | annotatedRoot = await WorkingDocument.GetSyntaxRootAsync(); 36 | annotatedNode = annotatedRoot.GetAnnotatedNodes(annotationForSelectedNode).FirstOrDefault(); 37 | 38 | var rewriter = GetRewriter(WorkingDocument); 39 | 40 | rewriter.Visit(annotatedNode); 41 | CollectMessages(rewriter.GetReport()); 42 | WorkingDocument = rewriter.WorkingDocument; 43 | } while (workingNode != null); 44 | 45 | return null; 46 | } 47 | 48 | protected override async Task SaveResultAsync(SyntaxNode initialSourceNode) 49 | { 50 | if (WorkingDocument is null) return; 51 | 52 | var text = await WorkingDocument.GetTextAsync(); 53 | 54 | if (string.Compare(text?.ToString(), ProjectItemDetails.InitialSourceNode.GetText().ToString(), false) != 0) 55 | { 56 | await TidyCSharpPackage.Instance.RefreshSolutionAsync(WorkingDocument.Project.Solution); 57 | } 58 | } 59 | 60 | protected abstract SyntaxNode GetWorkingNode(SyntaxNode initialSourceNode, SyntaxAnnotation annotationForSelectedNodes); 61 | 62 | protected abstract VariableRenamingBaseRewriter GetRewriter(Document workingDocument); 63 | 64 | protected abstract class VariableRenamingBaseRewriter : CleanupCSharpSyntaxRewriter 65 | { 66 | public Document WorkingDocument { get; protected set; } 67 | protected VariableRenamingBaseRewriter(Document workingDocument, bool isReportOnlyMode, ICleanupOption options) : base(isReportOnlyMode, options) 68 | { 69 | WorkingDocument = workingDocument; 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /TidyCSharp/Extensions/RunCodeAnalysisRulesCommand.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using EnvDTE80; 3 | using Microsoft.VisualStudio.Shell; 4 | using Microsoft.VisualStudio.Shell.Interop; 5 | using System; 6 | using System.Linq; 7 | using System.Runtime.InteropServices; 8 | 9 | namespace Geeks.VSIX.TidyCSharp.Extensions 10 | { 11 | public class RunCodeAnalysisRulesCommand 12 | { 13 | bool _overallBuildSuccess, _customBuildInProgress; 14 | 15 | //void CustomBuild_MenuItemCallback(object sender, EventArgs e) 16 | //{ 17 | // // Listen to the necessary build events. 18 | // var dte = (DTE2)Package.GetGlobalService(typeof(SDTE)); 19 | // dte.Events.BuildEvents.OnBuildDone += BuildEvents_OnBuildDone; 20 | // dte.Events.BuildEvents.OnBuildProjConfigDone += BuildEvents_OnBuildProjConfigDone; 21 | 22 | // try 23 | // { 24 | // // Build the active project. 25 | // _customBuildInProgress = true; 26 | // dte.ExecuteCommand("Build.BuildSelection"); 27 | // } 28 | // catch (COMException) 29 | // { 30 | // _customBuildInProgress = false; 31 | // WriteToOutputWindow("Build", "Could not determine project to build from selection"); 32 | // } 33 | //} 34 | 35 | void BuildEvents_OnBuildProjConfigDone(string project, string projectConfig, string platform, string solutionConfig, bool success) 36 | { 37 | // Ignore this build event if we didn't start it. 38 | if (!_customBuildInProgress) 39 | { 40 | return; 41 | } 42 | 43 | // Keep track of the overall build success. 44 | _overallBuildSuccess = success; 45 | } 46 | 47 | void BuildEvents_OnBuildDone(EnvDTE.vsBuildScope scope, EnvDTE.vsBuildAction action) 48 | { 49 | // Ignore this build event if we didn't start it. 50 | if (!_customBuildInProgress) 51 | { 52 | return; 53 | } 54 | 55 | _customBuildInProgress = false; 56 | 57 | if (_overallBuildSuccess) 58 | { 59 | // Launch the debugger. 60 | var dte = (DTE2)Package.GetGlobalService(typeof(SDTE)); 61 | dte.ExecuteCommand("Debug.Start"); 62 | } 63 | else 64 | { 65 | WriteToOutputWindow("Build", "Custom build failed."); 66 | } 67 | } 68 | 69 | void WriteToOutputWindow(string paneName, string message) 70 | { 71 | var dte = (DTE2)Package.GetGlobalService(typeof(SDTE)); 72 | 73 | var window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput); 74 | var outputWindow = (OutputWindow)window.Object; 75 | 76 | var targetPane = outputWindow.OutputWindowPanes.Cast() 77 | .FirstOrDefault(x => x.Name.Equals(paneName, StringComparison.OrdinalIgnoreCase)); 78 | 79 | if (targetPane == null) 80 | { 81 | targetPane = outputWindow.OutputWindowPanes.Add(paneName); 82 | } 83 | 84 | targetPane.Activate(); 85 | outputWindow.ActivePane.OutputString(message); 86 | outputWindow.ActivePane.OutputString(Environment.NewLine); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/RenameHelper/Lib/SingleVariableDesignationSyntaxWrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup.Renaming 4 | { 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using System.Reflection; 8 | using static Geeks.GeeksProductivityTools.Menus.Cleanup.Renaming.RenameHelper; 9 | 10 | internal struct SingleVariableDesignationSyntaxWrapper : ISyntaxWrapper 11 | { 12 | const string SingleVariableDesignationSyntaxTypeName = "Microsoft.CodeAnalysis.CSharp.Syntax.SingleVariableDesignationSyntax"; 13 | static readonly Type SingleVariableDesignationSyntaxType; 14 | 15 | static readonly Func IdentifierAccessor; 16 | static readonly Func WithIdentifierAccessor; 17 | 18 | readonly CSharpSyntaxNode node; 19 | 20 | static SingleVariableDesignationSyntaxWrapper() 21 | { 22 | SingleVariableDesignationSyntaxType = typeof(CSharpSyntaxNode).GetTypeInfo().Assembly.GetType(SingleVariableDesignationSyntaxTypeName); 23 | IdentifierAccessor = LightupHelpers.CreateSyntaxPropertyAccessor(SingleVariableDesignationSyntaxType, nameof(Identifier)); 24 | WithIdentifierAccessor = LightupHelpers.CreateSyntaxWithPropertyAccessor(SingleVariableDesignationSyntaxType, nameof(Identifier)); 25 | } 26 | private SingleVariableDesignationSyntaxWrapper(CSharpSyntaxNode node) => this.node = node; 27 | 28 | public CSharpSyntaxNode SyntaxNode => this.node; 29 | 30 | public SyntaxToken Identifier => IdentifierAccessor(this.SyntaxNode); 31 | 32 | public static explicit operator SingleVariableDesignationSyntaxWrapper(VariableDesignationSyntaxWrapper node) 33 | { 34 | return (SingleVariableDesignationSyntaxWrapper)node.SyntaxNode; 35 | } 36 | 37 | public static explicit operator SingleVariableDesignationSyntaxWrapper(SyntaxNode node) 38 | { 39 | if (node == null) 40 | { 41 | return default(SingleVariableDesignationSyntaxWrapper); 42 | } 43 | 44 | if (!IsInstance(node)) 45 | { 46 | throw new InvalidCastException($"Cannot cast '{node.GetType().FullName}' to '{SingleVariableDesignationSyntaxTypeName}'"); 47 | } 48 | 49 | return new SingleVariableDesignationSyntaxWrapper((CSharpSyntaxNode)node); 50 | } 51 | 52 | public static implicit operator VariableDesignationSyntaxWrapper(SingleVariableDesignationSyntaxWrapper wrapper) 53 | { 54 | return VariableDesignationSyntaxWrapper.FromUpcast(wrapper.node); 55 | } 56 | 57 | public static implicit operator CSharpSyntaxNode(SingleVariableDesignationSyntaxWrapper wrapper) 58 | { 59 | return wrapper.node; 60 | } 61 | 62 | public static bool IsInstance(SyntaxNode node) 63 | { 64 | return node != null && LightupHelpers.CanWrapNode(node, SingleVariableDesignationSyntaxType); 65 | } 66 | 67 | public SingleVariableDesignationSyntaxWrapper WithIdentifier(SyntaxToken identifier) 68 | { 69 | return new SingleVariableDesignationSyntaxWrapper(WithIdentifierAccessor(this.SyntaxNode, identifier)); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/RemoveAttributeKeywork.cs: -------------------------------------------------------------------------------- 1 | using Geeks.GeeksProductivityTools.Menus.Cleanup; 2 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 3 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors; 4 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using Microsoft.CodeAnalysis.CSharp.Syntax; 8 | using System; 9 | using System.Threading.Tasks; 10 | 11 | namespace Geeks.VSIX.TidyCSharp.Cleanup 12 | { 13 | public class RemoveAttributeKeywork : CodeCleanerCommandRunnerBase, ICodeCleaner 14 | { 15 | public override async Task CleanUpAsync(SyntaxNode initialSourceNode) 16 | { 17 | return RemoveAttributeKeyworkHelper(initialSourceNode, ProjectItemDetails.SemanticModel); 18 | } 19 | 20 | SyntaxNode RemoveAttributeKeyworkHelper(SyntaxNode initialSourceNode, SemanticModel semanticModel) 21 | { 22 | var syntaxRewriter = new Rewriter(semanticModel, IsReportOnlyMode, Options); 23 | var modifiedSyntaxNode = syntaxRewriter.Visit(initialSourceNode); 24 | 25 | if (IsReportOnlyMode) 26 | { 27 | CollectMessages(syntaxRewriter.GetReport()); 28 | return initialSourceNode; 29 | } 30 | 31 | return modifiedSyntaxNode; 32 | } 33 | 34 | static string Attribute_Keywork = SyntaxKind.Attribute.ToString(); 35 | class Rewriter : CleanupCSharpSyntaxRewriter 36 | { 37 | SemanticModel semanticModel; 38 | public Rewriter(SemanticModel semanticModel, bool isReportOnlyMode, ICleanupOption options) 39 | : base(isReportOnlyMode, options) => this.semanticModel = semanticModel; 40 | 41 | public override SyntaxNode VisitAttribute(AttributeSyntax node) 42 | { 43 | if (node.Name is IdentifierNameSyntax newNameNode) 44 | { 45 | if (newNameNode.Identifier.ValueText.EndsWith(Attribute_Keywork)) 46 | { 47 | var orginalNodeTypeInfo = semanticModel.GetTypeInfo(node.Name); 48 | 49 | if (orginalNodeTypeInfo.Type == null) base.VisitAttribute(node); 50 | 51 | if (orginalNodeTypeInfo.Type.Name == newNameNode.Identifier.ValueText) 52 | { 53 | var newName = newNameNode.Identifier.ValueText.TrimEnd(Attribute_Keywork); 54 | 55 | if (isReportOnlyMode) 56 | { 57 | var lineSpan = node.GetFileLinePosSpan(); 58 | 59 | AddReport(new ChangesReport(node) 60 | { 61 | LineNumber = lineSpan.StartLinePosition.Line, 62 | Column = lineSpan.StartLinePosition.Character, 63 | Message = "Attributes should not ended with \"Attribute\"", 64 | Generator = nameof(RemoveAttributeKeywork) 65 | }); 66 | } 67 | 68 | node = node.WithName(SyntaxFactory.IdentifierName(newName)); 69 | } 70 | } 71 | } 72 | 73 | return base.VisitAttribute(node); 74 | } 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/Infra/CodeCleanerType.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | using System; 3 | 4 | namespace Geeks.VSIX.TidyCSharp.Cleanup 5 | { 6 | [Flags] 7 | public enum CodeCleanerType //CleanerMainType 8 | { 9 | [CleanupItem(Title = "Remove and sort Usings", FirstOrder = 0)] 10 | OrganizeUsingDirectives = 0x04, 11 | 12 | [CleanupItem(Title = "Normalize white spaces", FirstOrder = 1, SubitemType = typeof(NormalizeWhiteSpace.CleanupTypes))] 13 | NormalizeWhiteSpaces = 0x01, 14 | 15 | [CleanupItem(Title = "Remove unnecessary explicit 'private' where it's the default", FirstOrder = 2, SubitemType = typeof(RemovePrivateModifier.CleanupTypes))] 16 | PrivateAccessModifier = 0x02, 17 | 18 | [CleanupItem(Title = "Small methods properties -> Expression bodied", FirstOrder = 3, SubitemType = typeof(MembersToExpressionBodied.CleanupTypes))] 19 | ConvertMembersToExpressionBodied = 0x08, 20 | 21 | [CleanupItem(Title = "Simplify async calls", FirstOrder = 4, SubitemType = typeof(SimplyAsyncCall.CleanupTypes))] 22 | SimplyAsyncCalls = 0x20, 23 | 24 | [CleanupItem(Title = "Compact multiple class field declarations into one line", FirstOrder = 5, SubitemType = typeof(SimplifyClassFieldDeclaration.CleanupTypes))] 25 | SimplifyClassFieldDeclarations = 0x80, 26 | 27 | [CleanupItem(Title = "Use 'var' for variable declarations", FirstOrder = 5)] 28 | SimplifyVariableDeclarations = 0x8000, 29 | 30 | [CleanupItem(Title = "Convert traditional properties to auto-properties", FirstOrder = 5)] 31 | ConvertPropertiesToAutoProperties = 0x10000, 32 | 33 | [CleanupItem(Title = "Remove unnecessary \"this.\"", FirstOrder = 6, SubitemType = typeof(RemoveExtraThisKeyword.CleanupTypes))] 34 | RemoveExtraThisQualification = 0x400, 35 | 36 | [CleanupItem(Title = "Use camelCase for...", FirstOrder = 7, SubitemType = typeof(CamelCasedMethodVariable.CleanupTypes))] 37 | CamelCasedMethodVariable = 0x800, 38 | 39 | [CleanupItem(Title = "Class field and const casing...", FirstOrder = 8, SubitemType = typeof(CamelCasedClassFields.CleanupTypes))] 40 | CamelCasedFields = 0x1000, 41 | 42 | [CleanupItem(Title = "Move constructors before methods", FirstOrder = 9)] 43 | SortClassMembers = 0x40, 44 | 45 | [CleanupItem(Title = "Remove unnecessary 'Attribute' (e.g. [SomethingAttribute] -> [Something])", FirstOrder = 10)] 46 | RemoveAttributeKeywork = 0x100, 47 | 48 | [CleanupItem(Title = "Compact small if/else blocks", FirstOrder = 11, SelectedByDefault = false)] 49 | CompactSmallIfElseStatements = 0x200, 50 | 51 | [CleanupItem(Title = "Use C# alias type names (e.g. System.Int32 -> int)", FirstOrder = 11)] 52 | ConvertFullNameTypesToBuiltInTypes = 0x10, 53 | 54 | [CleanupItem(Title = "Renew M# UI methods", FirstOrder = 12)] 55 | ConvertMsharpUIMethods = 0x25, 56 | 57 | [CleanupItem(Title = "Renew M# Model methods", FirstOrder = 13)] 58 | ConvertMsharpModelMethods = 0x26, 59 | 60 | [CleanupItem(Title = "Renew M# General Statements", FirstOrder = 14)] 61 | ConvertMsharpGeneralMethods = 0x27, 62 | 63 | [CleanupItem(Title = "Renew Zebble General Statements", FirstOrder = 15)] 64 | ConvertZebbleGeneralMethods = 0x28, 65 | 66 | [CleanupItem(Title = "Upgrade C# Syntax", FirstOrder = 16)] 67 | UpgradeCSharpSyntax = 0x29 68 | } 69 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/SimplifyVariableDeclarations.cs: -------------------------------------------------------------------------------- 1 | using Geeks.GeeksProductivityTools.Menus.Cleanup; 2 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 3 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors; 4 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using Microsoft.CodeAnalysis.CSharp.Syntax; 8 | using System.Threading.Tasks; 9 | 10 | namespace Geeks.VSIX.TidyCSharp.Cleanup 11 | { 12 | public class SimplifyVariableDeclarations : CodeCleanerCommandRunnerBase, ICodeCleaner 13 | { 14 | public override async Task CleanUpAsync(SyntaxNode initialSourceNode) 15 | { 16 | var syntaxRewriter = new Rewriter(ProjectItemDetails.SemanticModel, 17 | IsReportOnlyMode, Options); 18 | 19 | var modifiedSyntaxNode = syntaxRewriter.Visit(initialSourceNode); 20 | 21 | if (IsReportOnlyMode) 22 | { 23 | CollectMessages(syntaxRewriter.GetReport()); 24 | return initialSourceNode; 25 | } 26 | 27 | return modifiedSyntaxNode; 28 | } 29 | 30 | class Rewriter : CleanupCSharpSyntaxRewriter 31 | { 32 | const string VarKeyword = "var"; 33 | SemanticModel SemanticModel; 34 | public Rewriter(SemanticModel semanticModel, bool isReportOnlyMode, ICleanupOption options) 35 | : base(isReportOnlyMode, options) 36 | { 37 | SemanticModel = semanticModel; 38 | } 39 | 40 | public override SyntaxNode VisitVariableDeclaration(VariableDeclarationSyntax node) 41 | { 42 | return ConvertToVar(node) ?? node; 43 | } 44 | 45 | SyntaxNode ConvertToVar(VariableDeclarationSyntax node) 46 | { 47 | if (node.Parent is LocalDeclarationStatementSyntax == false) return null; 48 | if ((node.Parent as LocalDeclarationStatementSyntax).IsConst) return null; 49 | 50 | if (node.Type is IdentifierNameSyntax varIdentifierNameSyntax) 51 | { 52 | if (varIdentifierNameSyntax.Identifier.ValueText == VarKeyword) return null; 53 | } 54 | 55 | if (node.Variables.Count > 1) return null; 56 | 57 | var variable = node.Variables.FirstOrDefault(); 58 | 59 | if (variable.Initializer == null) return null; 60 | 61 | var typeOfInitializer = SemanticModel.GetTypeInfo(variable.Initializer.Value); 62 | 63 | var typeOfTypeDef = SemanticModel.GetTypeInfo(node.Type); 64 | 65 | if (typeOfInitializer.Type?.Name == typeOfTypeDef.Type?.Name) 66 | { 67 | if (isReportOnlyMode) 68 | { 69 | var lineSpan = node.GetFileLinePosSpan(); 70 | 71 | AddReport(new ChangesReport(node) 72 | { 73 | LineNumber = lineSpan.StartLinePosition.Line, 74 | Column = lineSpan.StartLinePosition.Character, 75 | Message = "Should Convert To Var", 76 | Generator = nameof(SimplifyVariableDeclarations) 77 | }); 78 | } 79 | 80 | node = 81 | node 82 | .WithType( 83 | SyntaxFactory.ParseTypeName(VarKeyword) 84 | .WithTrailingTrivia(SyntaxFactory.Space) 85 | .WithLeadingTrivia(node.Type.GetLeadingTrivia()) 86 | ); 87 | } 88 | 89 | return base.VisitVariableDeclaration(node); 90 | } 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/CodeCleanerFactory.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup; 2 | using Geeks.VSIX.TidyCSharp.Cleanup.CommandsHandlers; 3 | 4 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 5 | { 6 | public class CodeCleanerFactory 7 | { 8 | public static ICodeCleaner Create(CodeCleanerType type, CleanupOptions cleanupOptions, bool isReportOnly = false) 9 | { 10 | switch (type) 11 | { 12 | case CodeCleanerType.NormalizeWhiteSpaces: 13 | return new WhiteSpaceNormalizer() { Options = cleanupOptions.WhiteSpaceNormalizer, IsReportOnlyMode = isReportOnly }; 14 | case CodeCleanerType.ConvertMembersToExpressionBodied: 15 | return new ConvertMembersToExpressionBodied() { Options = cleanupOptions.ConvertMembersToExpressionBodied, IsReportOnlyMode = isReportOnly }; 16 | case CodeCleanerType.ConvertFullNameTypesToBuiltInTypes: 17 | return new ConvertFullNameTypesToBuiltInTypes() { IsReportOnlyMode = isReportOnly }; 18 | case CodeCleanerType.SortClassMembers: 19 | return new SortClassMembers() { IsReportOnlyMode = isReportOnly }; ; 20 | case CodeCleanerType.SimplyAsyncCalls: 21 | return new SimplyAsyncCalls() { Options = cleanupOptions.SimplyAsyncCall, IsReportOnlyMode = isReportOnly }; 22 | case CodeCleanerType.SimplifyClassFieldDeclarations: 23 | return new SimplifyClassFieldDeclarations() { Options = cleanupOptions.SimplifyClassFieldDeclarations, IsReportOnlyMode = isReportOnly }; 24 | case CodeCleanerType.RemoveAttributeKeywork: 25 | return new RemoveAttributeKeywork() { IsReportOnlyMode = isReportOnly }; 26 | case CodeCleanerType.CompactSmallIfElseStatements: 27 | return new CompactSmallIfElseStatements() { IsReportOnlyMode = isReportOnly }; 28 | case CodeCleanerType.RemoveExtraThisQualification: 29 | return new RemoveExtraThisQualification() { Options = cleanupOptions.RemoveExtraThisQualification, IsReportOnlyMode = isReportOnly }; 30 | case CodeCleanerType.CamelCasedMethodVariable: 31 | return new CamelCasedLocalVariable() { Options = cleanupOptions.CamelCasedLocalVariable, IsReportOnlyMode = isReportOnly }; 32 | case CodeCleanerType.CamelCasedFields: 33 | return new CamelCasedFields() { Options = cleanupOptions.CamelCasedFields, IsReportOnlyMode = isReportOnly }; 34 | case CodeCleanerType.PrivateAccessModifier: 35 | return new PrivateModifierRemover() { IsReportOnlyMode = isReportOnly }; 36 | case CodeCleanerType.OrganizeUsingDirectives: 37 | return new UsingDirectiveOrganizer() { Options = cleanupOptions.PrivateModifierRemover, IsReportOnlyMode = isReportOnly }; 38 | case CodeCleanerType.SimplifyVariableDeclarations: 39 | return new SimplifyVariableDeclarations() { IsReportOnlyMode = isReportOnly }; 40 | case CodeCleanerType.ConvertPropertiesToAutoProperties: 41 | return new ConvertPropertiesToAutoProperties() { IsReportOnlyMode = isReportOnly }; 42 | case CodeCleanerType.ConvertMsharpUIMethods: 43 | return new MSharpUICleaner() { IsReportOnlyMode = isReportOnly }; 44 | case CodeCleanerType.ConvertMsharpModelMethods: 45 | return new MSharpModelCleaner() { IsReportOnlyMode = isReportOnly }; 46 | case CodeCleanerType.ConvertMsharpGeneralMethods: 47 | return new MSharpGeneralCleaner() { IsReportOnlyMode = isReportOnly }; 48 | case CodeCleanerType.ConvertZebbleGeneralMethods: 49 | return new ZebbleCleaner() { IsReportOnlyMode = isReportOnly }; 50 | case CodeCleanerType.UpgradeCSharpSyntax: 51 | return new CSharpSyntaxUpgrade() { IsReportOnlyMode = isReportOnly }; 52 | default: return null; // TODO 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/SortClassMembers.cs: -------------------------------------------------------------------------------- 1 | using Geeks.GeeksProductivityTools.Menus.Cleanup; 2 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 3 | using Microsoft.CodeAnalysis; 4 | using Microsoft.CodeAnalysis.CSharp.Syntax; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace Geeks.VSIX.TidyCSharp.Cleanup 10 | { 11 | public class SortClassMembers : CodeCleanerCommandRunnerBase, ICodeCleaner 12 | { 13 | public override async Task CleanUpAsync(SyntaxNode initialSourceNode) 14 | { 15 | var modifiedSourceNode = SortClassMembersHelper(initialSourceNode); 16 | 17 | if (IsReportOnlyMode && 18 | !IsEquivalentToUNModified(modifiedSourceNode)) 19 | { 20 | CollectMessages(new ChangesReport(initialSourceNode) 21 | { 22 | LineNumber = 1, 23 | Column = 1, 24 | Message = "Sort Class Members", 25 | Generator = nameof(SortClassMembers) 26 | }); 27 | 28 | return initialSourceNode; 29 | } 30 | 31 | return modifiedSourceNode; 32 | } 33 | 34 | public static SyntaxNode SortClassMembersHelper(SyntaxNode initialSource) 35 | { 36 | var classes = 37 | initialSource 38 | .DescendantNodes() 39 | .Where(x => x is ClassDeclarationSyntax) 40 | .OfType(); 41 | 42 | var newClassesDic = new Dictionary(); 43 | 44 | foreach (var classNode in classes) 45 | { 46 | var newClassNode = SortClassMemebersHelper(classNode); 47 | newClassesDic.Add(classNode, newClassNode); 48 | } 49 | 50 | initialSource = 51 | initialSource 52 | .ReplaceNodes 53 | ( 54 | classes, 55 | (oldNode1, oldNode2) => 56 | { 57 | var newClass = newClassesDic[oldNode1]; 58 | if (oldNode1 != newClass) return newClass; 59 | return oldNode1; 60 | } 61 | ); 62 | 63 | return initialSource; 64 | } 65 | 66 | public static ClassDeclarationSyntax SortClassMemebersHelper(ClassDeclarationSyntax classNode) 67 | { 68 | var methods = classNode.Members.Where(x => x is MethodDeclarationSyntax).ToList(); 69 | var firstMethod = methods.FirstOrDefault(); 70 | if (firstMethod == null) return classNode; 71 | 72 | var methodAnnotation = new SyntaxAnnotation(); 73 | var annotatedClassNode = classNode.ReplaceNode(firstMethod, firstMethod.WithAdditionalAnnotations(methodAnnotation)); 74 | 75 | var constructors = annotatedClassNode.Members.Where(x => x is ConstructorDeclarationSyntax).ToList(); 76 | if (constructors.Any() == false) return classNode; 77 | 78 | var constructorsToMoveList = new List(); 79 | 80 | foreach (var constructorItem in constructors) 81 | { 82 | if (firstMethod.SpanStart < constructorItem.SpanStart) 83 | { 84 | constructorsToMoveList.Add(constructorItem); 85 | } 86 | } 87 | 88 | if (constructorsToMoveList.Any()) 89 | { 90 | annotatedClassNode = annotatedClassNode.RemoveNodes(constructorsToMoveList, SyntaxRemoveOptions.KeepNoTrivia); 91 | var annotatedMethod = annotatedClassNode.GetAnnotatedNodes(methodAnnotation).FirstOrDefault(); 92 | annotatedClassNode = annotatedClassNode.InsertNodesBefore(annotatedMethod, constructorsToMoveList); 93 | 94 | return annotatedClassNode; 95 | } 96 | 97 | return classNode; 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/CleanupOptions.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 2 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.CommandsHandlers; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace Geeks.VSIX.TidyCSharp.Cleanup.CommandsHandlers 7 | { 8 | public class CleanupOptions 9 | { 10 | List optionItems = new List(); 11 | 12 | public const string To_String_Seprator2 = ":", To_String_Seprator = ";"; 13 | public List ActionTypes { get; private set; } = new List(); 14 | 15 | public CleanupOptions() 16 | { 17 | optionItems.Add(CamelCasedFields = new CamelCasedClassFields.Options()); 18 | optionItems.Add(CamelCasedLocalVariable = new CamelCasedMethodVariable.Options()); 19 | optionItems.Add(ConvertMembersToExpressionBodied = new MembersToExpressionBodied.Options()); 20 | optionItems.Add(PrivateModifierRemover = new RemovePrivateModifier.Options()); 21 | optionItems.Add(RemoveExtraThisQualification = new RemoveExtraThisKeyword.Options()); 22 | optionItems.Add(SimplifyClassFieldDeclarations = new SimplifyClassFieldDeclaration.Options()); 23 | optionItems.Add(SimplyAsyncCall = new SimplyAsyncCall.Options()); 24 | optionItems.Add(WhiteSpaceNormalizer = new NormalizeWhiteSpace.Options()); 25 | } 26 | 27 | public void Accept(IMainCleanup mainCleanup) 28 | { 29 | foreach (var item in optionItems) 30 | item.Accept(mainCleanup); 31 | 32 | if (mainCleanup.IsMainObjectSelected) 33 | { 34 | ActionTypes.Add(mainCleanup.MainCleanupItemType); 35 | } 36 | } 37 | 38 | public CamelCasedClassFields.Options CamelCasedFields { get; private set; } 39 | public CamelCasedMethodVariable.Options CamelCasedLocalVariable { get; private set; } 40 | public MembersToExpressionBodied.Options ConvertMembersToExpressionBodied { get; private set; } 41 | public RemovePrivateModifier.Options PrivateModifierRemover { get; private set; } 42 | public RemoveExtraThisKeyword.Options RemoveExtraThisQualification { get; private set; } 43 | public SimplifyClassFieldDeclaration.Options SimplifyClassFieldDeclarations { get; private set; } 44 | public SimplyAsyncCall.Options SimplyAsyncCall { get; private set; } 45 | public NormalizeWhiteSpace.Options WhiteSpaceNormalizer { get; private set; } 46 | 47 | public string SerializeValues() 48 | { 49 | var values = System.Enum.GetValues(typeof(CodeCleanerType)).Cast(); 50 | 51 | return string.Join(To_String_Seprator, values 52 | .Select(enumValueAsObject => 53 | { 54 | var optionItem = optionItems.FirstOrDefault(o => (int)o.GetCodeCleanerType() == enumValueAsObject); 55 | 56 | var IsParentSelected = ActionTypes.Contains((CodeCleanerType)enumValueAsObject); 57 | 58 | if (optionItem == null) return $"{enumValueAsObject}{To_String_Seprator2}{IsParentSelected}{To_String_Seprator2}{-1}"; 59 | 60 | if (optionItem.CleanupItemsInteger.HasValue == false) 61 | return $"{enumValueAsObject}{To_String_Seprator2}{IsParentSelected}{To_String_Seprator2}{0}"; 62 | 63 | return $"{enumValueAsObject}{To_String_Seprator2}{IsParentSelected}{To_String_Seprator2}{optionItem.CleanupItemsInteger.Value}"; 64 | }) 65 | ); 66 | } 67 | 68 | public override string ToString() 69 | { 70 | return string.Join(To_String_Seprator, ActionTypes 71 | .Select(x => 72 | { 73 | var optionItem = optionItems.FirstOrDefault(o => o.GetCodeCleanerType() == x); 74 | if (optionItem == null) return $"{(int)x}{To_String_Seprator2}{-1}"; 75 | if (optionItem.CleanupItemsInteger.HasValue == false) return $"{(int)x}{To_String_Seprator2}{0}"; 76 | return $"{(int)x}{To_String_Seprator2}{optionItem.CleanupItemsInteger.Value}"; 77 | }) 78 | ); 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/Infra/UI/CleanupItemUserControl.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace Geeks.VSIX.TidyCSharp.Menus.Cleanup.CommandsHandlers 2 | { 3 | partial class CleanupItemUserControl 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.panel1 = new System.Windows.Forms.Panel(); 32 | this.customCheckListBox1 = new Geeks.VSIX.TidyCSharp.Menus.Cleanup.CommandsHandlers.Infra.CustomChecklistBox(); 33 | this.checkboxCleanupItem = new System.Windows.Forms.CheckBox(); 34 | this.SuspendLayout(); 35 | // 36 | // panel1 37 | // 38 | this.panel1.Dock = System.Windows.Forms.DockStyle.Left; 39 | this.panel1.Location = new System.Drawing.Point(2, 17); 40 | this.panel1.Name = "panel1"; 41 | this.panel1.Size = new System.Drawing.Size(18, 3); 42 | this.panel1.TabIndex = 15; 43 | // 44 | // customCheckListBox1 45 | // 46 | this.customCheckListBox1.AutoSize = true; 47 | this.customCheckListBox1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; 48 | this.customCheckListBox1.Dock = System.Windows.Forms.DockStyle.Fill; 49 | this.customCheckListBox1.Location = new System.Drawing.Point(20, 17); 50 | this.customCheckListBox1.MaximumSize = new System.Drawing.Size(460, 0); 51 | this.customCheckListBox1.Name = "customCheckListBox1"; 52 | this.customCheckListBox1.Size = new System.Drawing.Size(458, 3); 53 | this.customCheckListBox1.TabIndex = 16; 54 | // 55 | // checkboxCleanupItem 56 | // 57 | this.checkboxCleanupItem.AutoSize = true; 58 | this.checkboxCleanupItem.Dock = System.Windows.Forms.DockStyle.Top; 59 | this.checkboxCleanupItem.Location = new System.Drawing.Point(2, 0); 60 | this.checkboxCleanupItem.Margin = new System.Windows.Forms.Padding(2); 61 | this.checkboxCleanupItem.MaximumSize = new System.Drawing.Size(476, 0); 62 | this.checkboxCleanupItem.Name = "checkboxCleanupItem"; 63 | this.checkboxCleanupItem.Size = new System.Drawing.Size(476, 17); 64 | this.checkboxCleanupItem.TabIndex = 9; 65 | this.checkboxCleanupItem.Text = "checkboxCleanupItem"; 66 | this.checkboxCleanupItem.UseVisualStyleBackColor = true; 67 | // 68 | // CleanupItemUserControl 69 | // 70 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 71 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 72 | this.AutoSize = true; 73 | this.Controls.Add(this.customCheckListBox1); 74 | this.Controls.Add(this.panel1); 75 | this.Controls.Add(this.checkboxCleanupItem); 76 | this.Margin = new System.Windows.Forms.Padding(3, 0, 3, 3); 77 | this.Name = "CleanupItemUserControl"; 78 | this.Padding = new System.Windows.Forms.Padding(2, 0, 2, 2); 79 | this.Size = new System.Drawing.Size(480, 22); 80 | this.ResumeLayout(false); 81 | this.PerformLayout(); 82 | 83 | } 84 | 85 | #endregion 86 | private System.Windows.Forms.Panel panel1; 87 | private Infra.CustomChecklistBox customCheckListBox1; 88 | private System.Windows.Forms.CheckBox checkboxCleanupItem; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/ConvertFullNameTypesToBuiltInTypes.cs: -------------------------------------------------------------------------------- 1 | using Geeks.GeeksProductivityTools.Menus.Cleanup; 2 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 3 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors; 4 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace Geeks.VSIX.TidyCSharp.Cleanup 11 | { 12 | public class ConvertFullNameTypesToBuiltInTypes : CodeCleanerCommandRunnerBase, ICodeCleaner 13 | { 14 | public override async Task CleanUpAsync(SyntaxNode initialSourceNode) 15 | { 16 | var syntaxRewriter = new Rewriter(ProjectItemDetails.SemanticModel, IsReportOnlyMode 17 | , Options); 18 | 19 | var modifiedSourceNode = syntaxRewriter.ConvertFullNameTypesToBuiltInTypesHelper(initialSourceNode); 20 | 21 | if (IsReportOnlyMode) 22 | { 23 | CollectMessages(syntaxRewriter.GetReport()); 24 | return initialSourceNode; 25 | } 26 | 27 | return modifiedSourceNode; 28 | } 29 | 30 | class Rewriter : CleanupCSharpSyntaxRewriter 31 | { 32 | SemanticModel SemanticModel; 33 | public Rewriter(SemanticModel semanticModel, 34 | bool isReportOnlyMode, ICleanupOption options) : base(isReportOnlyMode, options) 35 | { 36 | SemanticModel = semanticModel; 37 | } 38 | 39 | public SyntaxNode ConvertFullNameTypesToBuiltInTypesHelper(SyntaxNode initialSource) 40 | { 41 | var builtInTypesMapDic = TypesMapItem.GetBuiltInTypesDic(); 42 | 43 | var selectedTokensList = 44 | initialSource 45 | .DescendantNodes() 46 | .Where 47 | ( 48 | n => 49 | (n is IdentifierNameSyntax || n is QualifiedNameSyntax) 50 | && 51 | builtInTypesMapDic.ContainsKey(n.WithoutTrivia().ToFullString()) 52 | ); 53 | 54 | return initialSource.ReplaceNodes( 55 | selectedTokensList, 56 | (oldNode1, oldNode2) => 57 | { 58 | if (oldNode1.Parent is QualifiedNameSyntax) return oldNode1; 59 | 60 | if (oldNode1.Parent is MemberAccessExpressionSyntax) 61 | { 62 | if ((oldNode1.Parent as MemberAccessExpressionSyntax).Expression != oldNode1) return oldNode1; 63 | var symbol = SemanticModel.GetSymbolInfo(oldNode1).Symbol; 64 | if (symbol != null && symbol.Kind != SymbolKind.NamedType) return oldNode1; 65 | } 66 | else if (oldNode1 is IdentifierNameSyntax == false && oldNode1 is QualifiedNameSyntax == false) return oldNode1; 67 | else 68 | { 69 | var symbol = SemanticModel.GetSymbolInfo(oldNode1).Symbol; 70 | if (symbol != null && symbol.Kind != SymbolKind.NamedType) return oldNode1; 71 | } 72 | 73 | var lineSpan = oldNode1.GetFileLinePosSpan(); 74 | 75 | AddReport(new ChangesReport(oldNode1) 76 | { 77 | LineNumber = lineSpan.StartLinePosition.Line, 78 | Column = lineSpan.StartLinePosition.Character, 79 | Message = "Convert full name types to built in Types", 80 | Generator = nameof(ConvertFullNameTypesToBuiltInTypes) 81 | }); 82 | 83 | return 84 | builtInTypesMapDic[oldNode1.WithoutTrivia().ToFullString()] 85 | .NewNode 86 | .WithLeadingTrivia(oldNode1.GetLeadingTrivia()) 87 | .WithTrailingTrivia(oldNode1.GetTrailingTrivia()); 88 | } 89 | ); 90 | } 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/CamelCasedClassFields/CamelCasedFields.cs: -------------------------------------------------------------------------------- 1 | using Geeks.GeeksProductivityTools.Menus.Cleanup; 2 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 3 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors; 4 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace Geeks.VSIX.TidyCSharp.Cleanup 11 | { 12 | public class CamelCasedFields : VariableRenamingBase, ICodeCleaner 13 | { 14 | protected override SyntaxNode GetWorkingNode(SyntaxNode initialSourceNode, SyntaxAnnotation annotationForSelectedNodes) 15 | { 16 | return 17 | initialSourceNode 18 | .DescendantNodes() 19 | .OfType() 20 | .FirstOrDefault(m => !m.HasAnnotation(annotationForSelectedNodes)); 21 | } 22 | 23 | protected override VariableRenamingBaseRewriter GetRewriter(Document workingDocument) 24 | { 25 | return new Rewriter(workingDocument, IsReportOnlyMode, Options); 26 | } 27 | 28 | class Rewriter : VariableRenamingBaseRewriter 29 | { 30 | public Rewriter(Document workingDocument, bool isReportOnlyMode, ICleanupOption options) : base(workingDocument, isReportOnlyMode, options) { } 31 | 32 | public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) 33 | { 34 | ClassDeclarationSyntax classDeclarationSyntax = null; 35 | 36 | Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskFactory 37 | .Run(async delegate 38 | { 39 | classDeclarationSyntax = await RenameDeclarationsAsync(node); 40 | }); 41 | 42 | return base.VisitClassDeclaration(classDeclarationSyntax as ClassDeclarationSyntax); 43 | } 44 | 45 | async Task RenameDeclarationsAsync(ClassDeclarationSyntax classNode) 46 | { 47 | if (CheckOption((int)CamelCasedClassFields.CleanupTypes.NormalFields)) 48 | { 49 | var renamingResult = await new FieldRenamer(WorkingDocument).RenameDeclarationsAsync(classNode); 50 | 51 | if (renamingResult != null && renamingResult.Node != null) 52 | { 53 | classNode = renamingResult.Node as ClassDeclarationSyntax; 54 | WorkingDocument = renamingResult.Document; 55 | } 56 | 57 | if (renamingResult != null) 58 | { 59 | var lineSpan = classNode.GetFileLinePosSpan(); 60 | 61 | AddReport(new ChangesReport(classNode) 62 | { 63 | LineNumber = lineSpan.StartLinePosition.Line, 64 | Column = lineSpan.StartLinePosition.Character, 65 | Message = "Camel Cased Fields", 66 | Generator = nameof(CamelCasedFields), 67 | }); 68 | } 69 | } 70 | 71 | if (CheckOption((int)CamelCasedClassFields.CleanupTypes.ConstFields)) 72 | { 73 | var renamingResult = await new CONSTRenamer(WorkingDocument).RenameDeclarationsAsync(classNode); 74 | 75 | if (renamingResult != null && renamingResult.Node != null) 76 | { 77 | classNode = renamingResult.Node as ClassDeclarationSyntax; 78 | WorkingDocument = renamingResult.Document; 79 | } 80 | 81 | if (renamingResult != null) 82 | { 83 | var lineSpan = classNode.GetFileLinePosSpan(); 84 | 85 | AddReport(new ChangesReport(classNode) 86 | { 87 | LineNumber = lineSpan.StartLinePosition.Line, 88 | Column = lineSpan.StartLinePosition.Character, 89 | Message = "CamelCasedFields", 90 | Generator = nameof(CamelCasedFields) 91 | }); 92 | } 93 | } 94 | 95 | return classNode; 96 | } 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/CamelCasedMethodVariable/CamelCasedLocalVariable.cs: -------------------------------------------------------------------------------- 1 | using Geeks.GeeksProductivityTools.Menus.Cleanup; 2 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 3 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors; 4 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace Geeks.VSIX.TidyCSharp.Cleanup 11 | { 12 | public class CamelCasedLocalVariable : VariableRenamingBase, ICodeCleaner 13 | { 14 | protected override SyntaxNode GetWorkingNode(SyntaxNode initialSourceNode, SyntaxAnnotation annotationForSelectedNodes) 15 | { 16 | return 17 | initialSourceNode 18 | .DescendantNodes() 19 | .OfType() 20 | .FirstOrDefault(m => !m.HasAnnotation(annotationForSelectedNodes)); 21 | } 22 | 23 | protected override VariableRenamingBaseRewriter GetRewriter(Document workingDocument) 24 | { 25 | return new Rewriter(workingDocument, IsReportOnlyMode, Options); 26 | } 27 | class Rewriter : VariableRenamingBaseRewriter 28 | { 29 | public Rewriter(Document workingDocument, bool isReportOnlyMode, ICleanupOption options) : base(workingDocument, isReportOnlyMode, options) { } 30 | 31 | public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) 32 | { 33 | MethodDeclarationSyntax methodDeclarationSyntax = null; 34 | 35 | Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskFactory 36 | .Run(async delegate 37 | { 38 | methodDeclarationSyntax = await RenameDeclarationsAsync(node); 39 | }); 40 | 41 | return base.VisitMethodDeclaration(methodDeclarationSyntax as MethodDeclarationSyntax); 42 | } 43 | 44 | async Task RenameDeclarationsAsync(MethodDeclarationSyntax methodNode) 45 | { 46 | if (CheckOption((int)CamelCasedMethodVariable.CleanupTypes.LocalVariable)) 47 | { 48 | var renamingResult = await new VariableRenamer(WorkingDocument).RenameDeclarationsAsync(methodNode); 49 | 50 | if (renamingResult != null && renamingResult.Node != null) 51 | { 52 | methodNode = renamingResult.Node as MethodDeclarationSyntax; 53 | WorkingDocument = renamingResult.Document; 54 | } 55 | 56 | if (renamingResult != null) 57 | { 58 | var lineSpan = methodNode.GetFileLinePosSpan(); 59 | 60 | AddReport(new ChangesReport(methodNode) 61 | { 62 | LineNumber = lineSpan.StartLinePosition.Line, 63 | Column = lineSpan.StartLinePosition.Character, 64 | Message = "Camel Cased Methods", 65 | Generator = nameof(CamelCasedLocalVariable) 66 | }); 67 | } 68 | } 69 | 70 | if (CheckOption((int)CamelCasedMethodVariable.CleanupTypes.MethodParameter)) 71 | { 72 | var renamingResult = await new ParameterRenamer(WorkingDocument).RenameDeclarationsAsync(methodNode); 73 | 74 | if (renamingResult != null && renamingResult.Node != null) 75 | { 76 | methodNode = renamingResult.Node as MethodDeclarationSyntax; 77 | WorkingDocument = renamingResult.Document; 78 | } 79 | 80 | if (renamingResult != null) 81 | { 82 | var lineSpan = methodNode.GetFileLinePosSpan(); 83 | 84 | AddReport(new ChangesReport(methodNode) 85 | { 86 | LineNumber = lineSpan.StartLinePosition.Line, 87 | Column = lineSpan.StartLinePosition.Character, 88 | Message = "Camel Cased Methods", 89 | Generator = nameof(CamelCasedLocalVariable) 90 | }); 91 | } 92 | } 93 | 94 | return methodNode; 95 | } 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /TidyCSharp/Utility/Utils.cs: -------------------------------------------------------------------------------- 1 | using EnvDTE; 2 | using EnvDTE80; 3 | using Geeks.GeeksProductivityTools; 4 | using Microsoft.VisualStudio.Shell; 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | namespace GeeksAddin 9 | { 10 | public static class Utils 11 | { 12 | // public static string GetSolutionName(DTE2 app) 13 | // { 14 | // if (app == null || app.Solution == null || string.IsNullOrEmpty(app.Solution.FullName)) return ""; 15 | // return Path.GetFileNameWithoutExtension(app.Solution.FullName); 16 | // } 17 | 18 | //public static string[] FindSolutionDirectories(DTE2 app) 19 | //{ 20 | // ThreadHelper.JoinableTaskFactory 21 | // .Run(async delegate 22 | // { 23 | // await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); 24 | // }); 25 | 26 | // var basePaths = new List(); 27 | 28 | // if (app.Solution != null) 29 | // { 30 | // for (var i = 1; i <= app.Solution.Projects.Count; i++) 31 | // { 32 | // var projectItem = app.Solution.Projects.Item(i); 33 | // AddPathFromProjectItem(basePaths, projectItem); 34 | // } 35 | 36 | // return basePaths.ToArray(); 37 | // } 38 | 39 | // app.StatusBar.Text = "No solution or project is identified. app.Solution is " + 40 | // (app.Solution?.GetType().Name).Or("NULL"); 41 | 42 | // App.DTE = (DTE2)TidyCSharpPackage.GetGlobalService(typeof(DTE2)); 43 | 44 | // return null; 45 | //} 46 | 47 | static void AddPathFromProjectItem(List basePaths, Project projectItem) 48 | { 49 | if (projectItem == null) return; 50 | 51 | try 52 | { 53 | // Project 54 | var projectFileName = projectItem.FileName; 55 | 56 | if (!string.IsNullOrWhiteSpace(projectFileName)) 57 | { 58 | if (projectItem.Properties.Item("FullPath").Value is string fullPath) 59 | basePaths.Add(fullPath); 60 | } 61 | else 62 | { 63 | // Folder 64 | for (var i = 1; i <= projectItem.ProjectItems.Count; i++) 65 | AddPathFromProjectItem(basePaths, projectItem.ProjectItems.Item(i).Object as Project); 66 | } 67 | } 68 | catch (Exception err) 69 | { 70 | ErrorNotification.WriteErrorToFile(err); 71 | ErrorNotification.WriteErrorToOutputWindow(err); 72 | } 73 | } 74 | 75 | // public static IEnumerable SplitCommandLine(string commandLine) 76 | // { 77 | // var inQuotes = false; 78 | 79 | // return commandLine.Split(c => 80 | // { 81 | // if (c == '\"') 82 | // inQuotes = !inQuotes; 83 | // return !inQuotes && c == ' '; 84 | // }).Select(arg => arg.Trim().TrimMatchingQuotes()) 85 | // .Where(arg => !string.IsNullOrEmpty(arg)); 86 | // } 87 | 88 | // public static IEnumerable Split(this string str, Func controller) 89 | // { 90 | // var nextPiece = 0; 91 | 92 | // for (var c = 0; c < str.Length; c++) 93 | // { 94 | // if (controller(str[c])) 95 | // { 96 | // yield return str.Substring(nextPiece, c - nextPiece); 97 | // nextPiece = c + 1; 98 | // } 99 | // } 100 | 101 | // yield return str.Substring(nextPiece); 102 | // } 103 | 104 | // public static string TrimMatchingQuotes(this string input, char quote = '\"') 105 | // { 106 | // if ((input.Length >= 2) && 107 | // (input[0] == quote) && (input[input.Length - 1] == quote)) 108 | // return input.Substring(1, input.Length - 2); 109 | 110 | // return input; 111 | // } 112 | 113 | // public static bool ContainsAny(this string str, params string[] subStrings) 114 | // { 115 | // foreach (var subString in subStrings) 116 | // if (str.Contains(subString)) 117 | // return true; 118 | 119 | // return false; 120 | // } 121 | } 122 | } -------------------------------------------------------------------------------- /TidyCSharp/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Geeks.VSIX.TidyCSharp { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | public class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | public static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Geeks.VSIX.TidyCSharp.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | public static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to PrivateModifierRemover: The file path is either null or the file does not exist. 65 | /// 66 | public static string PrivateModifierCleanUpFailed { 67 | get { 68 | return ResourceManager.GetString("PrivateModifierCleanUpFailed", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// Looks up a localized string similar to Warning - C# Code Cleanup. 74 | /// 75 | public static string WarningCaptionCleanup { 76 | get { 77 | return ResourceManager.GetString("WarningCaptionCleanup", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// Looks up a localized string similar to Warning - Organize using directives. 83 | /// 84 | public static string WarningCaptionOrganizeUsing { 85 | get { 86 | return ResourceManager.GetString("WarningCaptionOrganizeUsing", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// Looks up a localized string similar to It is strongly recommended that you close all open windows before starting this process.. 92 | /// 93 | public static string WarnOnCodeCleanUp { 94 | get { 95 | return ResourceManager.GetString("WarnOnCodeCleanUp", resourceCulture); 96 | } 97 | } 98 | 99 | /// 100 | /// Looks up a localized string similar to It is strongly recommended that you close all open windows before starting this process.. 101 | /// 102 | public static string WarnOnOrganizeUsings { 103 | get { 104 | return ResourceManager.GetString("WarnOnOrganizeUsings", resourceCulture); 105 | } 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /TidyCSharp/TidyCSharp.vsct: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandRunners/RemoveExtraThisQualification/RemoveExtraThisQualification.cs: -------------------------------------------------------------------------------- 1 | using Geeks.GeeksProductivityTools.Menus.Cleanup; 2 | using Geeks.VSIX.TidyCSharp.Cleanup.Infra; 3 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.SyntaxNodeExtractors; 4 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.Utils; 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using Microsoft.CodeAnalysis.CSharp.Syntax; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Threading.Tasks; 11 | 12 | namespace Geeks.VSIX.TidyCSharp.Cleanup 13 | { 14 | public class RemoveExtraThisQualification : CodeCleanerCommandRunnerBase, ICodeCleaner 15 | { 16 | public override async Task CleanUpAsync(SyntaxNode initialSourceNode) 17 | { 18 | var rewriter = new Rewriter(ProjectItemDetails, IsReportOnlyMode, Options); 19 | var modifiedSourceNode = rewriter.Visit(initialSourceNode); 20 | 21 | if (IsReportOnlyMode) 22 | { 23 | CollectMessages(rewriter.GetReport()); 24 | return initialSourceNode; 25 | } 26 | 27 | return modifiedSourceNode; 28 | } 29 | 30 | class Rewriter : CleanupCSharpSyntaxRewriter 31 | { 32 | readonly SemanticModel semanticModel; 33 | 34 | public Rewriter(ProjectItemDetailsType projectItemDetails, bool isReportOnlyMode, ICleanupOption options) 35 | : base(isReportOnlyMode, options) 36 | { 37 | semanticModel = projectItemDetails.SemanticModel; 38 | } 39 | 40 | public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) 41 | { 42 | if (node.Parent is ClassDeclarationSyntax == false) 43 | { 44 | node = Remove(node); 45 | } 46 | 47 | return base.VisitClassDeclaration(node); 48 | } 49 | 50 | ClassDeclarationSyntax Remove(ClassDeclarationSyntax classNode) 51 | { 52 | var thises = classNode.DescendantNodes().OfType(); 53 | var newItems = new Dictionary(); 54 | 55 | foreach (var thisItem in thises) 56 | { 57 | if (thisItem.Parent is MemberAccessExpressionSyntax thisItemAsMemberAccessException) 58 | { 59 | var newAccess = GetMemberAccessWithoutThis(thisItemAsMemberAccessException); 60 | 61 | if (newAccess != null) 62 | { 63 | newItems.Add(thisItemAsMemberAccessException, newAccess); 64 | } 65 | } 66 | } 67 | 68 | if (newItems.Any()) 69 | { 70 | classNode = classNode.ReplaceNodes(newItems.Keys, (node1, node2) => 71 | { 72 | if (isReportOnlyMode) 73 | { 74 | var lineSpan = node1.GetFileLinePosSpan(); 75 | 76 | AddReport(new ChangesReport(classNode) 77 | { 78 | LineNumber = lineSpan.StartLinePosition.Line, 79 | Column = lineSpan.StartLinePosition.Character, 80 | Message = "you can remove this Identifier", 81 | Generator = nameof(RemoveExtraThisQualification) 82 | }); 83 | } 84 | 85 | return newItems[node1]; 86 | }); 87 | } 88 | 89 | return classNode; 90 | } 91 | 92 | SyntaxNode GetMemberAccessWithoutThis(MemberAccessExpressionSyntax thisItemAsMemberAccessException) 93 | { 94 | var thisItemAsMemberAccessExceptionSymbol = semanticModel.GetSymbolInfo(thisItemAsMemberAccessException).Symbol; 95 | 96 | if (thisItemAsMemberAccessExceptionSymbol is IFieldSymbol && !CheckOption((int)RemoveExtraThisKeyword.CleanupTypes.RemoveFromFieldsCall)) return null; 97 | if (thisItemAsMemberAccessExceptionSymbol is IPropertySymbol && !CheckOption((int)RemoveExtraThisKeyword.CleanupTypes.RemoveFromPropertiesCall)) return null; 98 | if (thisItemAsMemberAccessExceptionSymbol is IMethodSymbol && !CheckOption((int)RemoveExtraThisKeyword.CleanupTypes.RemoveFromMethodCall)) return null; 99 | 100 | var right = thisItemAsMemberAccessException.Name; 101 | var symbols = semanticModel.LookupSymbols(thisItemAsMemberAccessException.SpanStart, name: right.Identifier.ValueText); 102 | 103 | if (symbols.Any(x => SymbolEqualityComparer.Default.Equals(x, thisItemAsMemberAccessExceptionSymbol))) 104 | { 105 | return right.WithLeadingTrivia(thisItemAsMemberAccessException.GetLeadingTrivia()); 106 | } 107 | 108 | return null; 109 | } 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/CommandsHandlers/CleanupOptionForm.cs: -------------------------------------------------------------------------------- 1 | using Geeks.VSIX.TidyCSharp.Cleanup; 2 | using Geeks.VSIX.TidyCSharp.Cleanup.CommandsHandlers; 3 | using Geeks.VSIX.TidyCSharp.Menus.Cleanup.CommandsHandlers; 4 | using Geeks.VSIX.TidyCSharp.Properties; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Drawing; 8 | using System.Linq; 9 | using System.Windows.Forms; 10 | 11 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup.CommandsHandlers.Infra 12 | { 13 | public partial class CleanupOptionForm : Form 14 | { 15 | public static CleanupOptionForm Instance { get; set; } = new CleanupOptionForm(); 16 | public CleanupOptions CleanupOptions { get; private set; } 17 | public IList AllControls { get; private set; } = new List(); 18 | 19 | CleanupOptionForm() 20 | { 21 | InitializeComponent(); 22 | mainPanel.Padding = new Padding(5, 5, 5, 0); 23 | MaximumSize = new Size(1000, Screen.PrimaryScreen.WorkingArea.Height); 24 | base.ShowInTaskbar = false; 25 | base.WindowState = FormWindowState.Normal; 26 | StartPosition = FormStartPosition.CenterScreen; 27 | BackColor = Color.FromArgb(0xF0, 0xF0, 0xF0); 28 | 29 | CreateControls(); 30 | LoadFromSetting(); 31 | } 32 | 33 | void CreateControls() 34 | { 35 | CleanupItemUserControl.CreateControls(typeof(CodeCleanerType), cleanupTypeItem => CreateCleanupTypeItemControl(cleanupTypeItem), true); 36 | 37 | foreach (var itemControl in AllControls.OrderByDescending(x => x.Height)) 38 | { 39 | if(itemControl.IsDisposed) continue; 40 | itemControl.TabIndex = TAB_INDEX_START++; 41 | 42 | if (rightTableLayoutPanel.Height + itemControl.Height >= leftTableLayoutPanel.Height) 43 | { 44 | leftTableLayoutPanel.Controls.Add(itemControl); 45 | } 46 | else 47 | { 48 | rightTableLayoutPanel.Controls.Add(itemControl); 49 | } 50 | } 51 | } 52 | 53 | int TAB_INDEX_START = 3; 54 | 55 | void CreateCleanupTypeItemControl(CleanerItemUIInfo cleanupTypeItem) 56 | { 57 | var newControl = new CleanupItemUserControl() 58 | { 59 | Dock = DockStyle.Top, 60 | AutoSize = false, 61 | }; 62 | 63 | newControl.Init((CodeCleanerType)cleanupTypeItem.CleanerType); 64 | AllControls.Add(newControl); 65 | } 66 | 67 | void DeserializeValues(string strValue) 68 | { 69 | try 70 | { 71 | var choices = strValue.Split(new string[] { CleanupOptions.To_String_Seprator }, System.StringSplitOptions.RemoveEmptyEntries); 72 | 73 | var controls = rightTableLayoutPanel.Controls.OfType() 74 | .Union(leftTableLayoutPanel.Controls.OfType()); 75 | 76 | foreach (var item in choices) 77 | { 78 | var choiceItem = item.Split(new string[] { CleanupOptions.To_String_Seprator2 }, System.StringSplitOptions.RemoveEmptyEntries); 79 | 80 | var cleanUpType = (CodeCleanerType)int.Parse(choiceItem[0]); 81 | var isSelected = bool.Parse(choiceItem[1]); 82 | 83 | var selectedControls = controls.FirstOrDefault(c => c.MainCleanupItemType == cleanUpType); 84 | 85 | selectedControls?.SetMainItemCheckState(isSelected); 86 | selectedControls?.SetItemsCheckState(int.Parse(choiceItem[2]), true); 87 | } 88 | } 89 | catch 90 | { 91 | } 92 | } 93 | 94 | void LoadFromSetting() 95 | { 96 | if (string.IsNullOrEmpty(Settings.Default.CleanupChoices)) 97 | { 98 | foreach (IMainCleanup control in rightTableLayoutPanel.Controls.OfType() 99 | .Union(leftTableLayoutPanel.Controls.OfType())) 100 | control.ResetItemsCheckState(); 101 | 102 | return; 103 | } 104 | 105 | DeserializeValues(Settings.Default.CleanupChoices); 106 | return; 107 | } 108 | 109 | void ApplyCleanup() 110 | { 111 | CleanupOptions = new CleanupOptions(); 112 | 113 | foreach (CleanupItemUserControl item in rightTableLayoutPanel.Controls) 114 | CleanupOptions.Accept(item); 115 | 116 | foreach (CleanupItemUserControl item in leftTableLayoutPanel.Controls) 117 | CleanupOptions.Accept(item); 118 | 119 | Settings.Default.CleanupChoices = CleanupOptions.SerializeValues(); 120 | 121 | if (string.IsNullOrEmpty(Settings.Default.CleanupChoices)) 122 | { 123 | Settings.Default.CleanupChoices = "null"; 124 | } 125 | 126 | Settings.Default.Save(); 127 | } 128 | 129 | void btnApply_Click(object sender, EventArgs e) 130 | { 131 | ApplyCleanup(); 132 | DialogResult = DialogResult.OK; 133 | Close(); 134 | } 135 | } 136 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/RenameHelper/Lib/Extensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using System.Linq; 3 | 4 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup.Renaming 5 | { 6 | public static class Extensions 7 | { 8 | public static string GetFullNamespace(this ISymbol symbol) 9 | { 10 | if ((symbol.ContainingNamespace == null) || 11 | (string.IsNullOrEmpty(symbol.ContainingNamespace.Name))) 12 | { 13 | return null; 14 | } 15 | 16 | // get the rest of the full namespace string 17 | var restOfResult = symbol.ContainingNamespace.GetFullNamespace(); 18 | 19 | var result = symbol.ContainingNamespace.Name; 20 | 21 | if (restOfResult != null) 22 | // if restOfResult is not null, append it after a period 23 | result = restOfResult + '.' + result; 24 | 25 | return result; 26 | } 27 | 28 | public static string GetFullTypeString(this INamedTypeSymbol type) 29 | { 30 | var result = type.Name; 31 | 32 | if (type.TypeArguments.Count() > 0) 33 | { 34 | result += "<"; 35 | 36 | var isFirstIteration = true; 37 | 38 | foreach (INamedTypeSymbol typeArg in type.TypeArguments) 39 | { 40 | if (isFirstIteration) isFirstIteration = false; 41 | else result += ", "; 42 | 43 | result += typeArg.GetFullTypeString(); 44 | } 45 | 46 | result += ">"; 47 | } 48 | 49 | return result; 50 | } 51 | 52 | public static string ConvertAccessabilityToString(this Accessibility accessability) 53 | { 54 | switch (accessability) 55 | { 56 | case Accessibility.Internal: 57 | return "internal"; 58 | case Accessibility.Private: 59 | return "private"; 60 | case Accessibility.Protected: 61 | return "protected"; 62 | case Accessibility.Public: 63 | return "public"; 64 | case Accessibility.ProtectedAndInternal: 65 | return "protected internal"; 66 | default: 67 | return "private"; 68 | } 69 | } 70 | 71 | public static string GetMethodSignature(this IMethodSymbol methodSymbol) 72 | { 73 | var result = methodSymbol.DeclaredAccessibility.ConvertAccessabilityToString(); 74 | 75 | if (methodSymbol.IsAsync) result += " async"; 76 | 77 | if (methodSymbol.IsAbstract) 78 | result += " abstract"; 79 | 80 | if (methodSymbol.IsVirtual) result += " virtual"; 81 | 82 | if (methodSymbol.IsStatic) result += " static"; 83 | 84 | if (methodSymbol.IsOverride) 85 | { 86 | result += " override"; 87 | } 88 | 89 | if (methodSymbol.ReturnsVoid) 90 | { 91 | result += " void"; 92 | } 93 | else 94 | { 95 | result += " " + (methodSymbol.ReturnType as INamedTypeSymbol).GetFullTypeString(); 96 | } 97 | 98 | result += " " + methodSymbol.Name + "("; 99 | 100 | var isFirstParameter = true; 101 | 102 | foreach (IParameterSymbol parameter in methodSymbol.Parameters) 103 | { 104 | if (isFirstParameter) isFirstParameter = false; 105 | else result += ", "; 106 | 107 | if (parameter.RefKind == RefKind.Out) 108 | { 109 | result += "out "; 110 | } 111 | else if (parameter.RefKind == RefKind.Ref) 112 | { 113 | result += "ref "; 114 | } 115 | 116 | var parameterTypeString = 117 | (parameter.Type as INamedTypeSymbol).GetFullTypeString(); 118 | 119 | result += parameterTypeString; 120 | 121 | result += " " + parameter.Name; 122 | 123 | if (parameter.HasExplicitDefaultValue) 124 | { 125 | result += " = " + parameter.ExplicitDefaultValue.ToString(); 126 | } 127 | } 128 | 129 | result += ")"; 130 | 131 | return result; 132 | } 133 | 134 | public static object GetAttributeConstructorValueByParameterName(this AttributeData attributeData, string argName) 135 | { 136 | // Get the parameter 137 | var parameterSymbol = attributeData.AttributeConstructor 138 | .Parameters 139 | .Where((constructorParam) => constructorParam.Name == argName).FirstOrDefault(); 140 | 141 | // get the index of the parameter 142 | var parameterIdx = attributeData.AttributeConstructor.Parameters.IndexOf(parameterSymbol); 143 | 144 | // get the construct argument corresponding to this parameter 145 | var constructorArg = attributeData.ConstructorArguments[parameterIdx]; 146 | 147 | // return the value passed to the attribute 148 | return constructorArg.Value; 149 | } 150 | } 151 | } -------------------------------------------------------------------------------- /TidyCSharp/Menus/Cleanup/Utils/TypesMapItem.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis.CSharp; 2 | using Microsoft.CodeAnalysis.CSharp.Syntax; 3 | using Microsoft.CSharp; 4 | using System; 5 | using System.CodeDom; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace Geeks.GeeksProductivityTools.Menus.Cleanup 10 | { 11 | public class TypesMapItem 12 | { 13 | public string Name { get; set; } 14 | public string FullName { get; set; } 15 | public string BuiltInName { get; set; } 16 | 17 | Type _builtInType; 18 | public Type BuiltInType 19 | { 20 | get 21 | { 22 | if (_builtInType != null) return _builtInType; 23 | if (string.IsNullOrEmpty(BuiltInName)) return _builtInType; 24 | 25 | _builtInType = Type.GetType(FullName); 26 | 27 | GetTypeDefaultValue(); 28 | 29 | return _builtInType; 30 | } 31 | } 32 | 33 | object _defaultValue; 34 | public object DefaultValue => GetTypeDefaultValue(); 35 | 36 | object GetTypeDefaultValue() 37 | { 38 | if (BuiltInType == null) return null; 39 | if (_defaultValue != null) return _defaultValue; 40 | 41 | if (BuiltInType.IsValueType) 42 | { 43 | _defaultValue = Activator.CreateInstance(BuiltInType); 44 | } 45 | 46 | return _defaultValue; 47 | } 48 | 49 | public TypeSyntax NewNode { get; set; } 50 | 51 | internal static TypesMapItem GetBuiltInTypes(Type type, TypeSyntax node, CSharpCodeProvider provider) 52 | { 53 | return new TypesMapItem 54 | { 55 | Name = type.Name, 56 | FullName = type.FullName, 57 | BuiltInName = provider.GetTypeOutput(new CodeTypeReference(type)), 58 | NewNode = node 59 | }; 60 | } 61 | 62 | internal static TypeSyntax GetPredefineType(SyntaxKind keyword) 63 | { 64 | return SyntaxFactory.PredefinedType(SyntaxFactory.Token(keyword)); 65 | } 66 | 67 | static Dictionary BuiltInTypesDic, _predefinedTypesDic; 68 | public static Dictionary GetBuiltInTypesDic() 69 | { 70 | if (BuiltInTypesDic != null) return BuiltInTypesDic; 71 | 72 | var output = new Dictionary(); 73 | 74 | using (var provider = new CSharpCodeProvider()) 75 | { 76 | var typesList = new TypesMapItem[] 77 | { 78 | GetBuiltInTypes(Type.GetType("System.Boolean"), GetPredefineType(SyntaxKind.BoolKeyword), provider), 79 | GetBuiltInTypes(Type.GetType("System.Byte"), GetPredefineType(SyntaxKind.ByteKeyword), provider), 80 | GetBuiltInTypes(Type.GetType("System.SByte"), GetPredefineType(SyntaxKind.SByteKeyword), provider), 81 | GetBuiltInTypes(Type.GetType("System.Char"), GetPredefineType(SyntaxKind.CharKeyword), provider), 82 | GetBuiltInTypes(Type.GetType("System.Decimal"), GetPredefineType(SyntaxKind.DecimalKeyword), provider), 83 | GetBuiltInTypes(Type.GetType("System.Double"), GetPredefineType(SyntaxKind.DoubleKeyword), provider), 84 | GetBuiltInTypes(Type.GetType("System.Single"), GetPredefineType(SyntaxKind.FloatKeyword), provider), 85 | GetBuiltInTypes(Type.GetType("System.Int32"), GetPredefineType(SyntaxKind.IntKeyword), provider), 86 | GetBuiltInTypes(Type.GetType("System.UInt32"), GetPredefineType(SyntaxKind.UIntKeyword), provider), 87 | GetBuiltInTypes(Type.GetType("System.Int64"), GetPredefineType(SyntaxKind.LongKeyword), provider), 88 | GetBuiltInTypes(Type.GetType("System.UInt64"), GetPredefineType(SyntaxKind.ULongKeyword), provider), 89 | GetBuiltInTypes(Type.GetType("System.Object"), GetPredefineType(SyntaxKind.ObjectKeyword), provider), 90 | GetBuiltInTypes(Type.GetType("System.Int16"), GetPredefineType(SyntaxKind.ShortKeyword), provider), 91 | GetBuiltInTypes(Type.GetType("System.UInt16"), GetPredefineType(SyntaxKind.UShortKeyword), provider), 92 | GetBuiltInTypes(Type.GetType("System.String"), GetPredefineType(SyntaxKind.StringKeyword), provider), 93 | }; 94 | 95 | foreach (var item in typesList) 96 | { 97 | output.Add(item.Name, item); 98 | output.Add(item.FullName, item); 99 | } 100 | 101 | return BuiltInTypesDic = output; 102 | } 103 | } 104 | 105 | internal static Dictionary GetAllPredefinedTypesDic() 106 | { 107 | if (_predefinedTypesDic != null) return _predefinedTypesDic; 108 | 109 | var output = GetBuiltInTypesDic(); 110 | 111 | using (var provider = new CSharpCodeProvider()) 112 | { 113 | var oldValues = output.Values.GroupBy(x => x.BuiltInName).ToList(); 114 | 115 | foreach (var item0 in oldValues) 116 | { 117 | var item = item0.FirstOrDefault(); 118 | 119 | output.Add(item.BuiltInName, new TypesMapItem { BuiltInName = item.BuiltInName, Name = item.BuiltInName, FullName = item.FullName }); 120 | } 121 | 122 | return _predefinedTypesDic = output; 123 | } 124 | } 125 | } 126 | } --------------------------------------------------------------------------------