diff --git a/.gitignore b/.gitignore index 4ead766..f9ca77d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,215 +1,19 @@ -################# -## Eclipse -################# - -*.pydevproject -.project -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.classpath -.settings/ -.loadpath - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# CDT-specific -.cproject - -# PDT-specific -.buildpath - - ################# ## Visual Studio ################# -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - # User-specific files *.suo *.user -*.sln.docstates # Build results - [Dd]ebug/ [Rr]elease/ -x64/ -build/ [Bb]in/ [Oo]bj/ -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -*_i.c -*_p.c -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.log -*.scc - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -*.ncrunch* -.*crunch*.local.xml - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.Publish.xml -*.pubxml - # NuGet Packages Directory -## TODO: If you have NuGet Package Restore enabled, uncomment the next line packages/ -# Windows Azure Build Output -csx -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.[Pp]ublish.xml -*.pfx -*.publishsettings - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file to a newer -# Visual Studio version. Backup files are not needed, because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -App_Data/*.mdf -App_Data/*.ldf - -############# -## Windows detritus -############# - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Mac crap -.DS_Store - - -############# -## Python -############# - -*.py[co] - -# Packages -*.egg -*.egg-info -dist/ -build/ -eggs/ -parts/ -var/ -sdist/ -develop-eggs/ -.installed.cfg - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -.tox - -#Translations -*.mo - -#Mr Developer -.mr.developer.cfg +# Build artifacts +*.nupkg diff --git a/CleanCode/src/NuGet.Packager/Package.nuspec b/CleanCode/src/CleanCode.nuspec similarity index 57% rename from CleanCode/src/NuGet.Packager/Package.nuspec rename to CleanCode/src/CleanCode.nuspec index b233c63..5acc271 100644 --- a/CleanCode/src/NuGet.Packager/Package.nuspec +++ b/CleanCode/src/CleanCode.nuspec @@ -1,9 +1,9 @@  - CleanCode - 4.0.0.0 - CleanCode + CleanCode.CleanCode + 5.1.0 + Clean Code Hadi Hariri, Matt Ellis, SuperJMN Hadi Hariri, Matt Ellis https://raw.githubusercontent.com/hhariri/CleanCode/master/logo.png @@ -11,21 +11,36 @@ https://raw.github.com/hhariri/CleanCode/master/license.txt false Automates some of the concepts in Uncle Bob's Clean Code book - Major update, thanks to @SuperJMN! + +• Updated to ReSharper 2017.1 + +From 5.0.3: +• Stop marking abstract methods too long (#19) + +From 5.0.2: +• Method parameter and type parameter declarations mistakenly used for "method too long" check (#12) + +From 5.0.1: +• Updated to ReSharper 2016.2 +• Fix minor installer issue + +From 4.0.0: +• Warning if a method uses flag parameters • Warning if a method contains too many nested blocks • Warning if a method name is too short to be meaningful • Warning if an epression is breaking the Law of Demeter • Warning if a constructor has too many parameters, indicating too many dependencies • Warning if a method has too many arguments • Suggestion highlight if class has too many methods -• Suggestion highlight if method has too many statements - Copyright 2014 Hadi Hariri and Contributors +• Suggestion highlight if method has too many statements + + Copyright 2014-2016 Hadi Hariri and Contributors - + clean code - - + + diff --git a/CleanCode/src/CleanCode.sln b/CleanCode/src/CleanCode.sln index 9321c79..e960136 100644 --- a/CleanCode/src/CleanCode.sln +++ b/CleanCode/src/CleanCode.sln @@ -1,11 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30501.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanCode.8.2", "CleanCode\CleanCode.8.2.csproj", "{5F96119C-2646-4298-AD40-30209E7E7BB2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NuGet.Packager", "NuGet.Packager\NuGet.Packager.csproj", "{0451BAEF-DF2E-4B98-8644-94EE9415E389}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanCode", "CleanCode\CleanCode.csproj", "{5F96119C-2646-4298-AD40-30209E7E7BB2}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,9 +15,6 @@ Global {5F96119C-2646-4298-AD40-30209E7E7BB2}.Debug|Any CPU.Build.0 = Debug|Any CPU {5F96119C-2646-4298-AD40-30209E7E7BB2}.Release|Any CPU.ActiveCfg = Release|Any CPU {5F96119C-2646-4298-AD40-30209E7E7BB2}.Release|Any CPU.Build.0 = Release|Any CPU - {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/CleanCode/src/CleanCode/CleanCode.8.2.csproj b/CleanCode/src/CleanCode/CleanCode.8.2.csproj deleted file mode 100644 index df96a5e..0000000 --- a/CleanCode/src/CleanCode/CleanCode.8.2.csproj +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {5F96119C-2646-4298-AD40-30209E7E7BB2} - Library - Properties - CleanCode - CleanCode.8.2 - v4.0 - 512 - - - - true - full - false - bin\Debug\ - TRACE;DEBUG;JET_MODE_ASSERT,RESHARPER_82 - prompt - 4 - - - pdbonly - true - ..\NuGet.Packager\lib\ - TRACE;RESHARPER_81 - prompt - 4 - - - Program - $(VsInstallDir)devenv.exe - /ReSharper.Plugin $(AssemblyName).dll /ReSharper.Internal - $(MSBuildProjectDirectory)\$(OutputPath) - - - - - - - - - - - - - - - - - - - - - - - - Code - - - Code - - - - - - Code - - - Code - - - - - Code - - - Code - - - - - Code - - - Code - - - - - Warnings.resx - True - True - - - - - True - True - Settings.resx - - - - OptionsPage.xaml - - - - - - - PublicResXFileCodeGenerator - Settings.Designer.cs - Designer - - - PublicResXFileCodeGenerator - Warnings.Designer.cs - Designer - - - - - - - - MSBuild:Compile - Designer - - - Designer - MSBuild:Compile - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - \ No newline at end of file diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj new file mode 100644 index 0000000..d6ea69a --- /dev/null +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -0,0 +1,409 @@ + + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {5F96119C-2646-4298-AD40-30209E7E7BB2} + Library + Properties + CleanCode + CleanCode + v4.5 + 512 + + aa44b150 + + + true + full + false + bin\Debug\ + TRACE;DEBUG;JET_MODE_ASSERT + prompt + 4 + + + pdbonly + true + TRACE + prompt + 4 + bin\Release\ + + + + ..\packages\Antlr2.Runtime.2.7.7.02\lib\antlr.runtime.dll + True + + + ..\packages\Appccelerate.StateMachine.JetBrains.2.2.0.1\lib\net45\Appccelerate.Fundamentals.dll + True + + + ..\packages\Appccelerate.StateMachine.JetBrains.2.2.0.1\lib\net45\Appccelerate.StateMachine.dll + True + + + ..\packages\xmlrpcnet.2.5.0\lib\net20\CookComputing.XmlRpcV2.dll + True + + + ..\packages\JetBrains.Platform.Lib.DevExpress.2.0.20150224.0\lib\Net\DevExpress.Data.v7.1.dll + True + + + ..\packages\JetBrains.Platform.Lib.DevExpress.2.0.20150224.0\lib\Net\DevExpress.Utils.v7.1.dll + True + + + ..\packages\JetBrains.Platform.Lib.DevExpress.2.0.20150224.0\lib\Net\DevExpress.XtraEditors.v7.1.dll + True + + + ..\packages\JetBrains.Platform.Lib.DevExpress.2.0.20150224.0\lib\Net\DevExpress.XtraTreeList.v7.1.dll + True + + + ..\packages\SharpZipLib.JetBrains.Stripped.0.87.20161027.6\lib\net40\ICSharpCode.SharpZipLib.dll + True + + + ..\packages\DotNetZip.Reduced.1.9.1.8\lib\net20\Ionic.Zip.Reduced.dll + True + + + ..\packages\JetBrains.Annotations.10.4.0\lib\net\JetBrains.Annotations.dll + True + + + ..\packages\JetBrains.Platform.MSBuild.Logger.1.0.20170130.0\lib\net\JetBrains.MSBuild.Logger.dll + True + True + + + ..\packages\JetBrains.System.Reflection.Metadata.1.0.0\lib\net45\JetBrains.System.Reflection.Metadata.dll + True + + + ..\packages\JetBrains.MahApps.Metro.1.3.1\lib\net45\MahApps.Metro.dll + True + + + ..\packages\JetBrains.Platform.Lib.Microsoft.Deployment.Compression.Cab.2.0.20140304.0\lib\Microsoft.Deployment.Compression.dll + True + + + ..\packages\JetBrains.Platform.Lib.Microsoft.Deployment.Compression.Cab.2.0.20140304.0\lib\Microsoft.Deployment.Compression.Cab.dll + True + + + ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll + True + + + ..\packages\Microsoft.Owin.FileSystems.3.0.1\lib\net45\Microsoft.Owin.FileSystems.dll + True + + + ..\packages\Microsoft.Owin.Host.HttpListener.3.0.1\lib\net45\Microsoft.Owin.Host.HttpListener.dll + True + + + ..\packages\Microsoft.Owin.Hosting.3.0.1\lib\net45\Microsoft.Owin.Hosting.dll + True + + + ..\packages\Microsoft.Owin.StaticFiles.3.0.1\lib\net45\Microsoft.Owin.StaticFiles.dll + True + + + ..\packages\Microsoft.Web.Xdt.2.1.1\lib\net40\Microsoft.Web.XmlTransform.dll + True + + + ..\packages\Windows7APICodePack.JetBrains.Stripped.1.1.20150225.0\lib\Net\Microsoft.WindowsAPICodePack.dll + True + + + ..\packages\Windows7APICodePack.JetBrains.Stripped.1.1.20150225.0\lib\Net\Microsoft.WindowsAPICodePack.Shell.dll + True + + + ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Client.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Commands.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Common.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Configuration.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.ContentModel.dll + True + + + ..\packages\JetBrains.NuGet.Core.2.14.1\lib\net40-Client\NuGet.Core.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.DependencyResolver.Core.dll + True + + + ..\packages\JetBrains.NuGet.Frameworks.4.0.0\lib\net45\NuGet.Frameworks.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.LibraryModel.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.PackageManagement.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Packaging.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Packaging.Core.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Packaging.Core.Types.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.ProjectManagement.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.ProjectModel.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Protocol.Core.Types.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Protocol.Core.v2.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Protocol.Core.v3.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Protocol.VisualStudio.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Repositories.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Resolver.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.RuntimeModel.dll + True + + + ..\packages\JetBrains.NuGet.Versioning.4.0.0\lib\net45\NuGet.Versioning.dll + True + + + ..\packages\NUnit.2.6.4\lib\nunit.framework.dll + True + + + ..\packages\NVelocity.1.0.3\lib\NVelocity.dll + True + + + ..\packages\Owin.1.0\lib\net40\Owin.dll + True + + + + + ..\packages\sharpcompress.0.11.6\lib\net40\SharpCompress.dll + True + + + ..\packages\Sprache.JetBrains.2.1.0\lib\net40\Sprache.dll + True + + + + + + + + + + + + + ..\packages\JetBrains.Platform.Lib.System.Windows.Interactivity.3.0.40218\lib\System.Windows.Interactivity.dll + True + + + + + + + + + + ..\packages\Vestris.ResourceLib.JetBrains.1.4.20150303.0\lib\Net\Vestris.ResourceLib.dll + True + + + + ..\packages\JetBrains.Platform.Lib.WpfContrib.2.0.20150225.0\lib\Net\WpfContrib.dll + True + + + ..\packages\xunit.JetBrains.1.9.2\lib\net20\xunit.dll + True + + + ..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll + True + + + ..\packages\xunit.runner.utility.2.2.0\lib\net35\xunit.runner.utility.net35.dll + True + + + + + + + + + + + + + + + + + + + + Code + + + + Code + + + + + Code + + + + + + + True + True + Settings.resx + + + Warnings.resx + True + True + + + + + + + + PublicResXFileCodeGenerator + Designer + Settings.Designer.cs + + + PublicResXFileCodeGenerator + Warnings.Designer.cs + Designer + + + + + MSBuild:Compile + Designer + + + + + + + + CleanCode.nuspec + Designer + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs deleted file mode 100644 index 7581ea5..0000000 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region License - -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. - -#endregion - -using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Psi.CSharp.Tree; - -namespace CleanCode -{ - [DaemonStage] - public class CleanCodeDaemonStage : CSharpDaemonStageBase - { - protected override IDaemonStageProcess CreateProcess(IDaemonProcess process, IContextBoundSettingsStore settings, - DaemonProcessKind processKind, ICSharpFile file) - { - return new CleanCodeDaemonStageProcess(process, file, settings); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs deleted file mode 100644 index 3272abf..0000000 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ /dev/null @@ -1,100 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using System; -using CleanCode.Features.ClassTooBig; -using CleanCode.Features.ExcessiveIndentation; -using CleanCode.Features.MethodNameNotMeaningful; -using CleanCode.Features.MethodTooLong; -using CleanCode.Features.TooManyChainedReferences; -using CleanCode.Features.TooManyDependencies; -using CleanCode.Features.TooManyMethodArguments; -using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; -using JetBrains.ReSharper.Psi; -using JetBrains.ReSharper.Psi.CSharp.Tree; - -namespace CleanCode -{ - public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase - { - private readonly IContextBoundSettingsStore settingsStore; - - private readonly MethodTooLongCheck methodTooLongCheck; - private readonly ClassTooBigCheck classTooBigCheck; - private readonly TooManyMethodArgumentsCheck tooManyArgumentsCheck; - private readonly ExcessiveIndentationCheck excessiveIndentationCheck; - private readonly TooManyDependenciesCheck tooManyDependenciesCheck; - private readonly MethodNamesNotMeaningfulCheck methodNamesNotMeaningfulCheck; - private readonly TooManyChainedReferencesCheck tooManyChainedReferencesCheck; - - public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile file, IContextBoundSettingsStore settingsStore) - : base(daemonProcess, file) - { - this.settingsStore = settingsStore; - - // Simple checks. - methodTooLongCheck = new MethodTooLongCheck(settingsStore); - classTooBigCheck = new ClassTooBigCheck(settingsStore); - tooManyArgumentsCheck = new TooManyMethodArgumentsCheck(settingsStore); - excessiveIndentationCheck = new ExcessiveIndentationCheck(settingsStore); - tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); - methodNamesNotMeaningfulCheck = new MethodNamesNotMeaningfulCheck(settingsStore); - tooManyChainedReferencesCheck = new TooManyChainedReferencesCheck(settingsStore); - } - - public override void Execute(Action commiter) - { - HighlightInFile((file, consumer) => file.ProcessDescendants(this, consumer), commiter, settingsStore); - } - - public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration, IHighlightingConsumer context) - { - methodTooLongCheck.ExecuteIfEnabled(methodDeclaration, context); - tooManyArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); - excessiveIndentationCheck.ExecuteIfEnabled(methodDeclaration, context); - methodNamesNotMeaningfulCheck.ExecuteIfEnabled(methodDeclaration, context); - } - - public override void VisitConstructorDeclaration(IConstructorDeclaration constructorDeclaration, IHighlightingConsumer context) - { - tooManyDependenciesCheck.ExecuteIfEnabled(constructorDeclaration, context); - } - - public override void VisitReferenceExpression(IReferenceExpression referenceExpressionParam, IHighlightingConsumer context) - { - tooManyChainedReferencesCheck.ExecuteIfEnabled(referenceExpressionParam, context); - } - - public override void VisitClassDeclaration(IClassDeclaration classDeclaration, IHighlightingConsumer context) - { - classTooBigCheck.ExecuteIfEnabled(classDeclaration, context); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/CleanCodeHighlightingGroupIds.cs b/CleanCode/src/CleanCode/CleanCodeHighlightingGroupIds.cs new file mode 100644 index 0000000..30d5108 --- /dev/null +++ b/CleanCode/src/CleanCode/CleanCodeHighlightingGroupIds.cs @@ -0,0 +1,12 @@ +using CleanCode; +using JetBrains.ReSharper.Feature.Services.Daemon; + +[assembly: RegisterConfigurableHighlightingsGroup(CleanCodeHighlightingGroupIds.CleanCode, "Clean Code")] + +namespace CleanCode +{ + public static class CleanCodeHighlightingGroupIds + { + public const string CleanCode = "CleanCode"; + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs new file mode 100644 index 0000000..cf9a714 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs @@ -0,0 +1,85 @@ +using System.Collections.Generic; +using CleanCode.Resources; +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.Tree; + +namespace CleanCode.Features.ChainedReferences +{ + [ElementProblemAnalyzer(typeof(ICSharpStatement), HighlightingTypes = new [] + { + typeof(MaximumChainedReferencesHighlighting) + })] + public class ChainedReferencesCheck : ElementProblemAnalyzer + { + protected override void Run(ICSharpStatement element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) + { + if (!element.CanBeEmbedded) + { + var threshold = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumChainedReferences); + HighlightMethodChainsThatAreTooLong(element, consumer, threshold); + } + } + + private void HighlightMethodChainsThatAreTooLong(ITreeNode statement, IHighlightingConsumer consumer, int threshold) + { + var children = statement.Children(); + + foreach (var treeNode in children) + { + var referenceExpression = treeNode as IReferenceExpression; + if (referenceExpression != null) + { + HighlightReferenceExpressionIfNeeded(referenceExpression, consumer, threshold); + } + else + { + HighlightMethodChainsThatAreTooLong(treeNode, consumer, threshold); + } + } + } + + private void HighlightReferenceExpressionIfNeeded(IReferenceExpression referenceExpression, IHighlightingConsumer consumer, int threshold) + { + var types = new HashSet(); + + var nextReferenceExpression = referenceExpression; + var chainLength = 0; + + while (nextReferenceExpression != null) + { + var childReturnType = ExtensionMethods.TryGetClosedReturnTypeFrom(nextReferenceExpression); + + if (childReturnType != null) + { + types.Add(childReturnType); + chainLength++; + } + + nextReferenceExpression = ExtensionMethods.TryGetFirstReferenceExpression(nextReferenceExpression); + } + + var isFluentChain = types.Count == 1; + + if (!isFluentChain) + { + if (chainLength > threshold) + { + AddHighlighting(referenceExpression, consumer); + } + } + } + + private static void AddHighlighting(IReferenceExpression reference, IHighlightingConsumer consumer) + { + var nameIdentifier = reference.NameIdentifier; + var documentRange = nameIdentifier.GetDocumentRange(); + var highlighting = new MaximumChainedReferencesHighlighting(Warnings.ChainedReferences, documentRange); + consumer.AddHighlighting(highlighting); + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs new file mode 100644 index 0000000..5b8ae6c --- /dev/null +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs @@ -0,0 +1,31 @@ +using CleanCode; +using CleanCode.Features.ChainedReferences; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly: RegisterConfigurableSeverity(MaximumChainedReferencesHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Too many chained references", "Too many chained references can break the Law of Demeter.", + Severity.WARNING)] + +namespace CleanCode.Features.ChainedReferences +{ + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class MaximumChainedReferencesHighlighting : IHighlighting + { + internal const string SeverityID = "TooManyChainedReferences"; + + private readonly DocumentRange documentRange; + + public MaximumChainedReferencesHighlighting(string toolTip, DocumentRange documentRange) + { + ToolTip = toolTip; + this.documentRange = documentRange; + } + + public DocumentRange CalculateRange() => documentRange; + public string ToolTip { get; } + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs index 0abbc53..14c7b69 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs @@ -1,42 +1,31 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; namespace CleanCode.Features.ClassTooBig { - public class ClassTooBigCheck : SimpleCheck + [ElementProblemAnalyzer(typeof(IClassDeclaration), HighlightingTypes = new [] { - public ClassTooBigCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override void ExecuteCore(IClassDeclaration classDeclaration, IHighlightingConsumer consumer) + typeof(ClassTooBigHighlighting) + })] + public class ClassTooBigCheck : ElementProblemAnalyzer + { + protected override void Run(IClassDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var maxLength = Threshold; + var maxLength = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumMethodsInClass); - var statementCount = classDeclaration.CountChildren(); + var statementCount = element.CountChildren(); if (statementCount > maxLength) { - var declarationIdentifier = classDeclaration.NameIdentifier; + var declarationIdentifier = element.NameIdentifier; var documentRange = declarationIdentifier.GetDocumentRange(); - var highlighting = new Highlighting(Warnings.ClassTooBig); - consumer.AddHighlighting(highlighting, documentRange); + var highlighting = new ClassTooBigHighlighting(Warnings.ClassTooBig, documentRange); + consumer.AddHighlighting(highlighting); } } - - protected override int Threshold - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigEnabled); } - } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs new file mode 100644 index 0000000..d417805 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs @@ -0,0 +1,31 @@ +using CleanCode; +using CleanCode.Features.ClassTooBig; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly: RegisterConfigurableSeverity(ClassTooBigHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Class too big", "This class contains too many methods", + Severity.SUGGESTION)] + +namespace CleanCode.Features.ClassTooBig +{ + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class ClassTooBigHighlighting : IHighlighting + { + internal const string SeverityID = "ClassTooBig"; + + private readonly DocumentRange documentRange; + + public ClassTooBigHighlighting(string toolTip, DocumentRange documentRange) + { + ToolTip = toolTip; + this.documentRange = documentRange; + } + + public DocumentRange CalculateRange() => documentRange; + public string ToolTip { get; } + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs deleted file mode 100644 index 0954796..0000000 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs +++ /dev/null @@ -1,69 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Features.ClassTooBig; -using JetBrains.ReSharper.Daemon; -using JetBrains.ReSharper.Psi.CSharp; - -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Class Too Big", "This class contains too many methods", - Severity.SUGGESTION, false)] - -namespace CleanCode.Features.ClassTooBig -{ - [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting - { - internal const string SeverityID = "ClassTooBig"; - private readonly string tooltip; - - public Highlighting(string toolTip) - { - tooltip = toolTip; - } - - public string ToolTip - { - get { return tooltip; } - } - - public string ErrorStripeToolTip - { - get { return tooltip; } - } - - public int NavigationOffsetPatch - { - get { return 0; } - } - - public bool IsValid() - { - return true; - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs deleted file mode 100644 index b512039..0000000 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs +++ /dev/null @@ -1,45 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; - -namespace CleanCode.Features.ClassTooBig -{ - [SolutionComponent] - public class InvalidateOnMaximumMethodsPerClass - { - public InvalidateOnMaximumMethodsPerClass(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) - { - var maxDepth = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.ClassTooBigMaximum); - settingsStore.AdviseChange(lifetime, maxDepth, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs new file mode 100644 index 0000000..131c11f --- /dev/null +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs @@ -0,0 +1,73 @@ +using System.Linq; +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.Tree; + +namespace CleanCode.Features.ComplexExpression +{ + // TODO: This might be better working with IOperatorExpression + // Walk up from the operator to the highest containing expression + // and count depth? + [ElementProblemAnalyzer(typeof(IIfStatement), + typeof(ILoopWithConditionStatement), + typeof(IConditionalTernaryExpression), + typeof(IAssignmentExpression), + typeof(IExpressionInitializer), + HighlightingTypes = new[] + { + typeof(ComplexConditionExpressionHighlighting) + })] + public class ComplexConditionExpressionCheck : ElementProblemAnalyzer + { + protected override void Run(ICSharpTreeNode element, ElementProblemAnalyzerData data, + IHighlightingConsumer consumer) + { + var expression = GetExpression(element); + if (expression != null) + CheckExpression(expression, data, consumer); + } + + private static IExpression GetExpression(ITreeNode node) + { + // Covers for, while and do + var loopStatement = node as ILoopWithConditionStatement; + if (loopStatement != null) + return loopStatement.Condition; + + var ifStatement = node as IIfStatement; + if (ifStatement != null) + return ifStatement.Condition; + + var conditionalTernaryExpression = node as IConditionalTernaryExpression; + if (conditionalTernaryExpression != null) + return conditionalTernaryExpression.ConditionOperand; + + // TODO: Should these two be part of this check? + // Perhaps they should also check the type of the resulting + // variable to be bool? + var assignmentExpression = node as IAssignmentExpression; + if (assignmentExpression != null) + return assignmentExpression.Source; + + var expressionInitializer = node as IExpressionInitializer; + return expressionInitializer?.Value; + } + + private static void CheckExpression(IExpression expression, ElementProblemAnalyzerData data, + IHighlightingConsumer consumer) + { + var maxExpressions = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumExpressionsInCondition); + var expressionCount = expression.GetChildrenRecursive().Count(); + + if (expressionCount > maxExpressions) + { + var documentRange = expression.GetDocumentRange(); + var highlighting = new ComplexConditionExpressionHighlighting(documentRange); + consumer.AddHighlighting(highlighting); + } + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs new file mode 100644 index 0000000..e2ddaa9 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs @@ -0,0 +1,31 @@ +using CleanCode; +using CleanCode.Features.ComplexExpression; +using CleanCode.Resources; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly:RegisterConfigurableSeverity(ComplexConditionExpressionHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Condition expression too complex", "The expression in the condition is too complex.", + Severity.WARNING)] + +namespace CleanCode.Features.ComplexExpression +{ + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class ComplexConditionExpressionHighlighting : IHighlighting + { + internal const string SeverityID = "ComplexConditionExpression"; + + private readonly DocumentRange documentRange; + + public ComplexConditionExpressionHighlighting(DocumentRange documentRange) + { + this.documentRange = documentRange; + } + + public DocumentRange CalculateRange() => documentRange; + public string ToolTip => Warnings.ExpressionTooComplex; + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs new file mode 100644 index 0000000..7292d80 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs @@ -0,0 +1,30 @@ +using CleanCode; +using CleanCode.Features.ExcessiveIndentation; +using CleanCode.Resources; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly:RegisterConfigurableSeverity(ExcessiveIndentHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Excessive indentation", "The nesting in this method is excessive.", + Severity.WARNING)] + +namespace CleanCode.Features.ExcessiveIndentation +{ + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class ExcessiveIndentHighlighting : IHighlighting + { + internal const string SeverityID = "ExcessiveIndentation"; + private readonly DocumentRange documentRange; + + public ExcessiveIndentHighlighting(DocumentRange documentRange) + { + this.documentRange = documentRange; + } + + public DocumentRange CalculateRange() => documentRange; + public string ToolTip => Warnings.ExcessiveDepth; + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs index 6252577..4f664cf 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs @@ -1,40 +1,30 @@ -using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; namespace CleanCode.Features.ExcessiveIndentation { - public class ExcessiveIndentationCheck : SimpleCheck - { - public ExcessiveIndentationCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) + [ElementProblemAnalyzer(typeof(IMethodDeclaration), + HighlightingTypes = new [] { - } - - protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) + typeof(ExcessiveIndentHighlighting) + })] + public class ExcessiveIndentationCheck : ElementProblemAnalyzer + { + protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var maxIndentation = Threshold; - var depth = classDeclaration.GetChildrenDepth(); + var maxIndentation = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumIndentationDepth); + var depth = element.GetChildrenDepth(); if (depth > maxIndentation) { - var highlighting = new Highlighting(Warnings.ExcessiveDepth); - consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); + var documentRange = element.GetNameDocumentRange(); + var highlighting = new ExcessiveIndentHighlighting(documentRange); + consumer.AddHighlighting(highlighting); } } - - protected override int Threshold - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationEnabled); } - } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs deleted file mode 100644 index 1086f2f..0000000 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs +++ /dev/null @@ -1,72 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Features.ExcessiveIndentation; -using JetBrains.ReSharper.Daemon; -using JetBrains.ReSharper.Psi.CSharp; - -[assembly:RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Excessive Depth", "The nesting in this method is excessive.", - Severity.WARNING, false)] - -namespace CleanCode.Features.ExcessiveIndentation -{ - /// - /// The highlighting that warns about high complexity - /// - [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting - { - internal const string SeverityID = "ExcessiveIndentation"; - private readonly string tooltip; - - public Highlighting(string toolTip) - { - tooltip = toolTip; - } - - public string ToolTip - { - get { return tooltip; } - } - - public string ErrorStripeToolTip - { - get { return tooltip; } - } - - public int NavigationOffsetPatch - { - get { return 0; } - } - - public bool IsValid() - { - return true; - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/InvalidateOnExcessiveIndentationChange.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/InvalidateOnExcessiveIndentationChange.cs deleted file mode 100644 index 211c5f6..0000000 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/InvalidateOnExcessiveIndentationChange.cs +++ /dev/null @@ -1,45 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; - -namespace CleanCode.Features.ExcessiveIndentation -{ - [SolutionComponent] - public class InvalidateOnExcessiveIndentationChange - { - public InvalidateOnExcessiveIndentationChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) - { - var maxDepth = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.ExcessiveIndentationMaximum); - settingsStore.AdviseChange(lifetime, maxDepth, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ExtensionMethods.cs b/CleanCode/src/CleanCode/Features/ExtensionMethods.cs index d12ef11..06bfdc5 100644 --- a/CleanCode/src/CleanCode/Features/ExtensionMethods.cs +++ b/CleanCode/src/CleanCode/Features/ExtensionMethods.cs @@ -1,6 +1,10 @@ using System; +using System.Collections.Generic; using System.Linq; +using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.ExtensionsAPI.Resolve; +using JetBrains.ReSharper.Psi.Resolve; using JetBrains.ReSharper.Psi.Tree; namespace CleanCode.Features @@ -21,9 +25,9 @@ public static int CountChildren(this ITreeNode node) where T : ITreeNode return count; } - + public static int GetChildrenDepth(this ITreeNode node) - { + { var childrenDepth = 0; var children = node.Children(); foreach (var block in children) @@ -34,11 +38,44 @@ public static int GetChildrenDepth(this ITreeNode node) if (IsNodeThatIncreasesDepth(node)) { - return childrenDepth + 1; + return childrenDepth + 1; } return childrenDepth; } + public static IEnumerable GetFlattenedHierarchyOfType(this ITreeNode root) where T : class, ITreeNode + { + var list = new List(); + + var rootAsType = root as T; + if (rootAsType != null) + { + list.Add(rootAsType); + } + + list.AddRange(root.GetChildrenRecursive()); + + return list; + } + + public static IEnumerable GetChildrenRecursive(this ITreeNode node) where T : ITreeNode + { + var nodeChildren = node.Children().ToList(); + + var list = new List(); + + var childOfType = nodeChildren.OfType(); + list.AddRange(childOfType); + + foreach (var childNode in nodeChildren) + { + var childrenOfType = GetChildrenRecursive(childNode); + list.AddRange(childrenOfType); + } + + return list; + } + private static bool IsNodeThatIncreasesDepth(ITreeNode node) { if (node is IIfStatement) @@ -60,5 +97,62 @@ private static bool IsNodeThatIncreasesDepth(ITreeNode node) return false; } + + public static IType TryGetClosedReturnTypeFrom(ITreeNode treeNode) + { + IType type = null; + var reference = treeNode as IReferenceExpression; + if (reference != null) + { + type = TryGetClosedReturnTypeFromReference(reference.Reference); + } + + var invocationExpression = treeNode as IInvocationExpression; + if (invocationExpression != null) + { + type = TryGetClosedReturnTypeFromReference(invocationExpression.Reference); + } + + return type; + } + + public static IReferenceExpression TryGetFirstReferenceExpression(ITreeNode currentNode) + { + var childNodes = currentNode.Children(); + var firstChildNode = childNodes.FirstOrDefault(); + + if (firstChildNode == null) + return null; + + return firstChildNode as IReferenceExpression ?? + TryGetFirstReferenceExpression(firstChildNode); + } + + private static IType TryGetClosedReturnTypeFromReference(IReference reference) + { + var resolveResultWithInfo = GetResolveResult(reference); + + var declaredElement = resolveResultWithInfo.DeclaredElement; + var parametersOwner = declaredElement as IParametersOwner; + + if (parametersOwner != null) + { + var returnType = parametersOwner.ReturnType; + return returnType.IsOpenType ? GetClosedType(resolveResultWithInfo, returnType) : returnType; + } + + return null; + } + + private static IType GetClosedType(ResolveResultWithInfo resolveResultWithInfo, IType returnType) + { + var closedType = resolveResultWithInfo.Result.Substitution.Apply(returnType); + return closedType; + } + + public static ResolveResultWithInfo GetResolveResult(this IReference reference) + { + return reference.Resolve(); + } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs new file mode 100644 index 0000000..cb97d11 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs @@ -0,0 +1,89 @@ +using System.Linq; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.Tree; +using System.Collections.Generic; +using System.Diagnostics; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.Util; + +namespace CleanCode.Features.FlagArguments +{ + [ElementProblemAnalyzer(typeof(IMethodDeclaration), + HighlightingTypes = new [] + { + typeof(FlagArgumentsHighlighting) + })] + public class FlagArgumentsCheck : ElementProblemAnalyzer + { + protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) + { + var parameterDeclarations = element.ParameterDeclarations; + + foreach (var parameterDeclaration in parameterDeclarations) + { + if (IsFlagArgument(parameterDeclaration, element.Body)) + { + AddHighlighting(consumer, parameterDeclaration); + } + } + } + + private static bool IsFlagArgument(ITypeOwnerDeclaration typeOwnerDeclaration, ITreeNode node) + { + if (IsOfTypeThatCanBeUsedAsFlag(typeOwnerDeclaration)) + { + var references = GetReferencesTo(typeOwnerDeclaration.DeclaredElement, node); + return references.Any(); + } + + return false; + } + + private static bool IsOfTypeThatCanBeUsedAsFlag(ITypeOwnerDeclaration arg) + { + var type = arg.Type; + return type.IsBool() || type.IsEnumType(); + } + + private static IEnumerable GetReferencesTo(IDeclaredElement declaredElement, ITreeNode body) + { + var ifStatements = body.GetChildrenRecursive(); + + var allConditions = ifStatements.Select(statement => statement.Condition); + + var allReferencesInConditions = + allConditions.SelectMany(expression => expression.GetFlattenedHierarchyOfType()); + + return GetReferencesToArgument(allReferencesInConditions, declaredElement); + } + + private static IEnumerable GetReferencesToArgument(IEnumerable allReferencesInConditions, IDeclaredElement declaredElementInArgument) + { + return allReferencesInConditions.Where(reference => IsReferenceToArgument(reference, declaredElementInArgument)); + } + + private static bool IsReferenceToArgument(IReferenceExpression referenceExpression, IDeclaredElement toFind) + { + if (referenceExpression == null) + { + return false; + } + + var resolveResultWithInfo = referenceExpression.Reference.GetResolveResult(); + var declaredElement = resolveResultWithInfo.DeclaredElement; + + Debug.Assert(declaredElement != null, "declaredElement != null"); + + return declaredElement.ShortName == toFind.ShortName; + } + + private static void AddHighlighting(IHighlightingConsumer consumer, ICSharpParameterDeclaration parameterDeclaration) + { + var documentRange = parameterDeclaration.GetDocumentRange(); + var highlighting = new FlagArgumentsHighlighting(documentRange); + consumer.AddHighlighting(highlighting); + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs new file mode 100644 index 0000000..084b01c --- /dev/null +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs @@ -0,0 +1,30 @@ +using CleanCode; +using CleanCode.Features.FlagArguments; +using CleanCode.Resources; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly: RegisterConfigurableSeverity(FlagArgumentsHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Flag argument", "An argument that is used as a flag.", + Severity.WARNING)] + +namespace CleanCode.Features.FlagArguments +{ + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class FlagArgumentsHighlighting : IHighlighting + { + internal const string SeverityID = "FlagArgument"; + private readonly DocumentRange documentRange; + + public FlagArgumentsHighlighting(DocumentRange documentRange) + { + this.documentRange = documentRange; + } + + public DocumentRange CalculateRange() => documentRange; + public string ToolTip => Warnings.FlagArgument; + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs new file mode 100644 index 0000000..7c0c23e --- /dev/null +++ b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using CleanCode.Resources; +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.Tree; + +namespace CleanCode.Features.HollowNames +{ + [ElementProblemAnalyzer(typeof(IClassDeclaration), + HighlightingTypes = new [] + { + typeof(HollowTypeNameHighlighting) + })] + public class HollowNamesCheck : ElementProblemAnalyzer + { + protected override void Run(IClassDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) + { + var suffixes = GetSuffixes(data.SettingsStore); + + var match = GetFirstMatchOrDefault(element.DeclaredName, suffixes); + if (match != null) + AddHighlighting(match, consumer, element); + } + + private IEnumerable GetSuffixes(IContextBoundSettingsStore dataSettingsStore) + { + var suffixes = dataSettingsStore.GetValue((CleanCodeSettings s) => s.MeaninglessClassNameSuffixes); + return suffixes.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); + } + + private static string GetFirstMatchOrDefault(string declaredName, IEnumerable suffixes) + { + return suffixes.FirstOrDefault(declaredName.EndsWith); + } + + private void AddHighlighting(string bannedSuffix, IHighlightingConsumer consumer, IClassDeclaration typeExpression) + { + var identifier = typeExpression.NameIdentifier; + var documentRange = identifier.GetDocumentRange(); + var highlighting = new HollowTypeNameHighlighting(string.Format(Warnings.HollowTypeName, bannedSuffix), documentRange); + consumer.AddHighlighting(highlighting); + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs b/CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs new file mode 100644 index 0000000..d3750b2 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs @@ -0,0 +1,30 @@ +using CleanCode; +using CleanCode.Features.HollowNames; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly: RegisterConfigurableSeverity(HollowTypeNameHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Hollow type name", "This type has a name that doesn't express its intent.", + Severity.SUGGESTION)] + +namespace CleanCode.Features.HollowNames +{ + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class HollowTypeNameHighlighting : IHighlighting + { + internal const string SeverityID = "HollowTypeName"; + private readonly DocumentRange documentRange; + + public HollowTypeNameHighlighting(string toolTip, DocumentRange documentRange) + { + ToolTip = toolTip; + this.documentRange = documentRange; + } + + public DocumentRange CalculateRange() => documentRange; + public string ToolTip { get; } + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs deleted file mode 100644 index a00aa83..0000000 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs +++ /dev/null @@ -1,73 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Features.MethodNameNotMeaningful; -using JetBrains.ReSharper.Daemon; -using JetBrains.ReSharper.Psi.CSharp; - -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Method Name Not Meaningful", - "This method name is to short to be meaningful. Please, choose a better name that describes its intent.", - Severity.WARNING, false)] - -namespace CleanCode.Features.MethodNameNotMeaningful -{ - /// - /// The highlighting that warns about high complexity - /// - [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting - { - internal const string SeverityID = "MethodNamesNotMeaningful"; - private readonly string tooltip; - - public Highlighting(string toolTip) - { - tooltip = toolTip; - } - - public string ToolTip - { - get { return tooltip; } - } - - public string ErrorStripeToolTip - { - get { return tooltip; } - } - - public int NavigationOffsetPatch - { - get { return 0; } - } - - public bool IsValid() - { - return true; - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs deleted file mode 100644 index 2ec7de2..0000000 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs +++ /dev/null @@ -1,45 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; - -namespace CleanCode.Features.MethodNameNotMeaningful -{ - [SolutionComponent] - public class InvalidateOnMinimumMethodNameLenghtChange - { - public InvalidateOnMinimumMethodNameLenghtChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) - { - var minMethodNameLenght = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimumEnabled); - settingsStore.AdviseChange(lifetime, minMethodNameLenght, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs new file mode 100644 index 0000000..a267f79 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs @@ -0,0 +1,33 @@ +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.Tree; + +namespace CleanCode.Features.MethodNameNotMeaningful +{ + [ElementProblemAnalyzer(typeof(IMethodDeclaration), HighlightingTypes = new [] + { + typeof(MethodNameNotMeaningfulHighlighting) + })] + public class MethodNameNotMeaningfulCheck : ElementProblemAnalyzer + { + protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) + { + if (element.NameIdentifier == null) + return; + + var minimumMethodNameLength = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MinimumMeaningfulMethodNameLength); + + var name = element.NameIdentifier.GetText(); + var methodNameLength = name.Length; + if (methodNameLength < minimumMethodNameLength) + { + var documentRange = element.GetNameDocumentRange(); + var highlighting = new MethodNameNotMeaningfulHighlighting(documentRange); + consumer.AddHighlighting(highlighting); + } + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs new file mode 100644 index 0000000..20c297b --- /dev/null +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs @@ -0,0 +1,31 @@ +using CleanCode; +using CleanCode.Features.MethodNameNotMeaningful; +using CleanCode.Resources; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly: RegisterConfigurableSeverity(MethodNameNotMeaningfulHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Method name not meaningful", + "This method name is too short to be meaningful.", + Severity.WARNING)] + +namespace CleanCode.Features.MethodNameNotMeaningful +{ + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class MethodNameNotMeaningfulHighlighting : IHighlighting + { + internal const string SeverityID = "MethodNameNotMeaningful"; + private readonly DocumentRange documentRange; + + public MethodNameNotMeaningfulHighlighting(DocumentRange documentRange) + { + this.documentRange = documentRange; + } + + public DocumentRange CalculateRange() => documentRange; + public string ToolTip => Warnings.MethodNameNotMeaningful; + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNamesNotMeaningfulCheck.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNamesNotMeaningfulCheck.cs deleted file mode 100644 index c190ab4..0000000 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNamesNotMeaningfulCheck.cs +++ /dev/null @@ -1,46 +0,0 @@ -using CleanCode.Resources; -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; -using JetBrains.ReSharper.Psi.CSharp.Tree; -using JetBrains.ReSharper.Psi.Tree; - -namespace CleanCode.Features.MethodNameNotMeaningful -{ - public class MethodNamesNotMeaningfulCheck : SimpleCheck - { - public MethodNamesNotMeaningfulCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override void ExecuteCore(IMethodDeclaration methodDeclaration, IHighlightingConsumer consumer) - { - var minimumMethodNameLenght = Threshold; - - if (methodDeclaration.NameIdentifier == null) - { - return; - } - - var name = methodDeclaration.NameIdentifier.GetText(); - var methodNameLenght = name.Length; - if (methodNameLenght < minimumMethodNameLenght) - { - var highlighting = new Highlighting(Warnings.MethodNameNotMeaningful); - consumer.AddHighlighting(highlighting, methodDeclaration.GetNameDocumentRange()); - } - } - - protected override int Threshold - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimumEnabled); } - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs deleted file mode 100644 index 684ed63..0000000 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs +++ /dev/null @@ -1,69 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Features.MethodTooLong; -using JetBrains.ReSharper.Daemon; -using JetBrains.ReSharper.Psi.CSharp; - -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Method Too Long", "The method is bigger than it should be.", - Severity.SUGGESTION, false)] - -namespace CleanCode.Features.MethodTooLong -{ - [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting - { - internal const string SeverityID = "MethodTooLong"; - private readonly string tooltip; - - public Highlighting(string toolTip) - { - tooltip = toolTip; - } - - public string ToolTip - { - get { return tooltip; } - } - - public string ErrorStripeToolTip - { - get { return tooltip; } - } - - public int NavigationOffsetPatch - { - get { return 0; } - } - - public bool IsValid() - { - return true; - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs deleted file mode 100644 index cd48f0c..0000000 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs +++ /dev/null @@ -1,45 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; - -namespace CleanCode.Features.MethodTooLong -{ - [SolutionComponent] - public class InvalidateOnMaximumLinesChange - { - public InvalidateOnMaximumLinesChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) - { - var maxLines = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.MethodTooLongMaximum); - settingsStore.AdviseChange(lifetime, maxLines, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs index 479df4a..de17804 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs @@ -1,40 +1,36 @@ -using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; namespace CleanCode.Features.MethodTooLong { - public class MethodTooLongCheck : SimpleCheck + [ElementProblemAnalyzer(typeof(IMethodDeclaration), HighlightingTypes = new [] { - public MethodTooLongCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override void ExecuteCore(IMethodDeclaration element, IHighlightingConsumer consumer) + typeof(MethodTooLongHighlighting) + })] + public class MethodTooLongCheck : ElementProblemAnalyzer + { + protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var maxLength = Threshold; + var maxStatements = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumMethodStatements); + var maxDeclarations = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumDeclarationsInMethod); var statementCount = element.CountChildren(); - if (statementCount > maxLength) + if (statementCount <= maxStatements) { - var highlighting = new Highlighting(Warnings.Warning_MethodTooLong); - consumer.AddHighlighting(highlighting, element.GetNameDocumentRange()); + // Only look in the method body for declarations, otherwise we see + // parameters + type parameters. We can ignore arrow expressions, as + // they must be a single expression and won't have declarations + var declarationCount = element.Body?.CountChildren() ?? 0; + if (declarationCount <= maxDeclarations) + return; } - } - protected override int Threshold - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongEnabled); } + var highlighting = new MethodTooLongHighlighting(element.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting); } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs new file mode 100644 index 0000000..8645138 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs @@ -0,0 +1,30 @@ +using CleanCode; +using CleanCode.Features.MethodTooLong; +using CleanCode.Resources; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly: RegisterConfigurableSeverity(MethodTooLongHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Method too long", "The method is bigger than it should be.", + Severity.SUGGESTION)] + +namespace CleanCode.Features.MethodTooLong +{ + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class MethodTooLongHighlighting : IHighlighting + { + internal const string SeverityID = "MethodTooLong"; + private readonly DocumentRange documentRange; + + public MethodTooLongHighlighting(DocumentRange documentRange) + { + this.documentRange = documentRange; + } + + public DocumentRange CalculateRange() => documentRange; + public string ToolTip => Warnings.MethodTooLong; + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/SimpleCheck.cs b/CleanCode/src/CleanCode/Features/SimpleCheck.cs deleted file mode 100644 index 372431c..0000000 --- a/CleanCode/src/CleanCode/Features/SimpleCheck.cs +++ /dev/null @@ -1,36 +0,0 @@ -using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.Stages; -using JetBrains.ReSharper.Psi.Tree; - -namespace CleanCode.Features -{ - public abstract class SimpleCheck where TElement : ITreeNode - { - private readonly IContextBoundSettingsStore settingsStore; - - protected SimpleCheck(IContextBoundSettingsStore settingsStore) - { - this.settingsStore = settingsStore; - } - - public void ExecuteIfEnabled(TElement methodDeclaration, IHighlightingConsumer context) - { - if (!IsEnabled) - { - return; - } - ExecuteCore(methodDeclaration, context); - } - - protected abstract void ExecuteCore(TElement element, IHighlightingConsumer consumer); - - protected abstract TThreshold Threshold { get; } - - protected abstract bool IsEnabled { get; } - - protected IContextBoundSettingsStore SettingsStore - { - get { return settingsStore; } - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/Highlighting.cs b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/Highlighting.cs deleted file mode 100644 index bbcd38c..0000000 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/Highlighting.cs +++ /dev/null @@ -1,69 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Features.TooManyChainedReferences; -using JetBrains.ReSharper.Daemon; -using JetBrains.ReSharper.Psi.CSharp; - -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Chained References", "There are too many chained references.", - Severity.WARNING, false)] - -namespace CleanCode.Features.TooManyChainedReferences -{ - [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting - { - internal const string SeverityID = "MaximumChainedReferences"; - private readonly string tooltip; - - public Highlighting(string toolTip) - { - tooltip = toolTip; - } - - public string ToolTip - { - get { return tooltip; } - } - - public string ErrorStripeToolTip - { - get { return tooltip; } - } - - public int NavigationOffsetPatch - { - get { return 0; } - } - - public bool IsValid() - { - return true; - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/InvalidateOnMaximumChainedCalls.cs b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/InvalidateOnMaximumChainedCalls.cs deleted file mode 100644 index d79ca32..0000000 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/InvalidateOnMaximumChainedCalls.cs +++ /dev/null @@ -1,45 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; - -namespace CleanCode.Features.TooManyChainedReferences -{ - [SolutionComponent] - public class InvalidateOnMaximumChainedCalls - { - public InvalidateOnMaximumChainedCalls(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) - { - var maxDepth = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); - settingsStore.AdviseChange(lifetime, maxDepth, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs deleted file mode 100644 index d8f1813..0000000 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs +++ /dev/null @@ -1,54 +0,0 @@ -using CleanCode.Resources; -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; -using JetBrains.ReSharper.Psi.CSharp.Tree; -using JetBrains.ReSharper.Psi.Tree; - -namespace CleanCode.Features.TooManyChainedReferences -{ - public class TooManyChainedReferencesCheck : SimpleCheck - { - public TooManyChainedReferencesCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override void ExecuteCore(IReferenceExpression methodDeclaration, IHighlightingConsumer consumer) - { - if (methodDeclaration != null && !ParentIsReference(methodDeclaration)) - { - ProcessReference(methodDeclaration, consumer); - } - } - - private void ProcessReference(IReferenceExpression reference, IHighlightingConsumer consumer) - { - var length = reference.CountChildren(); - var maximumChainedReferences = Threshold; - - if (length > maximumChainedReferences) - { - var highlighting = new Highlighting(Warnings.ChainedReferences); - consumer.AddHighlighting(highlighting, reference.GetDocumentRange()); - } - } - - private static bool ParentIsReference(ITreeNode element) - { - var reference = element.Parent as IReferenceExpression; - return reference != null; - } - - protected override int Threshold - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesEnabled); } - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs deleted file mode 100644 index e7976f0..0000000 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs +++ /dev/null @@ -1,69 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Features.TooManyDependencies; -using JetBrains.ReSharper.Daemon; -using JetBrains.ReSharper.Psi.CSharp; - -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Too Many Dependencies", "Too many dependencies passed into constructor.", - Severity.WARNING, false)] - -namespace CleanCode.Features.TooManyDependencies -{ - [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting - { - internal const string SeverityID = "TooManyDependencies"; - private readonly string tooltip; - - public Highlighting(string toolTip) - { - tooltip = toolTip; - } - - public string ToolTip - { - get { return tooltip; } - } - - public string ErrorStripeToolTip - { - get { return tooltip; } - } - - public int NavigationOffsetPatch - { - get { return 0; } - } - - public bool IsValid() - { - return true; - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs deleted file mode 100644 index 1a2cde0..0000000 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs +++ /dev/null @@ -1,45 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; - -namespace CleanCode.Features.TooManyDependencies -{ - [SolutionComponent] - public class InvalidateOnMaximumDependenciesChange - { - public InvalidateOnMaximumDependenciesChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) - { - var maxParams = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyDependenciesMaximum); - settingsStore.AdviseChange(lifetime, maxParams, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs index 98abf73..06f8ad5 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs @@ -1,47 +1,34 @@ using System.Linq; -using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; using JetBrains.ReSharper.Psi.Util; namespace CleanCode.Features.TooManyDependencies { - public class TooManyDependenciesCheck : SimpleCheck + [ElementProblemAnalyzer(typeof(IConstructorDeclaration), HighlightingTypes = new [] { - public TooManyDependenciesCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override void ExecuteCore(IConstructorDeclaration constructorDeclaration, IHighlightingConsumer consumer) + typeof(TooManyDependenciesHighlighting) + })] + public class TooManyDependenciesCheck : ElementProblemAnalyzer + { + protected override void Run(IConstructorDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var maxDependencies = Threshold; + var maxDependencies = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumConstructorDependencies); - var depedencies = constructorDeclaration.ParameterDeclarations.Select( + var dependencies = element.ParameterDeclarations.Select( declaration => declaration.DeclaredElement != null && declaration.DeclaredElement.Type.IsInterfaceType()); - var dependenciesCount = depedencies.Count(); - + var dependenciesCount = dependencies.Count(); if (dependenciesCount > maxDependencies) { - var highlighting = new Highlighting(Warnings.TooManyDependencies); - consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); + var highlighting = new TooManyDependenciesHighlighting(element.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting); } } - - protected override int Threshold - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximumEnabled); } - } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs new file mode 100644 index 0000000..909760c --- /dev/null +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs @@ -0,0 +1,30 @@ +using CleanCode; +using CleanCode.Features.TooManyDependencies; +using CleanCode.Resources; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly: RegisterConfigurableSeverity(TooManyDependenciesHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Too many dependencies", "Too many dependencies passed into constructor.", + Severity.WARNING)] + +namespace CleanCode.Features.TooManyDependencies +{ + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class TooManyDependenciesHighlighting : IHighlighting + { + internal const string SeverityID = "TooManyDependencies"; + private readonly DocumentRange documentRange; + + public TooManyDependenciesHighlighting(DocumentRange documentRange) + { + this.documentRange = documentRange; + } + + public DocumentRange CalculateRange() => documentRange; + public string ToolTip => Warnings.TooManyDependencies; + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs deleted file mode 100644 index f4369d8..0000000 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs +++ /dev/null @@ -1,69 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Features.TooManyMethodArguments; -using JetBrains.ReSharper.Daemon; -using JetBrains.ReSharper.Psi.CSharp; - -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Too Many Arguments", "Too many arguments passed to a method.", - Severity.WARNING, false)] - -namespace CleanCode.Features.TooManyMethodArguments -{ - [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting - { - internal const string SeverityID = "TooManyArguments"; - private readonly string tooltip; - - public Highlighting(string toolTip) - { - tooltip = toolTip; - } - - public string ToolTip - { - get { return tooltip; } - } - - public string ErrorStripeToolTip - { - get { return tooltip; } - } - - public int NavigationOffsetPatch - { - get { return 0; } - } - - public bool IsValid() - { - return true; - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs deleted file mode 100644 index be1fa24..0000000 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs +++ /dev/null @@ -1,46 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; - -namespace CleanCode.Features.TooManyMethodArguments -{ - [SolutionComponent] - public class InvalidateOnMaximumMethodArgumentsChange - { - public InvalidateOnMaximumMethodArgumentsChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) - { - var maxArguments = - settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); - settingsStore.AdviseChange(lifetime, maxArguments, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs new file mode 100644 index 0000000..1465da9 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs @@ -0,0 +1,30 @@ +using CleanCode; +using CleanCode.Features.TooManyMethodArguments; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly: RegisterConfigurableSeverity(TooManyArgumentsHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Too many arguments", "Too many arguments passed to a method.", + Severity.WARNING)] + +namespace CleanCode.Features.TooManyMethodArguments +{ + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class TooManyArgumentsHighlighting : IHighlighting + { + internal const string SeverityID = "TooManyArguments"; + private readonly DocumentRange documentRange; + + public TooManyArgumentsHighlighting(string toolTip, DocumentRange documentRange) + { + ToolTip = toolTip; + this.documentRange = documentRange; + } + + public DocumentRange CalculateRange() => documentRange; + public string ToolTip { get; } + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs index aa3955c..5928b94 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs @@ -1,40 +1,30 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; namespace CleanCode.Features.TooManyMethodArguments { - public class TooManyMethodArgumentsCheck : SimpleCheck + [ElementProblemAnalyzer(typeof(IMethodDeclaration), HighlightingTypes = new [] { - public TooManyMethodArgumentsCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override void ExecuteCore(IMethodDeclaration methodDeclaration, IHighlightingConsumer consumer) + typeof(TooManyArgumentsHighlighting) + })] + public class TooManyMethodArgumentsCheck : ElementProblemAnalyzer + { + protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var parameterDeclarations = methodDeclaration.ParameterDeclarations; - var maxParameters = Threshold; + var maxParameters = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumMethodParameters); + var parameterDeclarations = element.ParameterDeclarations; if (parameterDeclarations.Count > maxParameters) { - var highlighting = new Highlighting(Warnings.TooManyMethodArguments); - consumer.AddHighlighting(highlighting, methodDeclaration.GetNameDocumentRange()); + var highlighting = new TooManyArgumentsHighlighting(Warnings.TooManyMethodArguments, + element.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting); } } - - protected override int Threshold - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsEnabled); } - } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/InvalidateOnSettingsChange.cs b/CleanCode/src/CleanCode/InvalidateOnSettingsChange.cs new file mode 100644 index 0000000..4005a1a --- /dev/null +++ b/CleanCode/src/CleanCode/InvalidateOnSettingsChange.cs @@ -0,0 +1,18 @@ +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.DataFlow; +using JetBrains.ProjectModel; +using JetBrains.ReSharper.Feature.Services.Daemon; + +namespace CleanCode +{ + [SolutionComponent] + public class InvalidateOnSettingsChange + { + public InvalidateOnSettingsChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) + { + var settingsKey = settingsStore.Schema.GetKey(); + settingsStore.AdviseChange(lifetime, settingsKey, daemon.Invalidate); + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs index d64cedc..e95eb3d 100644 --- a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs +++ b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs @@ -1,46 +1,16 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion -using System.Reflection; +using System.Reflection; using System.Runtime.InteropServices; -using JetBrains.Application.PluginSupport; [assembly: AssemblyTitle("ReSharper Clean Code Plugin")] [assembly: AssemblyCompany("Hadi Hariri")] [assembly: AssemblyProduct("ReSharper Clean Code Plugin")] [assembly: AssemblyDescription("Automates some of the concepts in Uncle Bob's Clean Code book")] -[assembly: AssemblyCopyright("Copyright ® 2014 Hadi Hariri and Contributors")] +[assembly: AssemblyCopyright("Copyright ® 2016 Hadi Hariri and Contributors")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] [assembly: Guid("97927FF9-8C9C-4DC5-A309-29C23F41DA47")] -[assembly: AssemblyVersion("4.0.0.*")] - -[assembly: PluginTitle("Clean Code")] -[assembly: PluginDescription("Automates some of the concepts in Uncle Bob's Clean Code book")] -[assembly: PluginVendor("Hadi Hariri and Contributors")] +[assembly: AssemblyVersion("5.1.0.0")] +[assembly: AssemblyFileVersion("5.1.0.0")] diff --git a/CleanCode/src/CleanCode/Resources/Icons82/Settings/CleanCode.png b/CleanCode/src/CleanCode/Resources/Icons/Settings/CleanCode.png similarity index 100% rename from CleanCode/src/CleanCode/Resources/Icons82/Settings/CleanCode.png rename to CleanCode/src/CleanCode/Resources/Icons/Settings/CleanCode.png diff --git a/CleanCode/src/CleanCode/Resources/Icons82/Settings/ThemedIcons.Settings.Generated.Xaml b/CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xaml similarity index 100% rename from CleanCode/src/CleanCode/Resources/Icons82/Settings/ThemedIcons.Settings.Generated.Xaml rename to CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xaml diff --git a/CleanCode/src/CleanCode/Resources/Icons82/Settings/ThemedIcons.Settings.Generated.cs b/CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.cs similarity index 67% rename from CleanCode/src/CleanCode/Resources/Icons82/Settings/ThemedIcons.Settings.Generated.cs rename to CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.cs index 5a41f8f..ae6a859 100644 --- a/CleanCode/src/CleanCode/Resources/Icons82/Settings/ThemedIcons.Settings.Generated.cs +++ b/CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.cs @@ -1,19 +1,18 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34003 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ -[assembly: global::System.Windows.Markup.XmlnsDefinitionAttribute("urn:shemas-jetbrains-com:ui-application-icons-settings", "CleanCode.Resources.Icons82")] -[assembly: global::JetBrains.UI.Icons.CompiledIcons.CompiledIconsPackAttribute(IconPackResourceIdentification="CleanCode.8.2;component/Resources/Icons82/Settings/ThemedIcons.Settings.Generat" + - "ed.Xaml", IconNames=new string[] { +[assembly: global::System.Windows.Markup.XmlnsDefinitionAttribute("urn:shemas-jetbrains-com:ui-application-icons-settings", "CleanCode.Resources.Icons")] +[assembly: global::JetBrains.UI.Icons.CompiledIcons.CompiledIconsPackAttribute(IconPackResourceIdentification="CleanCode;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xaml", IconNames=new string[] { "CleanCode"})] -namespace CleanCode.Resources.Icons82 +namespace CleanCode.Resources.Icons { @@ -28,17 +27,17 @@ namespace CleanCode.Resources.Icons82 /// It has two primary goals: load the icons of this assembly to be registered with so that they were WPF-accessible and theme-sensitive; and emit early-bound accessors for referencing icons in codebehind in a compile-time-validated manner. ///

XAML

/// For performance reasons, the icons are not individually exposed with application resources. There is a custom markup extension to bind an image source in markup. - /// To use an icon from XAML, set an property to the markup extension, which takes an icon identifier class (nested in class) as a parameter. + /// To use an icon from XAML, set an property to the markup extension, which takes an icon identifier class (nested in class) as a parameter. /// Example: /// <Image Source="{icons:ThemedIcon myres:SettingsThemedIcons+CleanCode}" /> ///

Attributes

/// Sometimes you have to reference an icon from a type attriute when you're defining objects in code. Typical examples are Options pages and Tool Windows. - /// To avoid the use of string IDs which are not validated very well, we've emitted identifier classes to be used with typeof() expression, one per each icon. Use the attribute overload which takes a for an image, and choose your icon class from nested classes in the class. + /// To avoid the use of string IDs which are not validated very well, we've emitted identifier classes to be used with typeof() expression, one per each icon. Use the attribute overload which takes a for an image, and choose your icon class from nested classes in the class. /// Example: /// [Item(Name="Sample", Icon=typeof(SettingsThemedIcons.CleanCode))] ///

CodeBehind

/// In codebehind, we have two distinct tasks: (a) specify some icon in the APIs and (b) render icon images onscreen. - /// On the APIs stage you should only manipulate icon identifier objects (of type , statically defined in in Id fields). Icon identifier classes (nested in ) should be turned into icon identifier objects as early as possible. Rendering is about getting an to assign to WPF, or to use with GDI+ / Windows Forms. + /// On the APIs stage you should only manipulate icon identifier objects (of type , statically defined in in Id fields). Icon identifier classes (nested in ) should be turned into icon identifier objects as early as possible. Rendering is about getting an to assign to WPF, or to use with GDI+ / Windows Forms. /// You should turn an identifier object into a rendered image as late as possible. The identifier is static and lightweight and does not depend on the current theme, while the image is themed and has to be loaded or generated/rasterized. You need an instance to get the image out of an icon identifier object. Once you got the image, you should take care to change it with theme changes — either by using a live image property, or by listening to the theme change event. See and its extensions for the related facilities. /// Example: /// // Getting IconId identifier object to use with APIs @@ -58,13 +57,13 @@ public sealed class SettingsThemedIcons /// /// /// Autogenerated identifier class for the CleanCode Themed Icon. - /// Identifier classes should be used in attributes, XAML, or generic parameters. Where an value is expected, use the identifier object in the field of the identifier class. + /// Identifier classes should be used in attributes, XAML, or generic parameters. Where an value is expected, use the identifier object in the field of the identifier class. /// /// /// - /// For details on Themed Icons and their use, see Remarks on class. + /// For details on Themed Icons and their use, see Remarks on class. /// - /// + /// /// /// <Image Source="{icons:ThemedIcon myres:SettingsThemedIcons+CleanCode}" /> <!-- XAML --> /// @@ -77,21 +76,20 @@ public sealed class SettingsThemedIcons /// /// themediconmanager.GetIcon<SettingsThemedIcons.CleanCode>() // Icon image for rendering /// - [global::JetBrains.UI.Icons.CompiledIcons.CompiledIconClassAttribute("CleanCode.8.2;component/Resources/Icons82/Settings/ThemedIcons.Settings.Generat" + - "ed.Xaml", 0, "CleanCode")] + [global::JetBrains.UI.Icons.CompiledIcons.CompiledIconClassAttribute("CleanCode;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xaml", 0, "CleanCode")] public sealed class CleanCode : global::JetBrains.UI.Icons.CompiledIcons.CompiledIconClass { /// /// /// Autogenerated identifier object for the CleanCode Themed Icon. - /// Identifier objects should be used where an value is expected. In attributes, XAML, or generic parameters use the containing identifier class. + /// Identifier objects should be used where an value is expected. In attributes, XAML, or generic parameters use the containing identifier class. /// /// /// - /// For details on Themed Icons and their use, see Remarks on class. + /// For details on Themed Icons and their use, see Remarks on class. /// - /// + /// /// /// <Image Source="{icons:ThemedIcon myres:SettingsThemedIcons+CleanCode}" /> <!-- XAML --> /// @@ -104,8 +102,275 @@ public sealed class CleanCode : global::JetBrains.UI.Icons.CompiledIcons.Compile /// /// themediconmanager.GetIcon<SettingsThemedIcons.CleanCode>() // Icon image for rendering /// - public static global::JetBrains.UI.Icons.IconId Id = new global::JetBrains.UI.Icons.CompiledIcons.CompiledIconId("CleanCode.8.2;component/Resources/Icons82/Settings/ThemedIcons.Settings.Generat" + - "ed.Xaml", 0, "CleanCode"); + public static global::JetBrains.UI.Icons.IconId Id = new global::JetBrains.UI.Icons.CompiledIcons.CompiledIconId("CleanCode;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xaml", 0, "CleanCode"); } } } + + +public sealed class RenderedIcons_ByPackResourceNameHash_E1185BB5DC155E8A999AD43CA329D4ED +{ + + public static byte[] CleanCode____png__x1 = new byte[] { + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 16, + 0, + 0, + 0, + 16, + 8, + 6, + 0, + 0, + 0, + 31, + 243, + 255, + 97, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 19, + 73, + 68, + 65, + 84, + 56, + 79, + 99, + 24, + 5, + 163, + 96, + 20, + 140, + 2, + 48, + 96, + 96, + 0, + 0, + 4, + 16, + 0, + 1, + 167, + 68, + 124, + 99, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130}; + + public static byte[] CleanCode____png__x2 = new byte[] { + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 32, + 0, + 0, + 0, + 32, + 8, + 6, + 0, + 0, + 0, + 115, + 122, + 122, + 244, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 26, + 73, + 68, + 65, + 84, + 88, + 71, + 237, + 193, + 1, + 1, + 0, + 0, + 0, + 130, + 32, + 255, + 175, + 110, + 72, + 64, + 0, + 0, + 0, + 192, + 185, + 26, + 16, + 32, + 0, + 1, + 157, + 120, + 73, + 67, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130}; +} diff --git a/CleanCode/src/CleanCode/Resources/LocalizedStrings.cs b/CleanCode/src/CleanCode/Resources/LocalizedStrings.cs deleted file mode 100644 index 6355e42..0000000 --- a/CleanCode/src/CleanCode/Resources/LocalizedStrings.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace CleanCode.Resources -{ - public class LocalizedStrings - { - - public LocalizedStrings() - { - Warnings = new Warnings(); - Settings = new Settings(); - } - public Warnings Warnings { get; set; } - public Settings Settings { get; set; } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs index 1a4dba5..38efef2 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -61,146 +61,101 @@ internal Settings() { } /// - /// Looks up a localized string similar to Maximum Methods Per Class. + /// Looks up a localized string similar to Maximum declarations per method. /// - public static string ClassTooBig { + public static string DeclarationsMaximum { get { - return ResourceManager.GetString("ClassTooBig", resourceCulture); + return ResourceManager.GetString("DeclarationsMaximum", resourceCulture); } } /// - /// Looks up a localized string similar to Maximum Methods Per Class Check. + /// Looks up a localized string similar to Maximum chained references. /// - public static string ClassTooBigCheck { + public static string MaximumChainedReferences { get { - return ResourceManager.GetString("ClassTooBigCheck", resourceCulture); + return ResourceManager.GetString("MaximumChainedReferences", resourceCulture); } } /// - /// Looks up a localized string similar to Maximum level of nesting. + /// Looks up a localized string similar to Maximum interface dependencies for a constructor. /// - public static string ExcessiveDepth { + public static string MaximumConstructorDependencies { get { - return ResourceManager.GetString("ExcessiveDepth", resourceCulture); + return ResourceManager.GetString("MaximumConstructorDependencies", resourceCulture); } } /// - /// Looks up a localized string similar to Excessive Depth Of Nesting Check. + /// Looks up a localized string similar to Maximum expressions inside a condition. /// - public static string ExcessiveDepthCheck { + public static string MaximumExpressionsInsideACondition { get { - return ResourceManager.GetString("ExcessiveDepthCheck", resourceCulture); + return ResourceManager.GetString("MaximumExpressionsInsideACondition", resourceCulture); } } /// - /// Looks up a localized string similar to Maximum Chained References. + /// Looks up a localized string similar to Maximum level of nesting in a method. /// - public static string MaxChainedReferences { + public static string MaximumLevelOfNestingInAMethod { get { - return ResourceManager.GetString("MaxChainedReferences", resourceCulture); + return ResourceManager.GetString("MaximumLevelOfNestingInAMethod", resourceCulture); } } /// - /// Looks up a localized string similar to Maximum Chained References Check. + /// Looks up a localized string similar to Maximum method declaration parameters. /// - public static string MaxChainedReferencesCheck { + public static string MaximumMethodDeclarationParameters { get { - return ResourceManager.GetString("MaxChainedReferencesCheck", resourceCulture); + return ResourceManager.GetString("MaximumMethodDeclarationParameters", resourceCulture); } } /// - /// Looks up a localized string similar to Maximum Dependencies Check. + /// Looks up a localized string similar to Maximum methods per class. /// - public static string MaximumDependenciesCheck { + public static string MaximumMethodsPerClass { get { - return ResourceManager.GetString("MaximumDependenciesCheck", resourceCulture); + return ResourceManager.GetString("MaximumMethodsPerClass", resourceCulture); } } /// - /// Looks up a localized string similar to Maximum Method Arguments Check. - /// - public static string MaximumMethodArgumentsCheck { - get { - return ResourceManager.GetString("MaximumMethodArgumentsCheck", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Maximum Statements Per Method Check. - /// - public static string MethodTooLongCheck { - get { - return ResourceManager.GetString("MethodTooLongCheck", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Minimum lenght for the name of methods. - /// - public static string MinimumMethodNameLength { - get { - return ResourceManager.GetString("MinimumMethodNameLength", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Minimum Method Name Lenght. - /// - public static string MinimumMethodNameLengthCheck { - get { - return ResourceManager.GetString("MinimumMethodNameLengthCheck", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The options below help enforce certain practices that can be considered to leading to cleaner and more maintainable code.. - /// - public static string Options_Header { - get { - return ResourceManager.GetString("Options_Header", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Note: All references to Clean Code, including but not limited to the Clean Code icon are used with permission of Robert C. Martin (a.k.a. UncleBob). + /// Looks up a localized string similar to Maximum statements per method. /// - public static string Options_SubHeader { + public static string MaximumStatementsPerMethod { get { - return ResourceManager.GetString("Options_SubHeader", resourceCulture); + return ResourceManager.GetString("MaximumStatementsPerMethod", resourceCulture); } } /// - /// Looks up a localized string similar to Maximum statements per method. + /// Looks up a localized string similar to List of meaningless suffixes. /// - public static string TooLongLinesPerMethod { + public static string MeaninglessNameSuffixes { get { - return ResourceManager.GetString("TooLongLinesPerMethod", resourceCulture); + return ResourceManager.GetString("MeaninglessNameSuffixes", resourceCulture); } } /// - /// Looks up a localized string similar to Set maximum dependencies to. + /// Looks up a localized string similar to Separate items with commas. /// - public static string TooManyDependencies { + public static string MeaninglessNameSuffixesTooltip { get { - return ResourceManager.GetString("TooManyDependencies", resourceCulture); + return ResourceManager.GetString("MeaninglessNameSuffixesTooltip", resourceCulture); } } /// - /// Looks up a localized string similar to Set maximum arguments to. + /// Looks up a localized string similar to Minimum method name length. /// - public static string TooManyMethodArguments { + public static string MinimumMethodNameLength { get { - return ResourceManager.GetString("TooManyMethodArguments", resourceCulture); + return ResourceManager.GetString("MinimumMethodNameLength", resourceCulture); } } } diff --git a/CleanCode/src/CleanCode/Resources/Settings.resx b/CleanCode/src/CleanCode/Resources/Settings.resx index 64db111..7297fcd 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.resx +++ b/CleanCode/src/CleanCode/Resources/Settings.resx @@ -117,52 +117,37 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - The options below help enforce certain practices that can be considered to leading to cleaner and more maintainable code. - - - Maximum Dependencies Check - - - Maximum Method Arguments Check - - - Maximum Statements Per Method Check - - + Maximum statements per method - - Set maximum dependencies to + + Maximum interface dependencies for a constructor - - Set maximum arguments to + + Maximum method declaration parameters - - Note: All references to Clean Code, including but not limited to the Clean Code icon are used with permission of Robert C. Martin (a.k.a. UncleBob) + + Maximum level of nesting in a method - - Maximum level of nesting + + Maximum methods per class - - Excessive Depth Of Nesting Check + + Maximum chained references - - Maximum Methods Per Class - - - Maximum Methods Per Class Check + + Minimum method name length - - Maximum Chained References + + Maximum expressions inside a condition - - Maximum Chained References Check + + List of meaningless suffixes - - Minimum length for the name of methods + + Separate items with commas - - Minimum Method Name Length + + Maximum declarations per method - + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs index 040065e..40f8864 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -61,7 +61,7 @@ internal Warnings() { } /// - /// Looks up a localized string similar to Too many chained references.. + /// Looks up a localized string similar to Too many chained references. This might be violating the Law of Demeter.. /// public static string ChainedReferences { get { @@ -70,7 +70,7 @@ public static string ChainedReferences { } /// - /// Looks up a localized string similar to Class contains too many methods.. + /// Looks up a localized string similar to Class contains too many methods. This might be violating the Single Responsibility Principle.. /// public static string ClassTooBig { get { @@ -87,6 +87,33 @@ public static string ExcessiveDepth { } } + /// + /// Looks up a localized string similar to This expression is too complex.. + /// + public static string ExpressionTooComplex { + get { + return ResourceManager.GetString("ExpressionTooComplex", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This argument is used as a flag in the method. This might be violating the Single Responsibility Principle.. + /// + public static string FlagArgument { + get { + return ResourceManager.GetString("FlagArgument", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The usage of the suffix '{0}' is discouraged because it's too generic. Choose a meaningful name instead to clarify its intent and responsibilities.. + /// + public static string HollowTypeName { + get { + return ResourceManager.GetString("HollowTypeName", resourceCulture); + } + } + /// /// Looks up a localized string similar to The name of this method is too short to be meaningful.. /// @@ -97,29 +124,29 @@ public static string MethodNameNotMeaningful { } /// - /// Looks up a localized string similar to There are too many interfaces being passed in to this constructor. You might be violating SRP.. + /// Looks up a localized string similar to This method is too long, indicating that it has too much responsibility.. /// - public static string TooManyDependencies { + public static string MethodTooLong { get { - return ResourceManager.GetString("TooManyDependencies", resourceCulture); + return ResourceManager.GetString("MethodTooLong", resourceCulture); } } /// - /// Looks up a localized string similar to This method requires too many arguments.. + /// Looks up a localized string similar to There are too many interfaces being passed in to this constructor. It might be violating the Single Responsibility Principle.. /// - public static string TooManyMethodArguments { + public static string TooManyDependencies { get { - return ResourceManager.GetString("TooManyMethodArguments", resourceCulture); + return ResourceManager.GetString("TooManyDependencies", resourceCulture); } } /// - /// Looks up a localized string similar to This method contains too many statements.. + /// Looks up a localized string similar to This method requires too many arguments.. /// - public static string Warning_MethodTooLong { + public static string TooManyMethodArguments { get { - return ResourceManager.GetString("Warning_MethodTooLong", resourceCulture); + return ResourceManager.GetString("TooManyMethodArguments", resourceCulture); } } } diff --git a/CleanCode/src/CleanCode/Resources/Warnings.resx b/CleanCode/src/CleanCode/Resources/Warnings.resx index f51cc2a..f00f274 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.resx +++ b/CleanCode/src/CleanCode/Resources/Warnings.resx @@ -118,24 +118,33 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - There are too many interfaces being passed in to this constructor. You might be violating SRP. + There are too many interfaces being passed in to this constructor. It might be violating the Single Responsibility Principle. This method requires too many arguments. - - This method contains too many statements. + + This method is too long, indicating that it has too much responsibility. Excessive depth of nested code blocks. - Class contains too many methods. + Class contains too many methods. This might be violating the Single Responsibility Principle. - Too many chained references. + Too many chained references. This might be violating the Law of Demeter. The name of this method is too short to be meaningful. + + This argument is used as a flag in the method. This might be violating the Single Responsibility Principle. + + + This expression is too complex. + + + The usage of the suffix '{0}' is discouraged because it's too generic. Choose a meaningful name instead to clarify its intent and responsibilities. + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/CleanCodeOptionsPage.cs b/CleanCode/src/CleanCode/Settings/CleanCodeOptionsPage.cs new file mode 100644 index 0000000..05f81fb --- /dev/null +++ b/CleanCode/src/CleanCode/Settings/CleanCodeOptionsPage.cs @@ -0,0 +1,64 @@ +using System.Drawing; +using CleanCode.Resources.Icons; +using JetBrains.DataFlow; +using JetBrains.ReSharper.Feature.Services.Daemon.OptionPages; +using JetBrains.UI.Options; +using JetBrains.UI.Options.OptionsDialog2.SimpleOptions; +using JetBrains.UI.RichText; + +namespace CleanCode.Settings +{ + [OptionsPage(PageId, "Clean Code", typeof(SettingsThemedIcons.CleanCode), ParentId = CodeInspectionPage.PID)] + public class CleanCodeOptionsPage : CustomSimpleOptionsPage + { + private const string PageId = "CleanCode"; + + public CleanCodeOptionsPage(Lifetime lifetime, OptionsSettingsSmartContext optionsSettingsSmartContext) + : base(lifetime, optionsSettingsSmartContext) + { + AddHeader("Single Responsibility"); + AddText("A class should only have a single responsibility. Do not do too much in a class or method."); + AddIntOption((CleanCodeSettings s) => s.MaximumMethodsInClass, + Resources.Settings.MaximumMethodsPerClass, + "Too many method declarations in a class is an indicator that the class is doing too much."); + AddIntOption((CleanCodeSettings s) => s.MaximumMethodParameters, + Resources.Settings.MaximumMethodDeclarationParameters, + "Too many parameters in a method declaration is an indicator of having more than one responsibility"); + AddIntOption((CleanCodeSettings s) => s.MaximumMethodStatements, Resources.Settings.MaximumStatementsPerMethod, + "Long methods are indicator of having more than one responsibility."); + AddIntOption((CleanCodeSettings s) => s.MaximumDeclarationsInMethod, + Resources.Settings.DeclarationsMaximum, + "Too many variables are an indicator of having more than one responsibility."); + AddIntOption((CleanCodeSettings s) => s.MaximumIndentationDepth, + Resources.Settings.MaximumLevelOfNestingInAMethod, + "Too much nesting in a method is an indicator of having more than one responsibility."); + + AddHeader("Coupling"); + AddText("Avoid excessive coupling beween classes."); + AddIntOption((CleanCodeSettings s) => s.MaximumConstructorDependencies, + Resources.Settings.MaximumConstructorDependencies); + AddIntOption((CleanCodeSettings s) => s.MaximumChainedReferences, + Resources.Settings.MaximumChainedReferences, + "Avoid breaking the Law of Demeter."); + + AddHeader("Legibility"); + AddText("Names should be meaningful."); + AddIntOption((CleanCodeSettings s) => s.MinimumMeaningfulMethodNameLength, + Resources.Settings.MinimumMethodNameLength); + AddStringOption((CleanCodeSettings s) => s.MeaninglessClassNameSuffixes, + Resources.Settings.MeaninglessNameSuffixes, + Resources.Settings.MeaninglessNameSuffixesTooltip); + + AddHeader("Complexity"); + AddText("Reduce complexity in individual statements."); + AddIntOption((CleanCodeSettings s) => s.MaximumExpressionsInCondition, + Resources.Settings.MaximumExpressionsInsideACondition); + + AddRichText( + new RichText( + "Note: All references to Clean Code, including but not limited to the Clean Code icon are used with permission of Robert C. Martin (a.k.a. UncleBob)", + new TextStyle(FontStyle.Italic))); + FinishPage(); + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs index 7cad180..4cb5a24 100644 --- a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs +++ b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs @@ -1,73 +1,39 @@ -#region License - -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. - -#endregion - using JetBrains.Application.Settings; -using JetBrains.ReSharper.Settings; +using JetBrains.ReSharper.Resources.Settings; namespace CleanCode.Settings { [SettingsKey(typeof(CodeInspectionSettings), "CleanCode")] public class CleanCodeSettings { - [SettingsEntry(3, "TooManyDependenciesMaximum")] - public readonly int TooManyDependenciesMaximum; - [SettingsEntry(true, "TooManyDependenciesMaximumEnabled")] - public readonly bool TooManyDependenciesMaximumEnabled; + [SettingsEntry(3, "MaximumConstructorDependencies")] + public readonly int MaximumConstructorDependencies; + + [SettingsEntry(3, "MaximumMethodParameters")] + public readonly int MaximumMethodParameters; + + [SettingsEntry(15, "MaximumMethodStatements")] + public readonly int MaximumMethodStatements; + + [SettingsEntry(6, "MaximumDeclarationsInMethod")] + public readonly int MaximumDeclarationsInMethod; - [SettingsEntry(3, "TooManyMethodArgumentsMaximum")] - public readonly int TooManyMethodArgumentsMaximum; - [SettingsEntry(true, "TooManyMethodArgumentsEnabled")] - public readonly bool TooManyMethodArgumentsEnabled; + [SettingsEntry(3, "MaximumIndentationDepth")] + public int MaximumIndentationDepth { get; set; } - [SettingsEntry(true, "MethodTooLongEnabled")] - public readonly bool MethodTooLongEnabled; - [SettingsEntry(15, "MethodTooLongMaximum")] - public readonly int MethodTooLongMaximum; + [SettingsEntry(20, "MaximumMethodsInClass")] + public int MaximumMethodsInClass { get; set; } - [SettingsEntry(3, "ExcessiveIndentationMaximum")] - public int ExcessiveIndentationMaximum { get; set; } - [SettingsEntry(true, "ExcessiveIndentationEnabled")] - public bool ExcessiveIndentationEnabled { get; set; } + [SettingsEntry(2, "MaximumChainedReferences")] + public int MaximumChainedReferences { get; set; } - [SettingsEntry(true, "ClassTooBigEnabled")] - public bool ClassTooBigEnabled { get; set; } - [SettingsEntry(20, "ClassTooBigMaximum")] - public int ClassTooBigMaximum { get; set; } + [SettingsEntry(4, "MinimumMeaningfulMethodNameLength")] + public int MinimumMeaningfulMethodNameLength { get; set; } - [SettingsEntry(true, "TooManyChainedReferencesEnabled")] - public bool TooManyChainedReferencesEnabled { get; set; } - [SettingsEntry(2, "TooManyChainedReferencesMaximum")] - public int TooManyChainedReferencesMaximum { get; set; } + [SettingsEntry("Handler,Manager,Processor,Controller,Helper", "MeaninglessClassNameSuffixes")] + public string MeaninglessClassNameSuffixes { get; set; } - [SettingsEntry(true, "MethodNameNotMeaningfulMinimumEnabled")] - public bool MethodNameNotMeaningfulMinimumEnabled { get; set; } - [SettingsEntry(4, "MethodNameNotMeaningfulMinimum")] - public int MethodNameNotMeaningfulMinimum { get; set; } + [SettingsEntry(1, "MaximumExpressionsInCondition")] + public int MaximumExpressionsInCondition { get; set; } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml deleted file mode 100644 index c37f2d4..0000000 --- a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml.cs b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml.cs deleted file mode 100644 index e85c611..0000000 --- a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml.cs +++ /dev/null @@ -1,46 +0,0 @@ -using CleanCode.Resources.Icons82; -using JetBrains.DataFlow; -using JetBrains.ReSharper.Features.Environment.Options.Inspections; -using JetBrains.UI.Application; -using JetBrains.UI.CrossFramework; -using JetBrains.UI.Options; - -namespace CleanCode.Settings -{ - [OptionsPage(PageId, "Clean Code", typeof(SettingsThemedIcons.CleanCode), ParentId = CodeInspectionPage.PID)] - public partial class OptionsPage : IOptionsPage - { - const string PageId = "CleanCode"; - - public OptionsPage(Lifetime lifetime, IUIApplication environment, OptionsSettingsSmartContext settings) - : this() - { - DataContext = new OptionsViewModel(settings); - } - - private OptionsPage() - { - InitializeComponent(); - } - - public bool OnOk() - { - return true; - } - - public bool ValidatePage() - { - return true; - } - - public EitherControl Control - { - get - { - return this; - } - } - - public string Id { get; private set; } - } -} diff --git a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs deleted file mode 100644 index 02047af..0000000 --- a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System.Collections; -using System.ComponentModel; -using System.Runtime.CompilerServices; -using JetBrains.Annotations; -using JetBrains.Application.Settings; - -namespace CleanCode.Settings -{ - public abstract class ViewModel : INotifyPropertyChanged - { - public virtual event PropertyChangedEventHandler PropertyChanged; - - [NotifyPropertyChangedInvocator] - protected void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - var handler = PropertyChanged; - if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); - } - } - - public sealed class OptionsViewModel : ViewModel - { - public OptionsViewModel(IContextBoundSettingsStore settings) - { - Options = GetViewModels(settings); - } - - public ArrayList Options { get; set; } - - // TODO: We need to refactor this method. - // ReSharper disable once MethodTooLong - private static ArrayList GetViewModels(IContextBoundSettingsStore settings) - { - var viewModels = new ArrayList(); - - var methodTooLong = new SingleCheckSettingViewModel( - settings, - codeSettings => codeSettings.MethodTooLongEnabled, - codeSettings => codeSettings.MethodTooLongMaximum) - { - IsEnabledDescription = Resources.Settings.MethodTooLongCheck, - ValueDescription = Resources.Settings.TooLongLinesPerMethod, - }; - viewModels.Add(methodTooLong); - - var tooManyDependencies = new SingleCheckSettingViewModel( - settings, - e => e.TooManyDependenciesMaximumEnabled, - e => e.TooManyDependenciesMaximum) - { - IsEnabledDescription = Resources.Settings.MaximumDependenciesCheck, - ValueDescription = Resources.Settings.TooManyDependencies, - }; - viewModels.Add(tooManyDependencies); - - var tooManyMethodArguments = new SingleCheckSettingViewModel( - settings, - e => e.TooManyMethodArgumentsEnabled, - e => e.TooManyMethodArgumentsMaximum) - { - IsEnabledDescription = Resources.Settings.MaximumMethodArgumentsCheck, - ValueDescription = Resources.Settings.TooManyMethodArguments, - }; - - viewModels.Add(tooManyMethodArguments); - - var enabledMaxDepth = new SingleCheckSettingViewModel( - settings, - e => e.TooManyDependenciesMaximumEnabled, - e => e.ExcessiveIndentationMaximum) - { - IsEnabledDescription = Resources.Settings.ExcessiveDepthCheck, - ValueDescription = Resources.Settings.ExcessiveDepth, - }; - - viewModels.Add(enabledMaxDepth); - - var enableClassTooBig = new SingleCheckSettingViewModel( - settings, - e => e.ClassTooBigEnabled, - e => e.ClassTooBigMaximum) - { - IsEnabledDescription = Resources.Settings.ClassTooBigCheck, - ValueDescription = Resources.Settings.ClassTooBig, - }; - - viewModels.Add(enableClassTooBig); - - var enableChainedReferences = new SingleCheckSettingViewModel( - settings, - e => e.TooManyChainedReferencesEnabled, - e => e.TooManyChainedReferencesMaximum) - { - IsEnabledDescription = Resources.Settings.MaxChainedReferencesCheck, - ValueDescription = Resources.Settings.MaxChainedReferences, - }; - - viewModels.Add(enableChainedReferences); - - var enableMinimumMethodNameLength = new SingleCheckSettingViewModel( - settings, - e => e.MethodNameNotMeaningfulMinimumEnabled, - e => e.MethodNameNotMeaningfulMinimum) - { - IsEnabledDescription = Resources.Settings.MinimumMethodNameLengthCheck, - ValueDescription = Resources.Settings.MinimumMethodNameLength, - }; - - viewModels.Add(enableMinimumMethodNameLength); - - return viewModels; - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/SingleCheckSettingViewModel.cs b/CleanCode/src/CleanCode/Settings/SingleCheckSettingViewModel.cs deleted file mode 100644 index ca28c92..0000000 --- a/CleanCode/src/CleanCode/Settings/SingleCheckSettingViewModel.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Linq.Expressions; -using JetBrains.Application.Settings; - -namespace CleanCode.Settings -{ - public class SingleCheckSettingViewModel : ViewModel - { - private readonly Expression> isEnabledSelector; - private readonly Expression> valueSelector; - private readonly IContextBoundSettingsStore settings; - - public SingleCheckSettingViewModel(IContextBoundSettingsStore settings, Expression> isEnabledSelector, Expression> valueSelector) - { - this.settings = settings; - this.isEnabledSelector = isEnabledSelector; - this.valueSelector = valueSelector; - } - - public bool IsEnabled - { - get { return settings.GetValue(isEnabledSelector); } - set - { - settings.SetValue(isEnabledSelector, value); - OnPropertyChanged(); - } - } - - public TType Value - { - get { return settings.GetValue(valueSelector); } - set - { - settings.SetValue(valueSelector, value); - OnPropertyChanged(); - } - } - - public string IsEnabledDescription { get; set; } - public string ValueDescription { get; set; } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/ZoneMarker.cs b/CleanCode/src/CleanCode/ZoneMarker.cs new file mode 100644 index 0000000..4bafde4 --- /dev/null +++ b/CleanCode/src/CleanCode/ZoneMarker.cs @@ -0,0 +1,9 @@ +using JetBrains.Application.BuildScript.Application.Zones; + +namespace CleanCode +{ + [ZoneMarker] + public class ZoneMarker + { + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/packages.config b/CleanCode/src/CleanCode/packages.config index 6301eb7..bf0f33c 100644 --- a/CleanCode/src/CleanCode/packages.config +++ b/CleanCode/src/CleanCode/packages.config @@ -1,4 +1,59 @@  - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CleanCode/src/NuGet.Packager/.gitignore b/CleanCode/src/NuGet.Packager/.gitignore deleted file mode 100644 index 2357e0d..0000000 --- a/CleanCode/src/NuGet.Packager/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.nupkg -lib/*.dll diff --git a/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj b/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj deleted file mode 100644 index 68dabb3..0000000 --- a/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj +++ /dev/null @@ -1,93 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {0451BAEF-DF2E-4B98-8644-94EE9415E389} - Library - Properties - NuGet.Packager - NuGet.Packager - v4.0 - - - 512 - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - AnyCPU - bin\Debug\ - - - AnyCPU - bin\Release\ - - - - - - - - - - - - - Designer - - - - - - - - - - - - - {5f96119c-2646-4298-ad40-30209e7e7bb2} - CleanCode.8.2 - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CleanCode/src/NuGet.Packager/NuGet.config b/CleanCode/src/NuGet.Packager/NuGet.config deleted file mode 100644 index a7336c5..0000000 --- a/CleanCode/src/NuGet.Packager/NuGet.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/CleanCode/src/NuGet.Packager/NuGet.exe b/CleanCode/src/NuGet.Packager/NuGet.exe deleted file mode 100644 index c41a0d0..0000000 Binary files a/CleanCode/src/NuGet.Packager/NuGet.exe and /dev/null differ diff --git a/CleanCode/src/NuGet.Packager/NuGetPackage.ps1 b/CleanCode/src/NuGet.Packager/NuGetPackage.ps1 deleted file mode 100644 index fbcff49..0000000 --- a/CleanCode/src/NuGet.Packager/NuGetPackage.ps1 +++ /dev/null @@ -1,313 +0,0 @@ -Param ( - [switch]$Publish -) - -$ErrorActionPreference = "Stop" -$global:ExitCode = 1 - -function Write-Log { - - #region Parameters - - [cmdletbinding()] - Param( - [Parameter(ValueFromPipeline=$true)] - [array] $Messages, - - [Parameter()] [ValidateSet("Error", "Warn", "Info")] - [string] $Level = "Info", - - [Parameter()] - [Switch] $NoConsoleOut = $false, - - [Parameter()] - [String] $ForegroundColor = 'White', - - [Parameter()] [ValidateRange(1,30)] - [Int16] $Indent = 0, - - [Parameter()] - [IO.FileInfo] $Path = ".\NuGet.log", - - [Parameter()] - [Switch] $Clobber, - - [Parameter()] - [String] $EventLogName, - - [Parameter()] - [String] $EventSource, - - [Parameter()] - [Int32] $EventID = 1 - - ) - - #endregion - - Begin {} - - Process { - - $ErrorActionPreference = "Continue" - - if ($Messages.Length -gt 0) { - try { - foreach($m in $Messages) { - if ($NoConsoleOut -eq $false) { - switch ($Level) { - 'Error' { - Write-Error $m -ErrorAction SilentlyContinue - Write-Host ('{0}{1}' -f (" " * $Indent), $m) -ForegroundColor Red - } - 'Warn' { - Write-Warning $m - } - 'Info' { - Write-Host ('{0}{1}' -f (" " * $Indent), $m) -ForegroundColor $ForegroundColor - } - } - } - - if ($m.Trim().Length -gt 0) { - $msg = '{0}{1} [{2}] : {3}' -f (" " * $Indent), (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $Level.ToUpper(), $m - - if ($Clobber) { - $msg | Out-File -FilePath $Path -Force - } else { - $msg | Out-File -FilePath $Path -Append - } - } - - if ($EventLogName) { - - if (-not $EventSource) { - $EventSource = ([IO.FileInfo] $MyInvocation.ScriptName).Name - } - - if(-not [Diagnostics.EventLog]::SourceExists($EventSource)) { - [Diagnostics.EventLog]::CreateEventSource($EventSource, $EventLogName) - } - - $log = New-Object System.Diagnostics.EventLog - $log.set_log($EventLogName) - $log.set_source($EventSource) - - switch ($Level) { - "Error" { $log.WriteEntry($Message, 'Error', $EventID) } - "Warn" { $log.WriteEntry($Message, 'Warning', $EventID) } - "Info" { $log.WriteEntry($Message, 'Information', $EventID) } - } - } - } - } - catch { - throw "Failed to create log entry in: '$Path'. The error was: '$_'." - } - } - } - - End {} - - <# - .SYNOPSIS - Writes logging information to screen and log file simultaneously. - - .DESCRIPTION - Writes logging information to screen and log file simultaneously. Supports multiple log levels. - - .PARAMETER Messages - The messages to be logged. - - .PARAMETER Level - The type of message to be logged. - - .PARAMETER NoConsoleOut - Specifies to not display the message to the console. - - .PARAMETER ConsoleForeground - Specifies what color the text should be be displayed on the console. Ignored when switch 'NoConsoleOut' is specified. - - .PARAMETER Indent - The number of spaces to indent the line in the log file. - - .PARAMETER Path - The log file path. - - .PARAMETER Clobber - Existing log file is deleted when this is specified. - - .PARAMETER EventLogName - The name of the system event log, e.g. 'Application'. - - .PARAMETER EventSource - The name to appear as the source attribute for the system event log entry. This is ignored unless 'EventLogName' is specified. - - .PARAMETER EventID - The ID to appear as the event ID attribute for the system event log entry. This is ignored unless 'EventLogName' is specified. - - .EXAMPLE - PS C:\> Write-Log -Message "It's all good!" -Path C:\MyLog.log -Clobber -EventLogName 'Application' - - .EXAMPLE - PS C:\> Write-Log -Message "Oops, not so good!" -Level Error -EventID 3 -Indent 2 -EventLogName 'Application' -EventSource "My Script" - - .INPUTS - System.String - - .OUTPUTS - No output. - - .NOTES - Revision History: - 2011-03-10 : Andy Arismendi - Created. - #> -} - -function Create-Process() { - param([string] $fileName, [string] $arguments) - - $pinfo = New-Object System.Diagnostics.ProcessStartInfo - $pinfo.RedirectStandardError = $true - $pinfo.RedirectStandardOutput = $true - $pinfo.UseShellExecute = $false - $pinfo.FileName = $fileName - $pinfo.Arguments = $arguments - - $p = New-Object System.Diagnostics.Process - $p.StartInfo = $pinfo - - return $p -} - -function HandlePublishError { - param([string] $ErrorMessage) - - # Run NuGet Setup - $encodedMessage = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($ErrorMessage)) - $setupTask = Start-Process PowerShell.exe "-ExecutionPolicy Unrestricted -File .\NuGetSetup.ps1 -Url $url -Base64EncodedMessage $encodedMessage" -Wait -PassThru - - #Write-Log ("NuGet Setup Task Exit Code: " + $setupTask.ExitCode) - - if ($setupTask.ExitCode -eq 0) { - # Try to push package again - $publishTask = Create-Process .\NuGet.exe ("push " + $_.Name + " -Source " + $url) - $publishTask.Start() | Out-Null - $publishTask.WaitForExit() - - $output = ($publishTask.StandardOutput.ReadToEnd() -Split '[\r\n]') |? {$_} - $error = (($publishTask.StandardError.ReadToEnd() -Split '[\r\n]') |? {$_}) - Write-Log $output - Write-Log $error Error - - if ($publishTask.ExitCode -eq 0) { - $global:ExitCode = 0 - } - } - elseif ($setupTask.ExitCode -eq 2) { - $global:ExitCode = 2 - } - else { - $global:ExitCode = 0 - } -} - -function Publish { - - Write-Log " " - Write-Log "Publishing package..." -ForegroundColor Green - - # Get nuget config - [xml]$nugetConfig = Get-Content .\NuGet.Config - - $nugetConfig.configuration.packageSources.add | ForEach-Object { - $url = $_.value - - Write-Log "Repository Url: $url" - Write-Log " " - - Get-ChildItem *.nupkg | Where-Object { $_.Name.EndsWith(".symbols.nupkg") -eq $false } | ForEach-Object { - - # Try to push package - $task = Create-Process .\NuGet.exe ("push " + $_.Name + " -Source " + $url) - $task.Start() | Out-Null - $task.WaitForExit() - - $output = ($task.StandardOutput.ReadToEnd() -Split '[\r\n]') |? { $_ } - $error = ($task.StandardError.ReadToEnd() -Split '[\r\n]') |? { $_ } - Write-Log $output - Write-Log $error Error - - if ($task.ExitCode -gt 0) { - HandlePublishError -ErrorMessage $error - #Write-Log ("HandlePublishError() Exit Code: " + $global:ExitCode) - } - else { - $global:ExitCode = 0 - } - } - } -} - -Write-Log " " -Write-Log "NuGet Packager 2.0.3" -ForegroundColor Yellow - -# Make sure the nuget executable is writable -Set-ItemProperty NuGet.exe -Name IsReadOnly -Value $false - -# Make sure the nupkg files are writeable and create backup -if (Test-Path *.nupkg) { - Set-ItemProperty *.nupkg -Name IsReadOnly -Value $false - - Write-Log " " - Write-Log "Creating backup..." -ForegroundColor Green - - Get-ChildItem *.nupkg | ForEach-Object { - Move-Item $_.Name ($_.Name + ".bak") -Force - Write-Log ("Renamed " + $_.Name + " to " + $_.Name + ".bak") - } -} - -Write-Log " " -Write-Log "Updating NuGet..." -ForegroundColor Green -Write-Log (Invoke-Command {.\NuGet.exe update -Self} -ErrorAction Stop) - -Write-Log " " -Write-Log "Creating package..." -ForegroundColor Green - -# Create symbols package if any .pdb files are located in the lib folder -If ((Get-ChildItem *.pdb -Path .\lib -Recurse).Count -gt 0) { - $packageTask = Create-Process .\NuGet.exe ("pack Package.nuspec -Symbol -Verbosity Detailed") - $packageTask.Start() | Out-Null - $packageTask.WaitForExit() - - $output = ($packageTask.StandardOutput.ReadToEnd() -Split '[\r\n]') |? {$_} - $error = (($packageTask.StandardError.ReadToEnd() -Split '[\r\n]') |? {$_}) - Write-Log $output - Write-Log $error Error - - $global:ExitCode = $packageTask.ExitCode -} -Else { - $packageTask = Create-Process .\NuGet.exe ("pack Package.nuspec -Verbosity Detailed") - $packageTask.Start() | Out-Null - $packageTask.WaitForExit() - - $output = ($packageTask.StandardOutput.ReadToEnd() -Split '[\r\n]') |? {$_} - $error = (($packageTask.StandardError.ReadToEnd() -Split '[\r\n]') |? {$_}) - Write-Log $output - Write-Log $error Error - - $global:ExitCode = $packageTask.ExitCode -} - -# Check if package should be published -if ($Publish -and $global:ExitCode -eq 0) { - Publish -} - -Write-Log " " -Write-Log "Exit Code: $global:ExitCode" -ForegroundColor Gray - -$host.SetShouldExit($global:ExitCode) -Exit $global:ExitCode \ No newline at end of file diff --git a/CleanCode/src/NuGet.Packager/NuGetSetup.ps1 b/CleanCode/src/NuGet.Packager/NuGetSetup.ps1 deleted file mode 100644 index bd9aa5e..0000000 --- a/CleanCode/src/NuGet.Packager/NuGetSetup.ps1 +++ /dev/null @@ -1,208 +0,0 @@ -Param ( - [string]$Url, - [string]$Base64EncodedMessage -) - -$ErrorActionPreference = "Stop" -$ExitCode = 1 - -function Write-Log { - - #region Parameters - - [cmdletbinding()] - Param( - [Parameter(ValueFromPipeline=$true)] - [array] $Messages, - - [Parameter()] [ValidateSet("Error", "Warn", "Info")] - [string] $Level = "Info", - - [Parameter()] - [Switch] $NoConsoleOut = $false, - - [Parameter()] - [String] $ForegroundColor = 'White', - - [Parameter()] [ValidateRange(1,30)] - [Int16] $Indent = 0, - - [Parameter()] - [IO.FileInfo] $Path = ".\NuGet.log", - - [Parameter()] - [Switch] $Clobber, - - [Parameter()] - [String] $EventLogName, - - [Parameter()] - [String] $EventSource, - - [Parameter()] - [Int32] $EventID = 1 - - ) - - #endregion - - Begin {} - - Process { - - $ErrorActionPreference = "Continue" - - if ($Messages.Length -gt 0) { - try { - foreach($m in $Messages) { - if ($NoConsoleOut -eq $false) { - switch ($Level) { - 'Error' { - Write-Error $m -ErrorAction SilentlyContinue - Write-Host ('{0}{1}' -f (" " * $Indent), $m) -ForegroundColor Red - } - 'Warn' { - Write-Warning $m - } - 'Info' { - Write-Host ('{0}{1}' -f (" " * $Indent), $m) -ForegroundColor $ForegroundColor - } - } - } - - if ($m.Trim().Length -gt 0) { - $msg = '{0}{1} [{2}] : {3}' -f (" " * $Indent), (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $Level.ToUpper(), $m - - if ($Clobber) { - $msg | Out-File -FilePath $Path -Force - } else { - $msg | Out-File -FilePath $Path -Append - } - } - - if ($EventLogName) { - - if (-not $EventSource) { - $EventSource = ([IO.FileInfo] $MyInvocation.ScriptName).Name - } - - if(-not [Diagnostics.EventLog]::SourceExists($EventSource)) { - [Diagnostics.EventLog]::CreateEventSource($EventSource, $EventLogName) - } - - $log = New-Object System.Diagnostics.EventLog - $log.set_log($EventLogName) - $log.set_source($EventSource) - - switch ($Level) { - "Error" { $log.WriteEntry($Message, 'Error', $EventID) } - "Warn" { $log.WriteEntry($Message, 'Warning', $EventID) } - "Info" { $log.WriteEntry($Message, 'Information', $EventID) } - } - } - } - } - catch { - throw "Failed to create log entry in: '$Path'. The error was: '$_'." - } - } - } - - End {} - - <# - .SYNOPSIS - Writes logging information to screen and log file simultaneously. - - .DESCRIPTION - Writes logging information to screen and log file simultaneously. Supports multiple log levels. - - .PARAMETER Messages - The messages to be logged. - - .PARAMETER Level - The type of message to be logged. - - .PARAMETER NoConsoleOut - Specifies to not display the message to the console. - - .PARAMETER ConsoleForeground - Specifies what color the text should be be displayed on the console. Ignored when switch 'NoConsoleOut' is specified. - - .PARAMETER Indent - The number of spaces to indent the line in the log file. - - .PARAMETER Path - The log file path. - - .PARAMETER Clobber - Existing log file is deleted when this is specified. - - .PARAMETER EventLogName - The name of the system event log, e.g. 'Application'. - - .PARAMETER EventSource - The name to appear as the source attribute for the system event log entry. This is ignored unless 'EventLogName' is specified. - - .PARAMETER EventID - The ID to appear as the event ID attribute for the system event log entry. This is ignored unless 'EventLogName' is specified. - - .EXAMPLE - PS C:\> Write-Log -Message "It's all good!" -Path C:\MyLog.log -Clobber -EventLogName 'Application' - - .EXAMPLE - PS C:\> Write-Log -Message "Oops, not so good!" -Level Error -EventID 3 -Indent 2 -EventLogName 'Application' -EventSource "My Script" - - .INPUTS - System.String - - .OUTPUTS - No output. - - .NOTES - Revision History: - 2011-03-10 : Andy Arismendi - Created. - #> -} - -$choices = [System.Management.Automation.Host.ChoiceDescription[]]( - (New-Object System.Management.Automation.Host.ChoiceDescription "&Add API Key","Add an API Key for this URL"), - (New-Object System.Management.Automation.Host.ChoiceDescription "&Skip","Skip pushing to this URL")) - - Write-Output "" - Write-Log "Invalid API key for this repository URL, or there is a version conflict" Warn - - If ($Base64EncodedMessage) { - Write-Warning ([System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Base64EncodedMessage))) - } - - $firstAnswer = $Host.UI.PromptForChoice(("Would you like to try adding an API key for " + $Url + "?"), "", $choices, (1)) - - if ($firstAnswer -eq 0) { - $fields = new-object "System.Collections.ObjectModel.Collection``1[[System.Management.Automation.Host.FieldDescription]]" - - $f = New-Object System.Management.Automation.Host.FieldDescription "API Key for $Url" - $f.SetParameterType( [System.Security.SecureString] ) - $f.HelpMessage = "Please enter API Key for $Url" - $f.Label = "&API Key for $Url" - - $fields.Add($f) - - $results = $Host.UI.Prompt( "Add API Key", "", $fields ) - - $pass = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($results["API Key for $Url"])) - - # Add API Key to config file - Write-Log (.\NuGet.exe setApiKey $pass -Source $Url) - - if ($LASTEXITCODE -le 0) { - $ExitCode = 0 - } - } - else { - Write-Log "Skipping..." - $ExitCode = 2 - } - -$host.SetShouldExit($ExitCode) -Exit $ExitCode \ No newline at end of file diff --git a/CleanCode/src/NuGet.Packager/Properties/AssemblyInfo.cs b/CleanCode/src/NuGet.Packager/Properties/AssemblyInfo.cs deleted file mode 100644 index cb3fd4b..0000000 --- a/CleanCode/src/NuGet.Packager/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("NuGet.Packager")] -[assembly: AssemblyDescription("Project template made by EyeCatch (http://www.eyecatch.no/)")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("NuGet.Packager")] -[assembly: AssemblyCopyright("Copyright © 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("5b586874-8d3e-4137-9ba8-e982413416d5")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CleanCode/src/NuGet.Packager/tools/init.ps1 b/CleanCode/src/NuGet.Packager/tools/init.ps1 deleted file mode 100644 index a686abf..0000000 --- a/CleanCode/src/NuGet.Packager/tools/init.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -# Runs the first time a package is installed in a solution, and every time the solution is opened. - -param($installPath, $toolsPath, $package, $project) - -# $installPath is the path to the folder where the package is installed. -# $toolsPath is the path to the tools directory in the folder where the package is installed. -# $package is a reference to the package object. -# $project is null in init.ps1 diff --git a/CleanCode/src/NuGet.Packager/tools/install.ps1 b/CleanCode/src/NuGet.Packager/tools/install.ps1 deleted file mode 100644 index c175998..0000000 --- a/CleanCode/src/NuGet.Packager/tools/install.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -# Runs every time a package is installed in a project - -param($installPath, $toolsPath, $package, $project) - -# $installPath is the path to the folder where the package is installed. -# $toolsPath is the path to the tools directory in the folder where the package is installed. -# $package is a reference to the package object. -# $project is a reference to the project the package was installed to. diff --git a/CleanCode/src/NuGet.Packager/tools/uninstall.ps1 b/CleanCode/src/NuGet.Packager/tools/uninstall.ps1 deleted file mode 100644 index 0ed95e5..0000000 --- a/CleanCode/src/NuGet.Packager/tools/uninstall.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -# Runs every time a package is uninstalled - -param($installPath, $toolsPath, $package, $project) - -# $installPath is the path to the folder where the package is installed. -# $toolsPath is the path to the tools directory in the folder where the package is installed. -# $package is a reference to the package object. -# $project is a reference to the project the package was installed to. diff --git a/README.md b/README.md index 38dfb17..1dea790 100644 --- a/README.md +++ b/README.md @@ -4,21 +4,31 @@ An experiment in trying to automate some of concepts described in [Uncle Bob's books on Clean Code](http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882). -Currently includes: +This is a ReSharper extension to analyse your C# code to highlight a symptom that your code is becoming too complex, is not "clean" enough. Increased complexity can make your code harder to read, understand and maintain. The plugin currently checks: -* TooManyDependencies - Detects when a constructor has more than X interfaces passed in. X is configurable via options dialog +* **Too many dependencies** - warns when a constructor has too many interfaces passed in. +* **Excessive indentation** - warns if a class contains members with too much indentation. +* **Too many chained references** - warns if an expression has too many chained statements, is potentially violating the [Law of Demeter](https://en.wikipedia.org/wiki/Law_of_Demeter). The check will try to ignore fluent APIs - if the type returned is the same as the type invoked, it doesn't count. +* **Method too long** - warns when a method contains too many statements. +* **Class too big** - warns if a class has too many method declarations. +* **Too many method parameters** - warns if a method has too many parameters. +* **Method name not meaningful** - simple check that a method name is longer than a certain threshold. +* **Method flag parameters** - warns if a boolean or enum method parameter is used in an `if` statement with the method. This is an indication that the method has more than one responsibility. +* **Condition complexity** - warns if the condition in an `if` statement contains too many expressions. +* **Hollow type names** - warns if a class has a name with a suffix that is too general, e.g. `Handler`, `Manager`, `Controller`. The list of names is configurable. + +The limits used by each analysis are configurable in the options page. ### Upcoming features -All features are [logged here](http://youtrack.codebetter.com/issues/cc) +Please log feature requests and bugs in [Issues](https://github.com/hhariri/CleanCode/issues). Note that this version only supports C#. -Please use the previous issue tracker for logging bugs, feature requests, etc. ## Installing -Copy the DLL for each Plugin to the ReSharper\bin\Plugins folder +Install from ReSharper → Extension Manager. ## License -Licensed under MIT (c) 2012 Hadi Hariri and Contributors +Licensed under MIT (c) 2012 - 2016 Hadi Hariri and Contributors Note: All references to [Clean Code](http://www.cleancoders.com/), including but not limited to the Clean Code icon are used with permission of Robert C. Martin (a.k.a. UncleBob)