├── .gitattributes ├── .gitignore ├── CleanCode └── src │ ├── CleanCode.nuspec │ ├── CleanCode.sln │ ├── CleanCode.sln.DotSettings │ └── CleanCode │ ├── .gitignore │ ├── CleanCode.csproj │ ├── CleanCodeHighlightingGroupIds.cs │ ├── Features │ ├── ChainedReferences │ │ ├── ChainedReferencesCheck.cs │ │ └── MaximumChainedReferencesHighlighting.cs │ ├── ClassTooBig │ │ ├── ClassTooBigCheck.cs │ │ └── ClassTooBigHighlighting.cs │ ├── ComplexExpression │ │ ├── ComplexConditionExpressionCheck.cs │ │ └── ComplexConditionExpressionHighlighting.cs │ ├── ExcessiveIndentation │ │ ├── ExcessiveIndentHighlighting.cs │ │ └── ExcessiveIndentationCheck.cs │ ├── ExtensionMethods.cs │ ├── FlagArguments │ │ ├── FlagArgumentsCheck.cs │ │ └── FlagArgumentsHighlighting.cs │ ├── HollowNames │ │ ├── HollowNamesCheck.cs │ │ └── HollowTypeNameHighlighting.cs │ ├── MethodNameNotMeaningful │ │ ├── MethodNameNotMeaningfulCheck.cs │ │ └── MethodNameNotMeaningfulHighlighting.cs │ ├── MethodTooLong │ │ ├── MethodTooLongCheck.cs │ │ └── MethodTooLongHighlighting.cs │ ├── TooManyDependencies │ │ ├── TooManyDependenciesCheck.cs │ │ └── TooManyDependenciesHighlighting.cs │ └── TooManyMethodArguments │ │ ├── TooManyArgumentsHighlighting.cs │ │ └── TooManyMethodArgumentsCheck.cs │ ├── InvalidateOnSettingsChange.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Resources │ ├── Icons │ │ └── Settings │ │ │ ├── CleanCode.png │ │ │ ├── ThemedIcons.Settings.Generated.Xaml │ │ │ └── ThemedIcons.Settings.Generated.cs │ ├── Settings.Designer.cs │ ├── Settings.resx │ ├── Warnings.Designer.cs │ └── Warnings.resx │ ├── Settings │ ├── CleanCodeOptionsPage.cs │ └── CleanCodeSettings.cs │ ├── ZoneMarker.cs │ └── packages.config ├── README.md ├── license.txt └── logo.png /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Visual Studio 3 | ################# 4 | 5 | # User-specific files 6 | *.suo 7 | *.user 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Rr]elease/ 12 | [Bb]in/ 13 | [Oo]bj/ 14 | 15 | # NuGet Packages Directory 16 | packages/ 17 | 18 | # Build artifacts 19 | *.nupkg 20 | -------------------------------------------------------------------------------- /CleanCode/src/CleanCode.nuspec: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | CleanCode.CleanCode 5 | 5.1.0 6 | Clean Code 7 | Hadi Hariri, Matt Ellis, SuperJMN 8 | Hadi Hariri, Matt Ellis 9 | https://raw.githubusercontent.com/hhariri/CleanCode/master/logo.png 10 | https://github.com/hhariri/CleanCode 11 | https://raw.github.com/hhariri/CleanCode/master/license.txt 12 | false 13 | Automates some of the concepts in Uncle Bob's Clean Code book 14 | 15 | • Updated to ReSharper 2017.1 16 | 17 | From 5.0.3: 18 | • Stop marking abstract methods too long (#19) 19 | 20 | From 5.0.2: 21 | • Method parameter and type parameter declarations mistakenly used for "method too long" check (#12) 22 | 23 | From 5.0.1: 24 | • Updated to ReSharper 2016.2 25 | • Fix minor installer issue 26 | 27 | From 4.0.0: 28 | • Warning if a method uses flag parameters 29 | • Warning if a method contains too many nested blocks 30 | • Warning if a method name is too short to be meaningful 31 | • Warning if an epression is breaking the Law of Demeter 32 | • Warning if a constructor has too many parameters, indicating too many dependencies 33 | • Warning if a method has too many arguments 34 | • Suggestion highlight if class has too many methods 35 | • Suggestion highlight if method has too many statements 36 | 37 | Copyright 2014-2016 Hadi Hariri and Contributors 38 | 39 | 40 | 41 | clean code 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /CleanCode/src/CleanCode.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanCode", "CleanCode\CleanCode.csproj", "{5F96119C-2646-4298-AD40-30209E7E7BB2}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {5F96119C-2646-4298-AD40-30209E7E7BB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {5F96119C-2646-4298-AD40-30209E7E7BB2}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {5F96119C-2646-4298-AD40-30209E7E7BB2}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {5F96119C-2646-4298-AD40-30209E7E7BB2}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /CleanCode/src/CleanCode.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | ID 3 | 4 | -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/.gitignore: -------------------------------------------------------------------------------- 1 | *.nupkg 2 | -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/CleanCode.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | 8.0.30703 8 | 2.0 9 | {5F96119C-2646-4298-AD40-30209E7E7BB2} 10 | Library 11 | Properties 12 | CleanCode 13 | CleanCode 14 | v4.5 15 | 512 16 | 17 | aa44b150 18 | 19 | 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | TRACE;DEBUG;JET_MODE_ASSERT 25 | prompt 26 | 4 27 | 28 | 29 | pdbonly 30 | true 31 | TRACE 32 | prompt 33 | 4 34 | bin\Release\ 35 | 36 | 37 | 38 | ..\packages\Antlr2.Runtime.2.7.7.02\lib\antlr.runtime.dll 39 | True 40 | 41 | 42 | ..\packages\Appccelerate.StateMachine.JetBrains.2.2.0.1\lib\net45\Appccelerate.Fundamentals.dll 43 | True 44 | 45 | 46 | ..\packages\Appccelerate.StateMachine.JetBrains.2.2.0.1\lib\net45\Appccelerate.StateMachine.dll 47 | True 48 | 49 | 50 | ..\packages\xmlrpcnet.2.5.0\lib\net20\CookComputing.XmlRpcV2.dll 51 | True 52 | 53 | 54 | ..\packages\JetBrains.Platform.Lib.DevExpress.2.0.20150224.0\lib\Net\DevExpress.Data.v7.1.dll 55 | True 56 | 57 | 58 | ..\packages\JetBrains.Platform.Lib.DevExpress.2.0.20150224.0\lib\Net\DevExpress.Utils.v7.1.dll 59 | True 60 | 61 | 62 | ..\packages\JetBrains.Platform.Lib.DevExpress.2.0.20150224.0\lib\Net\DevExpress.XtraEditors.v7.1.dll 63 | True 64 | 65 | 66 | ..\packages\JetBrains.Platform.Lib.DevExpress.2.0.20150224.0\lib\Net\DevExpress.XtraTreeList.v7.1.dll 67 | True 68 | 69 | 70 | ..\packages\SharpZipLib.JetBrains.Stripped.0.87.20161027.6\lib\net40\ICSharpCode.SharpZipLib.dll 71 | True 72 | 73 | 74 | ..\packages\DotNetZip.Reduced.1.9.1.8\lib\net20\Ionic.Zip.Reduced.dll 75 | True 76 | 77 | 78 | ..\packages\JetBrains.Annotations.10.4.0\lib\net\JetBrains.Annotations.dll 79 | True 80 | 81 | 82 | ..\packages\JetBrains.Platform.MSBuild.Logger.1.0.20170130.0\lib\net\JetBrains.MSBuild.Logger.dll 83 | True 84 | True 85 | 86 | 87 | ..\packages\JetBrains.System.Reflection.Metadata.1.0.0\lib\net45\JetBrains.System.Reflection.Metadata.dll 88 | True 89 | 90 | 91 | ..\packages\JetBrains.MahApps.Metro.1.3.1\lib\net45\MahApps.Metro.dll 92 | True 93 | 94 | 95 | ..\packages\JetBrains.Platform.Lib.Microsoft.Deployment.Compression.Cab.2.0.20140304.0\lib\Microsoft.Deployment.Compression.dll 96 | True 97 | 98 | 99 | ..\packages\JetBrains.Platform.Lib.Microsoft.Deployment.Compression.Cab.2.0.20140304.0\lib\Microsoft.Deployment.Compression.Cab.dll 100 | True 101 | 102 | 103 | ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll 104 | True 105 | 106 | 107 | ..\packages\Microsoft.Owin.FileSystems.3.0.1\lib\net45\Microsoft.Owin.FileSystems.dll 108 | True 109 | 110 | 111 | ..\packages\Microsoft.Owin.Host.HttpListener.3.0.1\lib\net45\Microsoft.Owin.Host.HttpListener.dll 112 | True 113 | 114 | 115 | ..\packages\Microsoft.Owin.Hosting.3.0.1\lib\net45\Microsoft.Owin.Hosting.dll 116 | True 117 | 118 | 119 | ..\packages\Microsoft.Owin.StaticFiles.3.0.1\lib\net45\Microsoft.Owin.StaticFiles.dll 120 | True 121 | 122 | 123 | ..\packages\Microsoft.Web.Xdt.2.1.1\lib\net40\Microsoft.Web.XmlTransform.dll 124 | True 125 | 126 | 127 | ..\packages\Windows7APICodePack.JetBrains.Stripped.1.1.20150225.0\lib\Net\Microsoft.WindowsAPICodePack.dll 128 | True 129 | 130 | 131 | ..\packages\Windows7APICodePack.JetBrains.Stripped.1.1.20150225.0\lib\Net\Microsoft.WindowsAPICodePack.Shell.dll 132 | True 133 | 134 | 135 | ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll 136 | True 137 | 138 | 139 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Client.dll 140 | True 141 | 142 | 143 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Commands.dll 144 | True 145 | 146 | 147 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Common.dll 148 | True 149 | 150 | 151 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Configuration.dll 152 | True 153 | 154 | 155 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.ContentModel.dll 156 | True 157 | 158 | 159 | ..\packages\JetBrains.NuGet.Core.2.14.1\lib\net40-Client\NuGet.Core.dll 160 | True 161 | 162 | 163 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.DependencyResolver.Core.dll 164 | True 165 | 166 | 167 | ..\packages\JetBrains.NuGet.Frameworks.4.0.0\lib\net45\NuGet.Frameworks.dll 168 | True 169 | 170 | 171 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.LibraryModel.dll 172 | True 173 | 174 | 175 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.PackageManagement.dll 176 | True 177 | 178 | 179 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Packaging.dll 180 | True 181 | 182 | 183 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Packaging.Core.dll 184 | True 185 | 186 | 187 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Packaging.Core.Types.dll 188 | True 189 | 190 | 191 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.ProjectManagement.dll 192 | True 193 | 194 | 195 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.ProjectModel.dll 196 | True 197 | 198 | 199 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Protocol.Core.Types.dll 200 | True 201 | 202 | 203 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Protocol.Core.v2.dll 204 | True 205 | 206 | 207 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Protocol.Core.v3.dll 208 | True 209 | 210 | 211 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Protocol.VisualStudio.dll 212 | True 213 | 214 | 215 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Repositories.dll 216 | True 217 | 218 | 219 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Resolver.dll 220 | True 221 | 222 | 223 | ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.RuntimeModel.dll 224 | True 225 | 226 | 227 | ..\packages\JetBrains.NuGet.Versioning.4.0.0\lib\net45\NuGet.Versioning.dll 228 | True 229 | 230 | 231 | ..\packages\NUnit.2.6.4\lib\nunit.framework.dll 232 | True 233 | 234 | 235 | ..\packages\NVelocity.1.0.3\lib\NVelocity.dll 236 | True 237 | 238 | 239 | ..\packages\Owin.1.0\lib\net40\Owin.dll 240 | True 241 | 242 | 243 | 244 | 245 | ..\packages\sharpcompress.0.11.6\lib\net40\SharpCompress.dll 246 | True 247 | 248 | 249 | ..\packages\Sprache.JetBrains.2.1.0\lib\net40\Sprache.dll 250 | True 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | ..\packages\JetBrains.Platform.Lib.System.Windows.Interactivity.3.0.40218\lib\System.Windows.Interactivity.dll 264 | True 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | ..\packages\Vestris.ResourceLib.JetBrains.1.4.20150303.0\lib\Net\Vestris.ResourceLib.dll 275 | True 276 | 277 | 278 | 279 | ..\packages\JetBrains.Platform.Lib.WpfContrib.2.0.20150225.0\lib\Net\WpfContrib.dll 280 | True 281 | 282 | 283 | ..\packages\xunit.JetBrains.1.9.2\lib\net20\xunit.dll 284 | True 285 | 286 | 287 | ..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll 288 | True 289 | 290 | 291 | ..\packages\xunit.runner.utility.2.2.0\lib\net35\xunit.runner.utility.net35.dll 292 | True 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | Code 313 | 314 | 315 | 316 | Code 317 | 318 | 319 | 320 | 321 | Code 322 | 323 | 324 | 325 | 326 | 327 | 328 | True 329 | True 330 | Settings.resx 331 | 332 | 333 | Warnings.resx 334 | True 335 | True 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | PublicResXFileCodeGenerator 344 | Designer 345 | Settings.Designer.cs 346 | 347 | 348 | PublicResXFileCodeGenerator 349 | Warnings.Designer.cs 350 | Designer 351 | 352 | 353 | 354 | 355 | MSBuild:Compile 356 | Designer 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | CleanCode.nuspec 365 | Designer 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 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}. 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/CleanCodeHighlightingGroupIds.cs: -------------------------------------------------------------------------------- 1 | using CleanCode; 2 | using JetBrains.ReSharper.Feature.Services.Daemon; 3 | 4 | [assembly: RegisterConfigurableHighlightingsGroup(CleanCodeHighlightingGroupIds.CleanCode, "Clean Code")] 5 | 6 | namespace CleanCode 7 | { 8 | public static class CleanCodeHighlightingGroupIds 9 | { 10 | public const string CleanCode = "CleanCode"; 11 | } 12 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using CleanCode.Resources; 3 | using CleanCode.Settings; 4 | using JetBrains.Application.Settings; 5 | using JetBrains.ReSharper.Daemon.Stages.Dispatcher; 6 | using JetBrains.ReSharper.Feature.Services.Daemon; 7 | using JetBrains.ReSharper.Psi; 8 | using JetBrains.ReSharper.Psi.CSharp.Tree; 9 | using JetBrains.ReSharper.Psi.Tree; 10 | 11 | namespace CleanCode.Features.ChainedReferences 12 | { 13 | [ElementProblemAnalyzer(typeof(ICSharpStatement), HighlightingTypes = new [] 14 | { 15 | typeof(MaximumChainedReferencesHighlighting) 16 | })] 17 | public class ChainedReferencesCheck : ElementProblemAnalyzer 18 | { 19 | protected override void Run(ICSharpStatement element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) 20 | { 21 | if (!element.CanBeEmbedded) 22 | { 23 | var threshold = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumChainedReferences); 24 | HighlightMethodChainsThatAreTooLong(element, consumer, threshold); 25 | } 26 | } 27 | 28 | private void HighlightMethodChainsThatAreTooLong(ITreeNode statement, IHighlightingConsumer consumer, int threshold) 29 | { 30 | var children = statement.Children(); 31 | 32 | foreach (var treeNode in children) 33 | { 34 | var referenceExpression = treeNode as IReferenceExpression; 35 | if (referenceExpression != null) 36 | { 37 | HighlightReferenceExpressionIfNeeded(referenceExpression, consumer, threshold); 38 | } 39 | else 40 | { 41 | HighlightMethodChainsThatAreTooLong(treeNode, consumer, threshold); 42 | } 43 | } 44 | } 45 | 46 | private void HighlightReferenceExpressionIfNeeded(IReferenceExpression referenceExpression, IHighlightingConsumer consumer, int threshold) 47 | { 48 | var types = new HashSet(); 49 | 50 | var nextReferenceExpression = referenceExpression; 51 | var chainLength = 0; 52 | 53 | while (nextReferenceExpression != null) 54 | { 55 | var childReturnType = ExtensionMethods.TryGetClosedReturnTypeFrom(nextReferenceExpression); 56 | 57 | if (childReturnType != null) 58 | { 59 | types.Add(childReturnType); 60 | chainLength++; 61 | } 62 | 63 | nextReferenceExpression = ExtensionMethods.TryGetFirstReferenceExpression(nextReferenceExpression); 64 | } 65 | 66 | var isFluentChain = types.Count == 1; 67 | 68 | if (!isFluentChain) 69 | { 70 | if (chainLength > threshold) 71 | { 72 | AddHighlighting(referenceExpression, consumer); 73 | } 74 | } 75 | } 76 | 77 | private static void AddHighlighting(IReferenceExpression reference, IHighlightingConsumer consumer) 78 | { 79 | var nameIdentifier = reference.NameIdentifier; 80 | var documentRange = nameIdentifier.GetDocumentRange(); 81 | var highlighting = new MaximumChainedReferencesHighlighting(Warnings.ChainedReferences, documentRange); 82 | consumer.AddHighlighting(highlighting); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs: -------------------------------------------------------------------------------- 1 | using CleanCode; 2 | using CleanCode.Features.ChainedReferences; 3 | using JetBrains.DocumentModel; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp; 6 | 7 | [assembly: RegisterConfigurableSeverity(MaximumChainedReferencesHighlighting.SeverityID, null, 8 | CleanCodeHighlightingGroupIds.CleanCode, "Too many chained references", "Too many chained references can break the Law of Demeter.", 9 | Severity.WARNING)] 10 | 11 | namespace CleanCode.Features.ChainedReferences 12 | { 13 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] 14 | public class MaximumChainedReferencesHighlighting : IHighlighting 15 | { 16 | internal const string SeverityID = "TooManyChainedReferences"; 17 | 18 | private readonly DocumentRange documentRange; 19 | 20 | public MaximumChainedReferencesHighlighting(string toolTip, DocumentRange documentRange) 21 | { 22 | ToolTip = toolTip; 23 | this.documentRange = documentRange; 24 | } 25 | 26 | public DocumentRange CalculateRange() => documentRange; 27 | public string ToolTip { get; } 28 | public string ErrorStripeToolTip => ToolTip; 29 | public bool IsValid() => true; 30 | } 31 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Resources; 2 | using CleanCode.Settings; 3 | using JetBrains.Application.Settings; 4 | using JetBrains.ReSharper.Daemon.Stages.Dispatcher; 5 | using JetBrains.ReSharper.Feature.Services.Daemon; 6 | using JetBrains.ReSharper.Psi.CSharp.Tree; 7 | using JetBrains.ReSharper.Psi.Tree; 8 | 9 | namespace CleanCode.Features.ClassTooBig 10 | { 11 | [ElementProblemAnalyzer(typeof(IClassDeclaration), HighlightingTypes = new [] 12 | { 13 | typeof(ClassTooBigHighlighting) 14 | })] 15 | public class ClassTooBigCheck : ElementProblemAnalyzer 16 | { 17 | protected override void Run(IClassDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) 18 | { 19 | var maxLength = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumMethodsInClass); 20 | 21 | var statementCount = element.CountChildren(); 22 | if (statementCount > maxLength) 23 | { 24 | var declarationIdentifier = element.NameIdentifier; 25 | var documentRange = declarationIdentifier.GetDocumentRange(); 26 | var highlighting = new ClassTooBigHighlighting(Warnings.ClassTooBig, documentRange); 27 | consumer.AddHighlighting(highlighting); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs: -------------------------------------------------------------------------------- 1 | using CleanCode; 2 | using CleanCode.Features.ClassTooBig; 3 | using JetBrains.DocumentModel; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp; 6 | 7 | [assembly: RegisterConfigurableSeverity(ClassTooBigHighlighting.SeverityID, null, 8 | CleanCodeHighlightingGroupIds.CleanCode, "Class too big", "This class contains too many methods", 9 | Severity.SUGGESTION)] 10 | 11 | namespace CleanCode.Features.ClassTooBig 12 | { 13 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] 14 | public class ClassTooBigHighlighting : IHighlighting 15 | { 16 | internal const string SeverityID = "ClassTooBig"; 17 | 18 | private readonly DocumentRange documentRange; 19 | 20 | public ClassTooBigHighlighting(string toolTip, DocumentRange documentRange) 21 | { 22 | ToolTip = toolTip; 23 | this.documentRange = documentRange; 24 | } 25 | 26 | public DocumentRange CalculateRange() => documentRange; 27 | public string ToolTip { get; } 28 | public string ErrorStripeToolTip => ToolTip; 29 | public bool IsValid() => true; 30 | } 31 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using CleanCode.Settings; 3 | using JetBrains.Application.Settings; 4 | using JetBrains.ReSharper.Daemon.Stages.Dispatcher; 5 | using JetBrains.ReSharper.Feature.Services.Daemon; 6 | using JetBrains.ReSharper.Psi.CSharp.Tree; 7 | using JetBrains.ReSharper.Psi.Tree; 8 | 9 | namespace CleanCode.Features.ComplexExpression 10 | { 11 | // TODO: This might be better working with IOperatorExpression 12 | // Walk up from the operator to the highest containing expression 13 | // and count depth? 14 | [ElementProblemAnalyzer(typeof(IIfStatement), 15 | typeof(ILoopWithConditionStatement), 16 | typeof(IConditionalTernaryExpression), 17 | typeof(IAssignmentExpression), 18 | typeof(IExpressionInitializer), 19 | HighlightingTypes = new[] 20 | { 21 | typeof(ComplexConditionExpressionHighlighting) 22 | })] 23 | public class ComplexConditionExpressionCheck : ElementProblemAnalyzer 24 | { 25 | protected override void Run(ICSharpTreeNode element, ElementProblemAnalyzerData data, 26 | IHighlightingConsumer consumer) 27 | { 28 | var expression = GetExpression(element); 29 | if (expression != null) 30 | CheckExpression(expression, data, consumer); 31 | } 32 | 33 | private static IExpression GetExpression(ITreeNode node) 34 | { 35 | // Covers for, while and do 36 | var loopStatement = node as ILoopWithConditionStatement; 37 | if (loopStatement != null) 38 | return loopStatement.Condition; 39 | 40 | var ifStatement = node as IIfStatement; 41 | if (ifStatement != null) 42 | return ifStatement.Condition; 43 | 44 | var conditionalTernaryExpression = node as IConditionalTernaryExpression; 45 | if (conditionalTernaryExpression != null) 46 | return conditionalTernaryExpression.ConditionOperand; 47 | 48 | // TODO: Should these two be part of this check? 49 | // Perhaps they should also check the type of the resulting 50 | // variable to be bool? 51 | var assignmentExpression = node as IAssignmentExpression; 52 | if (assignmentExpression != null) 53 | return assignmentExpression.Source; 54 | 55 | var expressionInitializer = node as IExpressionInitializer; 56 | return expressionInitializer?.Value; 57 | } 58 | 59 | private static void CheckExpression(IExpression expression, ElementProblemAnalyzerData data, 60 | IHighlightingConsumer consumer) 61 | { 62 | var maxExpressions = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumExpressionsInCondition); 63 | var expressionCount = expression.GetChildrenRecursive().Count(); 64 | 65 | if (expressionCount > maxExpressions) 66 | { 67 | var documentRange = expression.GetDocumentRange(); 68 | var highlighting = new ComplexConditionExpressionHighlighting(documentRange); 69 | consumer.AddHighlighting(highlighting); 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs: -------------------------------------------------------------------------------- 1 | using CleanCode; 2 | using CleanCode.Features.ComplexExpression; 3 | using CleanCode.Resources; 4 | using JetBrains.DocumentModel; 5 | using JetBrains.ReSharper.Feature.Services.Daemon; 6 | using JetBrains.ReSharper.Psi.CSharp; 7 | 8 | [assembly:RegisterConfigurableSeverity(ComplexConditionExpressionHighlighting.SeverityID, null, 9 | CleanCodeHighlightingGroupIds.CleanCode, "Condition expression too complex", "The expression in the condition is too complex.", 10 | Severity.WARNING)] 11 | 12 | namespace CleanCode.Features.ComplexExpression 13 | { 14 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] 15 | public class ComplexConditionExpressionHighlighting : IHighlighting 16 | { 17 | internal const string SeverityID = "ComplexConditionExpression"; 18 | 19 | private readonly DocumentRange documentRange; 20 | 21 | public ComplexConditionExpressionHighlighting(DocumentRange documentRange) 22 | { 23 | this.documentRange = documentRange; 24 | } 25 | 26 | public DocumentRange CalculateRange() => documentRange; 27 | public string ToolTip => Warnings.ExpressionTooComplex; 28 | public string ErrorStripeToolTip => ToolTip; 29 | public bool IsValid() => true; 30 | } 31 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs: -------------------------------------------------------------------------------- 1 | using CleanCode; 2 | using CleanCode.Features.ExcessiveIndentation; 3 | using CleanCode.Resources; 4 | using JetBrains.DocumentModel; 5 | using JetBrains.ReSharper.Feature.Services.Daemon; 6 | using JetBrains.ReSharper.Psi.CSharp; 7 | 8 | [assembly:RegisterConfigurableSeverity(ExcessiveIndentHighlighting.SeverityID, null, 9 | CleanCodeHighlightingGroupIds.CleanCode, "Excessive indentation", "The nesting in this method is excessive.", 10 | Severity.WARNING)] 11 | 12 | namespace CleanCode.Features.ExcessiveIndentation 13 | { 14 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] 15 | public class ExcessiveIndentHighlighting : IHighlighting 16 | { 17 | internal const string SeverityID = "ExcessiveIndentation"; 18 | private readonly DocumentRange documentRange; 19 | 20 | public ExcessiveIndentHighlighting(DocumentRange documentRange) 21 | { 22 | this.documentRange = documentRange; 23 | } 24 | 25 | public DocumentRange CalculateRange() => documentRange; 26 | public string ToolTip => Warnings.ExcessiveDepth; 27 | public string ErrorStripeToolTip => ToolTip; 28 | public bool IsValid() => true; 29 | } 30 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Settings; 2 | using JetBrains.Application.Settings; 3 | using JetBrains.ReSharper.Daemon.Stages.Dispatcher; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp.Tree; 6 | using JetBrains.ReSharper.Psi.Tree; 7 | 8 | namespace CleanCode.Features.ExcessiveIndentation 9 | { 10 | [ElementProblemAnalyzer(typeof(IMethodDeclaration), 11 | HighlightingTypes = new [] 12 | { 13 | typeof(ExcessiveIndentHighlighting) 14 | })] 15 | public class ExcessiveIndentationCheck : ElementProblemAnalyzer 16 | { 17 | protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) 18 | { 19 | var maxIndentation = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumIndentationDepth); 20 | var depth = element.GetChildrenDepth(); 21 | 22 | if (depth > maxIndentation) 23 | { 24 | var documentRange = element.GetNameDocumentRange(); 25 | var highlighting = new ExcessiveIndentHighlighting(documentRange); 26 | consumer.AddHighlighting(highlighting); 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/ExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using JetBrains.ReSharper.Psi; 5 | using JetBrains.ReSharper.Psi.CSharp.Tree; 6 | using JetBrains.ReSharper.Psi.ExtensionsAPI.Resolve; 7 | using JetBrains.ReSharper.Psi.Resolve; 8 | using JetBrains.ReSharper.Psi.Tree; 9 | 10 | namespace CleanCode.Features 11 | { 12 | public static class ExtensionMethods 13 | { 14 | public static int CountChildren(this ITreeNode node) where T : ITreeNode 15 | { 16 | var treeNodes = node.Children().ToList(); 17 | 18 | var childOfType = treeNodes.OfType(); 19 | var count = childOfType.Count(); 20 | 21 | foreach (var childNodes in treeNodes) 22 | { 23 | count += CountChildren(childNodes); 24 | } 25 | return count; 26 | } 27 | 28 | 29 | public static int GetChildrenDepth(this ITreeNode node) 30 | { 31 | var childrenDepth = 0; 32 | var children = node.Children(); 33 | foreach (var block in children) 34 | { 35 | var levelOfCurrentBlock = GetChildrenDepth(block); 36 | childrenDepth = Math.Max(levelOfCurrentBlock, childrenDepth); 37 | } 38 | 39 | if (IsNodeThatIncreasesDepth(node)) 40 | { 41 | return childrenDepth + 1; 42 | } 43 | return childrenDepth; 44 | } 45 | 46 | public static IEnumerable GetFlattenedHierarchyOfType(this ITreeNode root) where T : class, ITreeNode 47 | { 48 | var list = new List(); 49 | 50 | var rootAsType = root as T; 51 | if (rootAsType != null) 52 | { 53 | list.Add(rootAsType); 54 | } 55 | 56 | list.AddRange(root.GetChildrenRecursive()); 57 | 58 | return list; 59 | } 60 | 61 | public static IEnumerable GetChildrenRecursive(this ITreeNode node) where T : ITreeNode 62 | { 63 | var nodeChildren = node.Children().ToList(); 64 | 65 | var list = new List(); 66 | 67 | var childOfType = nodeChildren.OfType(); 68 | list.AddRange(childOfType); 69 | 70 | foreach (var childNode in nodeChildren) 71 | { 72 | var childrenOfType = GetChildrenRecursive(childNode); 73 | list.AddRange(childrenOfType); 74 | } 75 | 76 | return list; 77 | } 78 | 79 | private static bool IsNodeThatIncreasesDepth(ITreeNode node) 80 | { 81 | if (node is IIfStatement) 82 | { 83 | return true; 84 | } 85 | if (node is IForeachStatement) 86 | { 87 | return true; 88 | } 89 | if (node is IForStatement) 90 | { 91 | return true; 92 | } 93 | if (node is ISwitchStatement) 94 | { 95 | return true; 96 | } 97 | 98 | return false; 99 | } 100 | 101 | public static IType TryGetClosedReturnTypeFrom(ITreeNode treeNode) 102 | { 103 | IType type = null; 104 | var reference = treeNode as IReferenceExpression; 105 | if (reference != null) 106 | { 107 | type = TryGetClosedReturnTypeFromReference(reference.Reference); 108 | } 109 | 110 | var invocationExpression = treeNode as IInvocationExpression; 111 | if (invocationExpression != null) 112 | { 113 | type = TryGetClosedReturnTypeFromReference(invocationExpression.Reference); 114 | } 115 | 116 | return type; 117 | } 118 | 119 | public static IReferenceExpression TryGetFirstReferenceExpression(ITreeNode currentNode) 120 | { 121 | var childNodes = currentNode.Children(); 122 | var firstChildNode = childNodes.FirstOrDefault(); 123 | 124 | if (firstChildNode == null) 125 | return null; 126 | 127 | return firstChildNode as IReferenceExpression ?? 128 | TryGetFirstReferenceExpression(firstChildNode); 129 | } 130 | 131 | private static IType TryGetClosedReturnTypeFromReference(IReference reference) 132 | { 133 | var resolveResultWithInfo = GetResolveResult(reference); 134 | 135 | var declaredElement = resolveResultWithInfo.DeclaredElement; 136 | var parametersOwner = declaredElement as IParametersOwner; 137 | 138 | if (parametersOwner != null) 139 | { 140 | var returnType = parametersOwner.ReturnType; 141 | return returnType.IsOpenType ? GetClosedType(resolveResultWithInfo, returnType) : returnType; 142 | } 143 | 144 | return null; 145 | } 146 | 147 | private static IType GetClosedType(ResolveResultWithInfo resolveResultWithInfo, IType returnType) 148 | { 149 | var closedType = resolveResultWithInfo.Result.Substitution.Apply(returnType); 150 | return closedType; 151 | } 152 | 153 | public static ResolveResultWithInfo GetResolveResult(this IReference reference) 154 | { 155 | return reference.Resolve(); 156 | } 157 | } 158 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using JetBrains.ReSharper.Psi; 3 | using JetBrains.ReSharper.Psi.CSharp.Tree; 4 | using JetBrains.ReSharper.Psi.Tree; 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using JetBrains.ReSharper.Daemon.Stages.Dispatcher; 8 | using JetBrains.ReSharper.Feature.Services.Daemon; 9 | using JetBrains.ReSharper.Psi.Util; 10 | 11 | namespace CleanCode.Features.FlagArguments 12 | { 13 | [ElementProblemAnalyzer(typeof(IMethodDeclaration), 14 | HighlightingTypes = new [] 15 | { 16 | typeof(FlagArgumentsHighlighting) 17 | })] 18 | public class FlagArgumentsCheck : ElementProblemAnalyzer 19 | { 20 | protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) 21 | { 22 | var parameterDeclarations = element.ParameterDeclarations; 23 | 24 | foreach (var parameterDeclaration in parameterDeclarations) 25 | { 26 | if (IsFlagArgument(parameterDeclaration, element.Body)) 27 | { 28 | AddHighlighting(consumer, parameterDeclaration); 29 | } 30 | } 31 | } 32 | 33 | private static bool IsFlagArgument(ITypeOwnerDeclaration typeOwnerDeclaration, ITreeNode node) 34 | { 35 | if (IsOfTypeThatCanBeUsedAsFlag(typeOwnerDeclaration)) 36 | { 37 | var references = GetReferencesTo(typeOwnerDeclaration.DeclaredElement, node); 38 | return references.Any(); 39 | } 40 | 41 | return false; 42 | } 43 | 44 | private static bool IsOfTypeThatCanBeUsedAsFlag(ITypeOwnerDeclaration arg) 45 | { 46 | var type = arg.Type; 47 | return type.IsBool() || type.IsEnumType(); 48 | } 49 | 50 | private static IEnumerable GetReferencesTo(IDeclaredElement declaredElement, ITreeNode body) 51 | { 52 | var ifStatements = body.GetChildrenRecursive(); 53 | 54 | var allConditions = ifStatements.Select(statement => statement.Condition); 55 | 56 | var allReferencesInConditions = 57 | allConditions.SelectMany(expression => expression.GetFlattenedHierarchyOfType()); 58 | 59 | return GetReferencesToArgument(allReferencesInConditions, declaredElement); 60 | } 61 | 62 | private static IEnumerable GetReferencesToArgument(IEnumerable allReferencesInConditions, IDeclaredElement declaredElementInArgument) 63 | { 64 | return allReferencesInConditions.Where(reference => IsReferenceToArgument(reference, declaredElementInArgument)); 65 | } 66 | 67 | private static bool IsReferenceToArgument(IReferenceExpression referenceExpression, IDeclaredElement toFind) 68 | { 69 | if (referenceExpression == null) 70 | { 71 | return false; 72 | } 73 | 74 | var resolveResultWithInfo = referenceExpression.Reference.GetResolveResult(); 75 | var declaredElement = resolveResultWithInfo.DeclaredElement; 76 | 77 | Debug.Assert(declaredElement != null, "declaredElement != null"); 78 | 79 | return declaredElement.ShortName == toFind.ShortName; 80 | } 81 | 82 | private static void AddHighlighting(IHighlightingConsumer consumer, ICSharpParameterDeclaration parameterDeclaration) 83 | { 84 | var documentRange = parameterDeclaration.GetDocumentRange(); 85 | var highlighting = new FlagArgumentsHighlighting(documentRange); 86 | consumer.AddHighlighting(highlighting); 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs: -------------------------------------------------------------------------------- 1 | using CleanCode; 2 | using CleanCode.Features.FlagArguments; 3 | using CleanCode.Resources; 4 | using JetBrains.DocumentModel; 5 | using JetBrains.ReSharper.Feature.Services.Daemon; 6 | using JetBrains.ReSharper.Psi.CSharp; 7 | 8 | [assembly: RegisterConfigurableSeverity(FlagArgumentsHighlighting.SeverityID, null, 9 | CleanCodeHighlightingGroupIds.CleanCode, "Flag argument", "An argument that is used as a flag.", 10 | Severity.WARNING)] 11 | 12 | namespace CleanCode.Features.FlagArguments 13 | { 14 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] 15 | public class FlagArgumentsHighlighting : IHighlighting 16 | { 17 | internal const string SeverityID = "FlagArgument"; 18 | private readonly DocumentRange documentRange; 19 | 20 | public FlagArgumentsHighlighting(DocumentRange documentRange) 21 | { 22 | this.documentRange = documentRange; 23 | } 24 | 25 | public DocumentRange CalculateRange() => documentRange; 26 | public string ToolTip => Warnings.FlagArgument; 27 | public string ErrorStripeToolTip => ToolTip; 28 | public bool IsValid() => true; 29 | } 30 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using CleanCode.Resources; 5 | using CleanCode.Settings; 6 | using JetBrains.Application.Settings; 7 | using JetBrains.ReSharper.Daemon.Stages.Dispatcher; 8 | using JetBrains.ReSharper.Feature.Services.Daemon; 9 | using JetBrains.ReSharper.Psi.CSharp.Tree; 10 | using JetBrains.ReSharper.Psi.Tree; 11 | 12 | namespace CleanCode.Features.HollowNames 13 | { 14 | [ElementProblemAnalyzer(typeof(IClassDeclaration), 15 | HighlightingTypes = new [] 16 | { 17 | typeof(HollowTypeNameHighlighting) 18 | })] 19 | public class HollowNamesCheck : ElementProblemAnalyzer 20 | { 21 | protected override void Run(IClassDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) 22 | { 23 | var suffixes = GetSuffixes(data.SettingsStore); 24 | 25 | var match = GetFirstMatchOrDefault(element.DeclaredName, suffixes); 26 | if (match != null) 27 | AddHighlighting(match, consumer, element); 28 | } 29 | 30 | private IEnumerable GetSuffixes(IContextBoundSettingsStore dataSettingsStore) 31 | { 32 | var suffixes = dataSettingsStore.GetValue((CleanCodeSettings s) => s.MeaninglessClassNameSuffixes); 33 | return suffixes.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); 34 | } 35 | 36 | private static string GetFirstMatchOrDefault(string declaredName, IEnumerable suffixes) 37 | { 38 | return suffixes.FirstOrDefault(declaredName.EndsWith); 39 | } 40 | 41 | private void AddHighlighting(string bannedSuffix, IHighlightingConsumer consumer, IClassDeclaration typeExpression) 42 | { 43 | var identifier = typeExpression.NameIdentifier; 44 | var documentRange = identifier.GetDocumentRange(); 45 | var highlighting = new HollowTypeNameHighlighting(string.Format(Warnings.HollowTypeName, bannedSuffix), documentRange); 46 | consumer.AddHighlighting(highlighting); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs: -------------------------------------------------------------------------------- 1 | using CleanCode; 2 | using CleanCode.Features.HollowNames; 3 | using JetBrains.DocumentModel; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp; 6 | 7 | [assembly: RegisterConfigurableSeverity(HollowTypeNameHighlighting.SeverityID, null, 8 | CleanCodeHighlightingGroupIds.CleanCode, "Hollow type name", "This type has a name that doesn't express its intent.", 9 | Severity.SUGGESTION)] 10 | 11 | namespace CleanCode.Features.HollowNames 12 | { 13 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] 14 | public class HollowTypeNameHighlighting : IHighlighting 15 | { 16 | internal const string SeverityID = "HollowTypeName"; 17 | private readonly DocumentRange documentRange; 18 | 19 | public HollowTypeNameHighlighting(string toolTip, DocumentRange documentRange) 20 | { 21 | ToolTip = toolTip; 22 | this.documentRange = documentRange; 23 | } 24 | 25 | public DocumentRange CalculateRange() => documentRange; 26 | public string ToolTip { get; } 27 | public string ErrorStripeToolTip => ToolTip; 28 | public bool IsValid() => true; 29 | } 30 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Settings; 2 | using JetBrains.Application.Settings; 3 | using JetBrains.ReSharper.Daemon.Stages.Dispatcher; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp.Tree; 6 | using JetBrains.ReSharper.Psi.Tree; 7 | 8 | namespace CleanCode.Features.MethodNameNotMeaningful 9 | { 10 | [ElementProblemAnalyzer(typeof(IMethodDeclaration), HighlightingTypes = new [] 11 | { 12 | typeof(MethodNameNotMeaningfulHighlighting) 13 | })] 14 | public class MethodNameNotMeaningfulCheck : ElementProblemAnalyzer 15 | { 16 | protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) 17 | { 18 | if (element.NameIdentifier == null) 19 | return; 20 | 21 | var minimumMethodNameLength = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MinimumMeaningfulMethodNameLength); 22 | 23 | var name = element.NameIdentifier.GetText(); 24 | var methodNameLength = name.Length; 25 | if (methodNameLength < minimumMethodNameLength) 26 | { 27 | var documentRange = element.GetNameDocumentRange(); 28 | var highlighting = new MethodNameNotMeaningfulHighlighting(documentRange); 29 | consumer.AddHighlighting(highlighting); 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs: -------------------------------------------------------------------------------- 1 | using CleanCode; 2 | using CleanCode.Features.MethodNameNotMeaningful; 3 | using CleanCode.Resources; 4 | using JetBrains.DocumentModel; 5 | using JetBrains.ReSharper.Feature.Services.Daemon; 6 | using JetBrains.ReSharper.Psi.CSharp; 7 | 8 | [assembly: RegisterConfigurableSeverity(MethodNameNotMeaningfulHighlighting.SeverityID, null, 9 | CleanCodeHighlightingGroupIds.CleanCode, "Method name not meaningful", 10 | "This method name is too short to be meaningful.", 11 | Severity.WARNING)] 12 | 13 | namespace CleanCode.Features.MethodNameNotMeaningful 14 | { 15 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] 16 | public class MethodNameNotMeaningfulHighlighting : IHighlighting 17 | { 18 | internal const string SeverityID = "MethodNameNotMeaningful"; 19 | private readonly DocumentRange documentRange; 20 | 21 | public MethodNameNotMeaningfulHighlighting(DocumentRange documentRange) 22 | { 23 | this.documentRange = documentRange; 24 | } 25 | 26 | public DocumentRange CalculateRange() => documentRange; 27 | public string ToolTip => Warnings.MethodNameNotMeaningful; 28 | public string ErrorStripeToolTip => ToolTip; 29 | public bool IsValid() => true; 30 | } 31 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Settings; 2 | using JetBrains.Application.Settings; 3 | using JetBrains.ReSharper.Daemon.Stages.Dispatcher; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp.Tree; 6 | using JetBrains.ReSharper.Psi.Tree; 7 | 8 | namespace CleanCode.Features.MethodTooLong 9 | { 10 | [ElementProblemAnalyzer(typeof(IMethodDeclaration), HighlightingTypes = new [] 11 | { 12 | typeof(MethodTooLongHighlighting) 13 | })] 14 | public class MethodTooLongCheck : ElementProblemAnalyzer 15 | { 16 | protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) 17 | { 18 | var maxStatements = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumMethodStatements); 19 | var maxDeclarations = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumDeclarationsInMethod); 20 | 21 | var statementCount = element.CountChildren(); 22 | if (statementCount <= maxStatements) 23 | { 24 | // Only look in the method body for declarations, otherwise we see 25 | // parameters + type parameters. We can ignore arrow expressions, as 26 | // they must be a single expression and won't have declarations 27 | var declarationCount = element.Body?.CountChildren() ?? 0; 28 | if (declarationCount <= maxDeclarations) 29 | return; 30 | } 31 | 32 | var highlighting = new MethodTooLongHighlighting(element.GetNameDocumentRange()); 33 | consumer.AddHighlighting(highlighting); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs: -------------------------------------------------------------------------------- 1 | using CleanCode; 2 | using CleanCode.Features.MethodTooLong; 3 | using CleanCode.Resources; 4 | using JetBrains.DocumentModel; 5 | using JetBrains.ReSharper.Feature.Services.Daemon; 6 | using JetBrains.ReSharper.Psi.CSharp; 7 | 8 | [assembly: RegisterConfigurableSeverity(MethodTooLongHighlighting.SeverityID, null, 9 | CleanCodeHighlightingGroupIds.CleanCode, "Method too long", "The method is bigger than it should be.", 10 | Severity.SUGGESTION)] 11 | 12 | namespace CleanCode.Features.MethodTooLong 13 | { 14 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] 15 | public class MethodTooLongHighlighting : IHighlighting 16 | { 17 | internal const string SeverityID = "MethodTooLong"; 18 | private readonly DocumentRange documentRange; 19 | 20 | public MethodTooLongHighlighting(DocumentRange documentRange) 21 | { 22 | this.documentRange = documentRange; 23 | } 24 | 25 | public DocumentRange CalculateRange() => documentRange; 26 | public string ToolTip => Warnings.MethodTooLong; 27 | public string ErrorStripeToolTip => ToolTip; 28 | public bool IsValid() => true; 29 | } 30 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using CleanCode.Settings; 3 | using JetBrains.Application.Settings; 4 | using JetBrains.ReSharper.Daemon.Stages.Dispatcher; 5 | using JetBrains.ReSharper.Feature.Services.Daemon; 6 | using JetBrains.ReSharper.Psi.CSharp.Tree; 7 | using JetBrains.ReSharper.Psi.Tree; 8 | using JetBrains.ReSharper.Psi.Util; 9 | 10 | namespace CleanCode.Features.TooManyDependencies 11 | { 12 | [ElementProblemAnalyzer(typeof(IConstructorDeclaration), HighlightingTypes = new [] 13 | { 14 | typeof(TooManyDependenciesHighlighting) 15 | })] 16 | public class TooManyDependenciesCheck : ElementProblemAnalyzer 17 | { 18 | protected override void Run(IConstructorDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) 19 | { 20 | var maxDependencies = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumConstructorDependencies); 21 | 22 | var dependencies = element.ParameterDeclarations.Select( 23 | declaration => declaration.DeclaredElement != null && 24 | declaration.DeclaredElement.Type.IsInterfaceType()); 25 | 26 | var dependenciesCount = dependencies.Count(); 27 | if (dependenciesCount > maxDependencies) 28 | { 29 | var highlighting = new TooManyDependenciesHighlighting(element.GetNameDocumentRange()); 30 | consumer.AddHighlighting(highlighting); 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs: -------------------------------------------------------------------------------- 1 | using CleanCode; 2 | using CleanCode.Features.TooManyDependencies; 3 | using CleanCode.Resources; 4 | using JetBrains.DocumentModel; 5 | using JetBrains.ReSharper.Feature.Services.Daemon; 6 | using JetBrains.ReSharper.Psi.CSharp; 7 | 8 | [assembly: RegisterConfigurableSeverity(TooManyDependenciesHighlighting.SeverityID, null, 9 | CleanCodeHighlightingGroupIds.CleanCode, "Too many dependencies", "Too many dependencies passed into constructor.", 10 | Severity.WARNING)] 11 | 12 | namespace CleanCode.Features.TooManyDependencies 13 | { 14 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] 15 | public class TooManyDependenciesHighlighting : IHighlighting 16 | { 17 | internal const string SeverityID = "TooManyDependencies"; 18 | private readonly DocumentRange documentRange; 19 | 20 | public TooManyDependenciesHighlighting(DocumentRange documentRange) 21 | { 22 | this.documentRange = documentRange; 23 | } 24 | 25 | public DocumentRange CalculateRange() => documentRange; 26 | public string ToolTip => Warnings.TooManyDependencies; 27 | public string ErrorStripeToolTip => ToolTip; 28 | public bool IsValid() => true; 29 | } 30 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs: -------------------------------------------------------------------------------- 1 | using CleanCode; 2 | using CleanCode.Features.TooManyMethodArguments; 3 | using JetBrains.DocumentModel; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp; 6 | 7 | [assembly: RegisterConfigurableSeverity(TooManyArgumentsHighlighting.SeverityID, null, 8 | CleanCodeHighlightingGroupIds.CleanCode, "Too many arguments", "Too many arguments passed to a method.", 9 | Severity.WARNING)] 10 | 11 | namespace CleanCode.Features.TooManyMethodArguments 12 | { 13 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] 14 | public class TooManyArgumentsHighlighting : IHighlighting 15 | { 16 | internal const string SeverityID = "TooManyArguments"; 17 | private readonly DocumentRange documentRange; 18 | 19 | public TooManyArgumentsHighlighting(string toolTip, DocumentRange documentRange) 20 | { 21 | ToolTip = toolTip; 22 | this.documentRange = documentRange; 23 | } 24 | 25 | public DocumentRange CalculateRange() => documentRange; 26 | public string ToolTip { get; } 27 | public string ErrorStripeToolTip => ToolTip; 28 | public bool IsValid() => true; 29 | } 30 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Resources; 2 | using CleanCode.Settings; 3 | using JetBrains.Application.Settings; 4 | using JetBrains.ReSharper.Daemon.Stages.Dispatcher; 5 | using JetBrains.ReSharper.Feature.Services.Daemon; 6 | using JetBrains.ReSharper.Psi.CSharp.Tree; 7 | using JetBrains.ReSharper.Psi.Tree; 8 | 9 | namespace CleanCode.Features.TooManyMethodArguments 10 | { 11 | [ElementProblemAnalyzer(typeof(IMethodDeclaration), HighlightingTypes = new [] 12 | { 13 | typeof(TooManyArgumentsHighlighting) 14 | })] 15 | public class TooManyMethodArgumentsCheck : ElementProblemAnalyzer 16 | { 17 | protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) 18 | { 19 | var maxParameters = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumMethodParameters); 20 | var parameterDeclarations = element.ParameterDeclarations; 21 | 22 | if (parameterDeclarations.Count > maxParameters) 23 | { 24 | var highlighting = new TooManyArgumentsHighlighting(Warnings.TooManyMethodArguments, 25 | element.GetNameDocumentRange()); 26 | consumer.AddHighlighting(highlighting); 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/InvalidateOnSettingsChange.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Settings; 2 | using JetBrains.Application.Settings; 3 | using JetBrains.DataFlow; 4 | using JetBrains.ProjectModel; 5 | using JetBrains.ReSharper.Feature.Services.Daemon; 6 | 7 | namespace CleanCode 8 | { 9 | [SolutionComponent] 10 | public class InvalidateOnSettingsChange 11 | { 12 | public InvalidateOnSettingsChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) 13 | { 14 | var settingsKey = settingsStore.Schema.GetKey(); 15 | settingsStore.AdviseChange(lifetime, settingsKey, daemon.Invalidate); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("ReSharper Clean Code Plugin")] 5 | [assembly: AssemblyCompany("Hadi Hariri")] 6 | [assembly: AssemblyProduct("ReSharper Clean Code Plugin")] 7 | [assembly: AssemblyDescription("Automates some of the concepts in Uncle Bob's Clean Code book")] 8 | [assembly: AssemblyCopyright("Copyright ® 2016 Hadi Hariri and Contributors")] 9 | [assembly: AssemblyTrademark("")] 10 | [assembly: AssemblyCulture("")] 11 | 12 | [assembly: ComVisible(false)] 13 | [assembly: Guid("97927FF9-8C9C-4DC5-A309-29C23F41DA47")] 14 | 15 | [assembly: AssemblyVersion("5.1.0.0")] 16 | [assembly: AssemblyFileVersion("5.1.0.0")] 17 | -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Resources/Icons/Settings/CleanCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhariri/CleanCode/dccdf5b0c4c348485be3d3807efde1d5dc3c5872/CleanCode/src/CleanCode/Resources/Icons/Settings/CleanCode.png -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAB3RJTUUH3AQMCwQuopFIpgAAAAd0RVh0QXV0aG9yAKmuzEgAAAAMdEVYdERlc2NyaXB0aW9uABMJISMAAAAKdEVYdENvcHlyaWdodACsD8w6AAAADnRFWHRDcmVhdGlvbiB0aW1lADX3DwkAAAAJdEVYdFNvZnR3YXJlAF1w/zoAAAALdEVYdERpc2NsYWltZXIAt8C0jwAAAAh0RVh0V2FybmluZwDAG+aHAAAAB3RFWHRTb3VyY2UA9f+D6wAAAAh0RVh0Q29tbWVudAD2zJa/AAAABnRFWHRUaXRsZQCo7tInAAADI0lEQVQ4jW2TX2gbdQDHP3eXNG1imiWtJMvsOrBbaXWC1qldaZ3QVXwozKkI/unDZLPgg/TF5019UVBfZCiCTyIyBs7hoC3FEautXZcodI0sk6Wy1a5prrnLXS6/3OXufNjDKvP7/P1+nr4fSQjhsyOu5/JrYYn51QVul9ZRJIVk/EGG+gYZeWSIgKLsrCPtBCzfzHH2h69oFUEuXZvlYLqfrl17uLQyywuPjlJtmrzz0tsMHzx8P+D7qz8y/dMMDz/QzeXlDEWniJKQ8Zou5qZFf7SPZCpFuD3C4YFBJp5/7R5guZjj468/4aHQbuav/8yel9PEetoRrsAwDCzdQs2rKMtBepN9yBGFyVdOceSJYaSaVfPf+PQk+q0Kek2l790DdOzrQA7JVK0qallFLalsl7bZ/ruCO+Nz/KkXqQdtPn/vM5TnXj16+sZKAUcTRMcj7B3YSzKRItoSRQpJ2LZNuBFmvDlOXqyy6d1BW61iKy7pzt3Iv+WvkI6lWKutkehPEIvECEoBZEkGCRJKghPtJ1h0F9FkDb/TR22WaBESiytLyLIrUzE0/JhH3bXQHZ0ev4devxfd0jkmHWOuMke2nsW2bZCh4ldoaQ1Qr1nI/1Q20Ewd4QhMw6RULpHVshxyDjFoDFJWy0yXpxF1gWnX8GQX3/cxbAO70SCQiifRiiphEUHoAlVRUSsqmWiGbqubL9a/xDAMRFUg2aA4Cm1uG1pFo1UOEXjywOOcmz3PxsYW5D3C+9twAjYXty4SqofIVq+i6RoNq4HneVCC6q0qhY0CZ06dITDcP0Q03s5bz77J6W/fJxaIIMdkFqVFzIZJvVanYTeQXAm/6tNcajIwMoC4Ixg7Mnb3SPOrC0x8dJIOdmHWKmj7t3E7XWzPBo+74y0fKScRD8XZXN/kwtkL9wAA38x9x8KVBSJ+G7l8jj/VPEbAANdHMWUSwQ7C0TCOcJh6fYrJicn7Zcr88Q== 6 | C+dmztPiBlm7XUQ1VPaluygZWxT/ukk8kuDDqQ8YHRn9fxsBnKbD5WyG62s3yBZ+pyuWBs/nmceeZmz4KMFg8D86/wtO9pvksFBNEwAAAABJRU5ErkJggg== 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | [assembly: global::System.Windows.Markup.XmlnsDefinitionAttribute("urn:shemas-jetbrains-com:ui-application-icons-settings", "CleanCode.Resources.Icons")] 12 | [assembly: global::JetBrains.UI.Icons.CompiledIcons.CompiledIconsPackAttribute(IconPackResourceIdentification="CleanCode;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xaml", IconNames=new string[] { 13 | "CleanCode"})] 14 | 15 | namespace CleanCode.Resources.Icons 16 | { 17 | 18 | 19 | /// 20 | /// 21 | /// Autogenerated identifier classes and identifier objects to Themed Icons registered with . 22 | /// Identifier classes should be used in attributes, XAML, or generic parameters. Where an value is expected, use the identifier object in the Id field of the identifier class. 23 | /// 24 | /// 25 | /// 26 | /// This code was compile-time generated to support Themed Icons in the JetBrains application. 27 | /// 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. 28 | ///

XAML

29 | /// 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. 30 | /// 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. 31 | /// Example: 32 | /// <Image Source="{icons:ThemedIcon myres:SettingsThemedIcons+CleanCode}" /> 33 | ///

Attributes

34 | /// 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. 35 | /// 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. 36 | /// Example: 37 | /// [Item(Name="Sample", Icon=typeof(SettingsThemedIcons.CleanCode))] 38 | ///

CodeBehind

39 | /// In codebehind, we have two distinct tasks: (a) specify some icon in the APIs and (b) render icon images onscreen. 40 | /// 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. 41 | /// 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. 42 | /// Example: 43 | /// // Getting IconId identifier object to use with APIs 44 | ///IconId iconid = SettingsThemedIcons.CleanCode.Id; 45 | /// // Getting IconId out of an Icon Identifier Class type 46 | ///IconId iconid = CompiledIconClassAttribute.TryGetCompiledIconClassId(typeof(SettingsThemedIcons.CleanCode), OnError.Throw); 47 | /// // Getting image for screen rendering by IconId 48 | ///themediconmanager.Icons[icnoid] 49 | /// // Getting image for screen rendering by Icon Identifier Class 50 | ///themediconmanager.GetIcon<SettingsThemedIcons.CleanCode>() 51 | ///

Icons Origin

52 | /// This code was generated by a pre-compile build task from a set of input files which are XAML files adhering to a certain convention, as convenient for exporting them from the Illustrator workspace, plus separate PNG files with raster icons. In the projects, these files are designated with ThemedIconsXamlV3 and ThemedIconPng build actions and do not themselves get into the output assembly. All of such files are processed, vector images for different themes of the same icon are split and combined into the single list of icons in this assembly. This list is then written into the genearted XAML file (compiled into BAML within assembly), and serves as the source for this generated code. 53 | ///
54 | public sealed class SettingsThemedIcons 55 | { 56 | 57 | /// 58 | /// 59 | /// Autogenerated identifier class for the CleanCode Themed Icon. 60 | /// 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. 61 | /// 62 | /// 63 | /// 64 | /// For details on Themed Icons and their use, see Remarks on class. 65 | /// 66 | /// 67 | /// 68 | /// <Image Source="{icons:ThemedIcon myres:SettingsThemedIcons+CleanCode}" /> <!-- XAML --> 69 | /// 70 | /// 71 | /// [Item(Name="Sample", Icon=typeof(SettingsThemedIcons.CleanCode))] // C# Type attribute 72 | /// 73 | /// 74 | /// IconId iconid = SettingsThemedIcons.CleanCode.Id; // IconId identifier object 75 | /// 76 | /// 77 | /// themediconmanager.GetIcon<SettingsThemedIcons.CleanCode>() // Icon image for rendering 78 | /// 79 | [global::JetBrains.UI.Icons.CompiledIcons.CompiledIconClassAttribute("CleanCode;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xaml", 0, "CleanCode")] 80 | public sealed class CleanCode : global::JetBrains.UI.Icons.CompiledIcons.CompiledIconClass 81 | { 82 | 83 | /// 84 | /// 85 | /// Autogenerated identifier object for the CleanCode Themed Icon. 86 | /// Identifier objects should be used where an value is expected. In attributes, XAML, or generic parameters use the containing identifier class. 87 | /// 88 | /// 89 | /// 90 | /// For details on Themed Icons and their use, see Remarks on class. 91 | /// 92 | /// 93 | /// 94 | /// <Image Source="{icons:ThemedIcon myres:SettingsThemedIcons+CleanCode}" /> <!-- XAML --> 95 | /// 96 | /// 97 | /// [Item(Name="Sample", Icon=typeof(SettingsThemedIcons.CleanCode))] // C# Type attribute 98 | /// 99 | /// 100 | /// IconId iconid = SettingsThemedIcons.CleanCode.Id; // IconId identifier object 101 | /// 102 | /// 103 | /// themediconmanager.GetIcon<SettingsThemedIcons.CleanCode>() // Icon image for rendering 104 | /// 105 | 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"); 106 | } 107 | } 108 | } 109 | 110 | 111 | public sealed class RenderedIcons_ByPackResourceNameHash_E1185BB5DC155E8A999AD43CA329D4ED 112 | { 113 | 114 | public static byte[] CleanCode____png__x1 = new byte[] { 115 | 137, 116 | 80, 117 | 78, 118 | 71, 119 | 13, 120 | 10, 121 | 26, 122 | 10, 123 | 0, 124 | 0, 125 | 0, 126 | 13, 127 | 73, 128 | 72, 129 | 68, 130 | 82, 131 | 0, 132 | 0, 133 | 0, 134 | 16, 135 | 0, 136 | 0, 137 | 0, 138 | 16, 139 | 8, 140 | 6, 141 | 0, 142 | 0, 143 | 0, 144 | 31, 145 | 243, 146 | 255, 147 | 97, 148 | 0, 149 | 0, 150 | 0, 151 | 1, 152 | 115, 153 | 82, 154 | 71, 155 | 66, 156 | 0, 157 | 174, 158 | 206, 159 | 28, 160 | 233, 161 | 0, 162 | 0, 163 | 0, 164 | 4, 165 | 103, 166 | 65, 167 | 77, 168 | 65, 169 | 0, 170 | 0, 171 | 177, 172 | 143, 173 | 11, 174 | 252, 175 | 97, 176 | 5, 177 | 0, 178 | 0, 179 | 0, 180 | 9, 181 | 112, 182 | 72, 183 | 89, 184 | 115, 185 | 0, 186 | 0, 187 | 14, 188 | 195, 189 | 0, 190 | 0, 191 | 14, 192 | 195, 193 | 1, 194 | 199, 195 | 111, 196 | 168, 197 | 100, 198 | 0, 199 | 0, 200 | 0, 201 | 19, 202 | 73, 203 | 68, 204 | 65, 205 | 84, 206 | 56, 207 | 79, 208 | 99, 209 | 24, 210 | 5, 211 | 163, 212 | 96, 213 | 20, 214 | 140, 215 | 2, 216 | 48, 217 | 96, 218 | 96, 219 | 0, 220 | 0, 221 | 4, 222 | 16, 223 | 0, 224 | 1, 225 | 167, 226 | 68, 227 | 124, 228 | 99, 229 | 0, 230 | 0, 231 | 0, 232 | 0, 233 | 73, 234 | 69, 235 | 78, 236 | 68, 237 | 174, 238 | 66, 239 | 96, 240 | 130}; 241 | 242 | public static byte[] CleanCode____png__x2 = new byte[] { 243 | 137, 244 | 80, 245 | 78, 246 | 71, 247 | 13, 248 | 10, 249 | 26, 250 | 10, 251 | 0, 252 | 0, 253 | 0, 254 | 13, 255 | 73, 256 | 72, 257 | 68, 258 | 82, 259 | 0, 260 | 0, 261 | 0, 262 | 32, 263 | 0, 264 | 0, 265 | 0, 266 | 32, 267 | 8, 268 | 6, 269 | 0, 270 | 0, 271 | 0, 272 | 115, 273 | 122, 274 | 122, 275 | 244, 276 | 0, 277 | 0, 278 | 0, 279 | 1, 280 | 115, 281 | 82, 282 | 71, 283 | 66, 284 | 0, 285 | 174, 286 | 206, 287 | 28, 288 | 233, 289 | 0, 290 | 0, 291 | 0, 292 | 4, 293 | 103, 294 | 65, 295 | 77, 296 | 65, 297 | 0, 298 | 0, 299 | 177, 300 | 143, 301 | 11, 302 | 252, 303 | 97, 304 | 5, 305 | 0, 306 | 0, 307 | 0, 308 | 9, 309 | 112, 310 | 72, 311 | 89, 312 | 115, 313 | 0, 314 | 0, 315 | 14, 316 | 195, 317 | 0, 318 | 0, 319 | 14, 320 | 195, 321 | 1, 322 | 199, 323 | 111, 324 | 168, 325 | 100, 326 | 0, 327 | 0, 328 | 0, 329 | 26, 330 | 73, 331 | 68, 332 | 65, 333 | 84, 334 | 88, 335 | 71, 336 | 237, 337 | 193, 338 | 1, 339 | 1, 340 | 0, 341 | 0, 342 | 0, 343 | 130, 344 | 32, 345 | 255, 346 | 175, 347 | 110, 348 | 72, 349 | 64, 350 | 0, 351 | 0, 352 | 0, 353 | 192, 354 | 185, 355 | 26, 356 | 16, 357 | 32, 358 | 0, 359 | 1, 360 | 157, 361 | 120, 362 | 73, 363 | 67, 364 | 0, 365 | 0, 366 | 0, 367 | 0, 368 | 73, 369 | 69, 370 | 78, 371 | 68, 372 | 174, 373 | 66, 374 | 96, 375 | 130}; 376 | } 377 | -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Resources/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CleanCode.Resources { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | public class Settings { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Settings() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | public static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CleanCode.Resources.Settings", typeof(Settings).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | public static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to Maximum declarations per method. 65 | /// 66 | public static string DeclarationsMaximum { 67 | get { 68 | return ResourceManager.GetString("DeclarationsMaximum", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// Looks up a localized string similar to Maximum chained references. 74 | /// 75 | public static string MaximumChainedReferences { 76 | get { 77 | return ResourceManager.GetString("MaximumChainedReferences", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// Looks up a localized string similar to Maximum interface dependencies for a constructor. 83 | /// 84 | public static string MaximumConstructorDependencies { 85 | get { 86 | return ResourceManager.GetString("MaximumConstructorDependencies", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// Looks up a localized string similar to Maximum expressions inside a condition. 92 | /// 93 | public static string MaximumExpressionsInsideACondition { 94 | get { 95 | return ResourceManager.GetString("MaximumExpressionsInsideACondition", resourceCulture); 96 | } 97 | } 98 | 99 | /// 100 | /// Looks up a localized string similar to Maximum level of nesting in a method. 101 | /// 102 | public static string MaximumLevelOfNestingInAMethod { 103 | get { 104 | return ResourceManager.GetString("MaximumLevelOfNestingInAMethod", resourceCulture); 105 | } 106 | } 107 | 108 | /// 109 | /// Looks up a localized string similar to Maximum method declaration parameters. 110 | /// 111 | public static string MaximumMethodDeclarationParameters { 112 | get { 113 | return ResourceManager.GetString("MaximumMethodDeclarationParameters", resourceCulture); 114 | } 115 | } 116 | 117 | /// 118 | /// Looks up a localized string similar to Maximum methods per class. 119 | /// 120 | public static string MaximumMethodsPerClass { 121 | get { 122 | return ResourceManager.GetString("MaximumMethodsPerClass", resourceCulture); 123 | } 124 | } 125 | 126 | /// 127 | /// Looks up a localized string similar to Maximum statements per method. 128 | /// 129 | public static string MaximumStatementsPerMethod { 130 | get { 131 | return ResourceManager.GetString("MaximumStatementsPerMethod", resourceCulture); 132 | } 133 | } 134 | 135 | /// 136 | /// Looks up a localized string similar to List of meaningless suffixes. 137 | /// 138 | public static string MeaninglessNameSuffixes { 139 | get { 140 | return ResourceManager.GetString("MeaninglessNameSuffixes", resourceCulture); 141 | } 142 | } 143 | 144 | /// 145 | /// Looks up a localized string similar to Separate items with commas. 146 | /// 147 | public static string MeaninglessNameSuffixesTooltip { 148 | get { 149 | return ResourceManager.GetString("MeaninglessNameSuffixesTooltip", resourceCulture); 150 | } 151 | } 152 | 153 | /// 154 | /// Looks up a localized string similar to Minimum method name length. 155 | /// 156 | public static string MinimumMethodNameLength { 157 | get { 158 | return ResourceManager.GetString("MinimumMethodNameLength", resourceCulture); 159 | } 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Resources/Settings.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Maximum statements per method 122 | 123 | 124 | Maximum interface dependencies for a constructor 125 | 126 | 127 | Maximum method declaration parameters 128 | 129 | 130 | Maximum level of nesting in a method 131 | 132 | 133 | Maximum methods per class 134 | 135 | 136 | Maximum chained references 137 | 138 | 139 | Minimum method name length 140 | 141 | 142 | Maximum expressions inside a condition 143 | 144 | 145 | List of meaningless suffixes 146 | 147 | 148 | Separate items with commas 149 | 150 | 151 | Maximum declarations per method 152 | 153 | -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Resources/Warnings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CleanCode.Resources { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | public class Warnings { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Warnings() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | public static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CleanCode.Resources.Warnings", typeof(Warnings).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | public static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to Too many chained references. This might be violating the Law of Demeter.. 65 | /// 66 | public static string ChainedReferences { 67 | get { 68 | return ResourceManager.GetString("ChainedReferences", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// Looks up a localized string similar to Class contains too many methods. This might be violating the Single Responsibility Principle.. 74 | /// 75 | public static string ClassTooBig { 76 | get { 77 | return ResourceManager.GetString("ClassTooBig", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// Looks up a localized string similar to Excessive depth of nested code blocks.. 83 | /// 84 | public static string ExcessiveDepth { 85 | get { 86 | return ResourceManager.GetString("ExcessiveDepth", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// Looks up a localized string similar to This expression is too complex.. 92 | /// 93 | public static string ExpressionTooComplex { 94 | get { 95 | return ResourceManager.GetString("ExpressionTooComplex", resourceCulture); 96 | } 97 | } 98 | 99 | /// 100 | /// 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.. 101 | /// 102 | public static string FlagArgument { 103 | get { 104 | return ResourceManager.GetString("FlagArgument", resourceCulture); 105 | } 106 | } 107 | 108 | /// 109 | /// 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.. 110 | /// 111 | public static string HollowTypeName { 112 | get { 113 | return ResourceManager.GetString("HollowTypeName", resourceCulture); 114 | } 115 | } 116 | 117 | /// 118 | /// Looks up a localized string similar to The name of this method is too short to be meaningful.. 119 | /// 120 | public static string MethodNameNotMeaningful { 121 | get { 122 | return ResourceManager.GetString("MethodNameNotMeaningful", resourceCulture); 123 | } 124 | } 125 | 126 | /// 127 | /// Looks up a localized string similar to This method is too long, indicating that it has too much responsibility.. 128 | /// 129 | public static string MethodTooLong { 130 | get { 131 | return ResourceManager.GetString("MethodTooLong", resourceCulture); 132 | } 133 | } 134 | 135 | /// 136 | /// 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.. 137 | /// 138 | public static string TooManyDependencies { 139 | get { 140 | return ResourceManager.GetString("TooManyDependencies", resourceCulture); 141 | } 142 | } 143 | 144 | /// 145 | /// Looks up a localized string similar to This method requires too many arguments.. 146 | /// 147 | public static string TooManyMethodArguments { 148 | get { 149 | return ResourceManager.GetString("TooManyMethodArguments", resourceCulture); 150 | } 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Resources/Warnings.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | There are too many interfaces being passed in to this constructor. It might be violating the Single Responsibility Principle. 122 | 123 | 124 | This method requires too many arguments. 125 | 126 | 127 | This method is too long, indicating that it has too much responsibility. 128 | 129 | 130 | Excessive depth of nested code blocks. 131 | 132 | 133 | Class contains too many methods. This might be violating the Single Responsibility Principle. 134 | 135 | 136 | Too many chained references. This might be violating the Law of Demeter. 137 | 138 | 139 | The name of this method is too short to be meaningful. 140 | 141 | 142 | This argument is used as a flag in the method. This might be violating the Single Responsibility Principle. 143 | 144 | 145 | This expression is too complex. 146 | 147 | 148 | The usage of the suffix '{0}' is discouraged because it's too generic. Choose a meaningful name instead to clarify its intent and responsibilities. 149 | 150 | -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Settings/CleanCodeOptionsPage.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using CleanCode.Resources.Icons; 3 | using JetBrains.DataFlow; 4 | using JetBrains.ReSharper.Feature.Services.Daemon.OptionPages; 5 | using JetBrains.UI.Options; 6 | using JetBrains.UI.Options.OptionsDialog2.SimpleOptions; 7 | using JetBrains.UI.RichText; 8 | 9 | namespace CleanCode.Settings 10 | { 11 | [OptionsPage(PageId, "Clean Code", typeof(SettingsThemedIcons.CleanCode), ParentId = CodeInspectionPage.PID)] 12 | public class CleanCodeOptionsPage : CustomSimpleOptionsPage 13 | { 14 | private const string PageId = "CleanCode"; 15 | 16 | public CleanCodeOptionsPage(Lifetime lifetime, OptionsSettingsSmartContext optionsSettingsSmartContext) 17 | : base(lifetime, optionsSettingsSmartContext) 18 | { 19 | AddHeader("Single Responsibility"); 20 | AddText("A class should only have a single responsibility. Do not do too much in a class or method."); 21 | AddIntOption((CleanCodeSettings s) => s.MaximumMethodsInClass, 22 | Resources.Settings.MaximumMethodsPerClass, 23 | "Too many method declarations in a class is an indicator that the class is doing too much."); 24 | AddIntOption((CleanCodeSettings s) => s.MaximumMethodParameters, 25 | Resources.Settings.MaximumMethodDeclarationParameters, 26 | "Too many parameters in a method declaration is an indicator of having more than one responsibility"); 27 | AddIntOption((CleanCodeSettings s) => s.MaximumMethodStatements, Resources.Settings.MaximumStatementsPerMethod, 28 | "Long methods are indicator of having more than one responsibility."); 29 | AddIntOption((CleanCodeSettings s) => s.MaximumDeclarationsInMethod, 30 | Resources.Settings.DeclarationsMaximum, 31 | "Too many variables are an indicator of having more than one responsibility."); 32 | AddIntOption((CleanCodeSettings s) => s.MaximumIndentationDepth, 33 | Resources.Settings.MaximumLevelOfNestingInAMethod, 34 | "Too much nesting in a method is an indicator of having more than one responsibility."); 35 | 36 | AddHeader("Coupling"); 37 | AddText("Avoid excessive coupling beween classes."); 38 | AddIntOption((CleanCodeSettings s) => s.MaximumConstructorDependencies, 39 | Resources.Settings.MaximumConstructorDependencies); 40 | AddIntOption((CleanCodeSettings s) => s.MaximumChainedReferences, 41 | Resources.Settings.MaximumChainedReferences, 42 | "Avoid breaking the Law of Demeter."); 43 | 44 | AddHeader("Legibility"); 45 | AddText("Names should be meaningful."); 46 | AddIntOption((CleanCodeSettings s) => s.MinimumMeaningfulMethodNameLength, 47 | Resources.Settings.MinimumMethodNameLength); 48 | AddStringOption((CleanCodeSettings s) => s.MeaninglessClassNameSuffixes, 49 | Resources.Settings.MeaninglessNameSuffixes, 50 | Resources.Settings.MeaninglessNameSuffixesTooltip); 51 | 52 | AddHeader("Complexity"); 53 | AddText("Reduce complexity in individual statements."); 54 | AddIntOption((CleanCodeSettings s) => s.MaximumExpressionsInCondition, 55 | Resources.Settings.MaximumExpressionsInsideACondition); 56 | 57 | AddRichText( 58 | new RichText( 59 | "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)", 60 | new TextStyle(FontStyle.Italic))); 61 | FinishPage(); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Application.Settings; 2 | using JetBrains.ReSharper.Resources.Settings; 3 | 4 | namespace CleanCode.Settings 5 | { 6 | [SettingsKey(typeof(CodeInspectionSettings), "CleanCode")] 7 | public class CleanCodeSettings 8 | { 9 | [SettingsEntry(3, "MaximumConstructorDependencies")] 10 | public readonly int MaximumConstructorDependencies; 11 | 12 | [SettingsEntry(3, "MaximumMethodParameters")] 13 | public readonly int MaximumMethodParameters; 14 | 15 | [SettingsEntry(15, "MaximumMethodStatements")] 16 | public readonly int MaximumMethodStatements; 17 | 18 | [SettingsEntry(6, "MaximumDeclarationsInMethod")] 19 | public readonly int MaximumDeclarationsInMethod; 20 | 21 | [SettingsEntry(3, "MaximumIndentationDepth")] 22 | public int MaximumIndentationDepth { get; set; } 23 | 24 | [SettingsEntry(20, "MaximumMethodsInClass")] 25 | public int MaximumMethodsInClass { get; set; } 26 | 27 | [SettingsEntry(2, "MaximumChainedReferences")] 28 | public int MaximumChainedReferences { get; set; } 29 | 30 | [SettingsEntry(4, "MinimumMeaningfulMethodNameLength")] 31 | public int MinimumMeaningfulMethodNameLength { get; set; } 32 | 33 | [SettingsEntry("Handler,Manager,Processor,Controller,Helper", "MeaninglessClassNameSuffixes")] 34 | public string MeaninglessClassNameSuffixes { get; set; } 35 | 36 | [SettingsEntry(1, "MaximumExpressionsInCondition")] 37 | public int MaximumExpressionsInCondition { get; set; } 38 | } 39 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/ZoneMarker.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Application.BuildScript.Application.Zones; 2 | 3 | namespace CleanCode 4 | { 5 | [ZoneMarker] 6 | public class ZoneMarker 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /CleanCode/src/CleanCode/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Clean Code ReSharper Plugin Project 2 | 3 | ### CleanCode 4 | 5 | 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). 6 | 7 | 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: 8 | 9 | * **Too many dependencies** - warns when a constructor has too many interfaces passed in. 10 | * **Excessive indentation** - warns if a class contains members with too much indentation. 11 | * **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. 12 | * **Method too long** - warns when a method contains too many statements. 13 | * **Class too big** - warns if a class has too many method declarations. 14 | * **Too many method parameters** - warns if a method has too many parameters. 15 | * **Method name not meaningful** - simple check that a method name is longer than a certain threshold. 16 | * **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. 17 | * **Condition complexity** - warns if the condition in an `if` statement contains too many expressions. 18 | * **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. 19 | 20 | The limits used by each analysis are configurable in the options page. 21 | 22 | ### Upcoming features 23 | 24 | Please log feature requests and bugs in [Issues](https://github.com/hhariri/CleanCode/issues). Note that this version only supports C#. 25 | 26 | ## Installing 27 | 28 | Install from ReSharper → Extension Manager. 29 | 30 | ## License 31 | 32 | Licensed under MIT (c) 2012 - 2016 Hadi Hariri and Contributors 33 | 34 | 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) 35 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Hadi Hariri and Contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhariri/CleanCode/dccdf5b0c4c348485be3d3807efde1d5dc3c5872/logo.png --------------------------------------------------------------------------------