├── logo.png ├── tools ├── 7za.exe ├── nuget.exe └── vswhere.exe ├── src ├── rider │ └── main │ │ ├── resources │ │ ├── messages │ │ │ └── CleanCodeBundle.properties │ │ └── META-INF │ │ │ └── plugin.xml │ │ └── kotlin │ │ └── com │ │ └── jetbrains │ │ └── rider │ │ └── plugins │ │ └── cleancode │ │ ├── options │ │ └── CleanCodeOptionsPage.kt │ │ └── CleanCodeBundle.kt └── dotnet │ ├── MO.CleanCode │ ├── Resources │ │ ├── Icons │ │ │ └── Settings │ │ │ │ ├── CleanCode.png │ │ │ │ ├── ThemedIcons.Settings.Generated.Xaml │ │ │ │ └── ThemedIcons.Settings.Generated.cs │ │ ├── Settings.resx │ │ ├── Warnings.Designer.cs │ │ ├── Warnings.resx │ │ └── Settings.Designer.cs │ ├── ZoneMarker.cs │ ├── CleanCodeHighlightingGroupIds.cs │ ├── Extension │ │ └── ExpressionExt.cs │ ├── Features │ │ ├── ExtensionMethodsVb.cs │ │ ├── HollowNames │ │ │ ├── HollowNamesCheckCs.cs │ │ │ ├── HollowNamesCheckVb.cs │ │ │ ├── HollowTypeNameHighlighting.cs │ │ │ └── HollowNamesCheck.cs │ │ ├── MethodTooLong │ │ │ ├── MethodTooLongCheckVb.cs │ │ │ ├── MethodTooLongCheckCs.cs │ │ │ ├── MethodTooLongHighlighting.cs │ │ │ ├── MethodTooManyDeclarationsHighlighting.cs │ │ │ └── MethodTooLongCheck.cs │ │ ├── ClassTooBig │ │ │ ├── ClassTooBigCheckVb.cs │ │ │ ├── ClassTooBigCheckCs.cs │ │ │ ├── ClassTooBigCheck.cs │ │ │ └── ClassTooBigHighlighting.cs │ │ ├── MethodNameNotMeaningful │ │ │ ├── MethodNameNotMeaningfulCheckVb.cs │ │ │ ├── MethodNameNotMeaningfulCheckCs.cs │ │ │ ├── MethodNameNotMeaningfulCheck.cs │ │ │ └── MethodNameNotMeaningfulHighlighting.cs │ │ ├── TooManyPublicMethods │ │ │ ├── TooManyPublicMethodsCheckVb.cs │ │ │ ├── TooManyPublicMethodsCheckCs.cs │ │ │ ├── TooManyPublicMethodsCheck.cs │ │ │ └── TooManyPublicMethodsHighlighting.cs │ │ ├── ChainedReferences │ │ │ ├── ChainedReferencesCheckVb.cs │ │ │ ├── ChainedReferencesCheckCs.cs │ │ │ ├── MaximumChainedReferencesHighlighting.cs │ │ │ └── ChainedReferencesCheck.cs │ │ ├── FlagArguments │ │ │ ├── FlagArgumentsHighlighting.cs │ │ │ └── FlagArgumentsCheckCs.cs │ │ ├── ExcessiveIndentation │ │ │ ├── ExcessiveIndentationCheckCs.cs │ │ │ └── ExcessiveIndentHighlighting.cs │ │ ├── TooManyMethodArguments │ │ │ ├── TooManyMethodArgumentsCheckVb.cs │ │ │ ├── TooManyMethodArgumentsCheckCs.cs │ │ │ └── TooManyArgumentsHighlighting.cs │ │ ├── TooManyDependencies │ │ │ ├── TooManyDependenciesCheckCs.cs │ │ │ ├── TooManyDependenciesCheckVb.cs │ │ │ └── TooManyDependenciesHighlighting.cs │ │ ├── ComplexExpression │ │ │ ├── ComplexConditionExpressionHighlighting.cs │ │ │ ├── ComplexConditionExpressionCheckCs.cs │ │ │ └── ComplexConditionExpressionCheckVb.cs │ │ └── ExtensionMethodsCsharp.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── InvalidateOnSettingsChange.cs │ ├── Settings │ │ ├── CleanCodeSettings.cs │ │ └── CleanCodeOptionsPage.cs │ ├── MO.CleanCode.Rider.csproj │ ├── MO.CleanCode.csproj │ └── CleanCode.ruleset │ ├── CleanCode.sln.DotSettings │ ├── Plugin.props │ ├── Directory.Build.props │ └── CleanCode.sln ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── libs.versions.toml ├── global.json ├── .config └── dotnet-tools.json ├── .github ├── dependabot.yml └── workflows │ └── main.yml ├── .gitattributes ├── .gitignore ├── gradle.properties ├── protocol ├── src │ └── main │ │ └── kotlin │ │ └── model │ │ └── rider │ │ └── CleanCodeModel.kt └── build.gradle.kts ├── .idea └── runConfigurations │ ├── Generate_Protocol.xml │ ├── rdgen.xml │ └── Rider.xml ├── publishPlugin.ps1 ├── settings.gradle ├── license.txt ├── settings.ps1 ├── Readme.md ├── CHANGELOG.md ├── runVisualStudio.ps1 ├── gradlew.bat └── gradlew /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MO2k4/CleanCode/HEAD/logo.png -------------------------------------------------------------------------------- /tools/7za.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MO2k4/CleanCode/HEAD/tools/7za.exe -------------------------------------------------------------------------------- /tools/nuget.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MO2k4/CleanCode/HEAD/tools/nuget.exe -------------------------------------------------------------------------------- /tools/vswhere.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MO2k4/CleanCode/HEAD/tools/vswhere.exe -------------------------------------------------------------------------------- /src/rider/main/resources/messages/CleanCodeBundle.properties: -------------------------------------------------------------------------------- 1 | configurable.name.cleancode.options.title=Clean Code -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MO2k4/CleanCode/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "8.0.100", 4 | "rollForward": "latestMinor" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Resources/Icons/Settings/CleanCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MO2k4/CleanCode/HEAD/src/dotnet/MO.CleanCode/Resources/Icons/Settings/CleanCode.png -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/ZoneMarker.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.Application.BuildScript.Application.Zones; 2 | 3 | namespace CleanCode 4 | { 5 | [ZoneMarker] 6 | public class ZoneMarker { } 7 | } 8 | -------------------------------------------------------------------------------- /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "csharpier": { 6 | "version": "1.2.1", 7 | "commands": [ 8 | "csharpier" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://cache-redirector.jetbrains.com/services.gradle.org/distributions/gradle-8.8-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: nuget 4 | directory: "/src/dotnet/" 5 | schedule: 6 | interval: daily 7 | time: "18:10" 8 | open-pull-requests-limit: 10 9 | - package-ecosystem: "gradle" 10 | directory: "/" # Location of package manifests 11 | schedule: 12 | interval: "daily" 13 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/CleanCodeHighlightingGroupIds.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.ReSharper.Feature.Services.Daemon; 2 | 3 | namespace CleanCode 4 | { 5 | [RegisterConfigurableHighlightingsGroup(CleanCode, "Clean Code")] 6 | public static class CleanCodeHighlightingGroupIds 7 | { 8 | public const string CleanCode = "CleanCode"; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Extension/ExpressionExt.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using CleanCode.Features; 3 | using JetBrains.ReSharper.Psi.Tree; 4 | 5 | namespace CleanCode.Extension 6 | { 7 | public static class ExpressionExt 8 | { 9 | public static int GetExpressionCount(this IExpression expression) 10 | where T : ITreeNode => expression.GetChildrenRecursive().Count(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/dotnet/CleanCode.sln.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | ID 3 | 4 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | kotlin = "2.2.21" # https://plugins.jetbrains.com/docs/intellij/using-kotlin.html#kotlin-standard-library 3 | rdGen = "2025.3.1" # https://github.com/JetBrains/rd/releases 4 | 5 | [libraries] 6 | kotlinStdLib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" } 7 | rdGen = { group = "com.jetbrains.rd", name = "rd-gen", version.ref = "rdGen" } 8 | 9 | [plugins] 10 | kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } -------------------------------------------------------------------------------- /src/rider/main/kotlin/com/jetbrains/rider/plugins/cleancode/options/CleanCodeOptionsPage.kt: -------------------------------------------------------------------------------- 1 | package com.jetbrains.rider.plugins.cleancode.options 2 | 3 | import com.jetbrains.rider.plugins.cleancode.CleanCodeBundle 4 | import com.jetbrains.rider.settings.simple.SimpleOptionsPage 5 | 6 | class CleanCodeOptionsPage : SimpleOptionsPage( 7 | name= CleanCodeBundle.message("configurable.name.cleancode.options.title"), 8 | pageId = "CleanCodeAnalysisOptionsPage") { 9 | override fun getId(): String { 10 | return "CleanCodeAnalysisOptionsPage"; 11 | } 12 | } -------------------------------------------------------------------------------- /.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 | .vs/ 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | 10 | # Build results 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | [Bb]in/ 14 | [Oo]bj/ 15 | 16 | # NuGet Packages Directory 17 | packages/ 18 | 19 | # Build artifacts 20 | *.nupkg 21 | tools 22 | /*.lnk 23 | 24 | build 25 | output 26 | .gradle 27 | .tmp 28 | 29 | # User-specific files 30 | *.suo 31 | *.user 32 | *.sln.docstates 33 | *.cache 34 | 35 | # IDEs 36 | .idea 37 | .vs 38 | _ReSharper* 39 | _dotTrace* 40 | /distribution/*.zip 41 | .settings/org.eclipse.buildship.core.prefs 42 | .project 43 | .classpath 44 | protocol/.settings/org.eclipse.buildship.core.prefs 45 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ExtensionMethodsVb.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using JetBrains.ReSharper.Psi.Tree; 3 | using JetBrains.ReSharper.Psi.VB.Tree; 4 | 5 | namespace CleanCode.Features 6 | { 7 | public static class ExtensionMethodsVb 8 | { 9 | public static IReferenceExpression TryGetFirstReferenceExpression(ITreeNode currentNode) 10 | { 11 | var childNodes = currentNode.Children(); 12 | var firstChildNode = childNodes.FirstOrDefault(); 13 | 14 | if (firstChildNode == null) 15 | return null; 16 | 17 | return firstChildNode as IReferenceExpression 18 | ?? TryGetFirstReferenceExpression(firstChildNode); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/HollowNames/HollowNamesCheckCs.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.ReSharper.Feature.Services.Daemon; 2 | using JetBrains.ReSharper.Psi.CSharp.Tree; 3 | 4 | namespace CleanCode.Features.HollowNames 5 | { 6 | [ElementProblemAnalyzer( 7 | typeof(IClassDeclaration), 8 | HighlightingTypes = new[] { typeof(HollowTypeNameHighlighting) } 9 | )] 10 | public class HollowNamesCheckCs : HollowNamesCheck 11 | { 12 | protected override void Run( 13 | IClassDeclaration element, 14 | ElementProblemAnalyzerData data, 15 | IHighlightingConsumer consumer 16 | ) 17 | { 18 | CheckAndAddHighlighting(element, data, consumer); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/HollowNames/HollowNamesCheckVb.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.ReSharper.Feature.Services.Daemon; 2 | using JetBrains.ReSharper.Psi.VB.Tree; 3 | 4 | namespace CleanCode.Features.HollowNames 5 | { 6 | [ElementProblemAnalyzer( 7 | typeof(IClassDeclaration), 8 | HighlightingTypes = new[] { typeof(HollowTypeNameHighlighting) } 9 | )] 10 | public class HollowNamesCheckVb : HollowNamesCheck 11 | { 12 | protected override void Run( 13 | IClassDeclaration element, 14 | ElementProblemAnalyzerData data, 15 | IHighlightingConsumer consumer 16 | ) 17 | { 18 | CheckAndAddHighlighting(element, data, consumer); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/MethodTooLong/MethodTooLongCheckVb.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.ReSharper.Feature.Services.Daemon; 2 | using JetBrains.ReSharper.Psi.VB.Tree; 3 | 4 | namespace CleanCode.Features.MethodTooLong 5 | { 6 | [ElementProblemAnalyzer( 7 | typeof(IMethodDeclaration), 8 | HighlightingTypes = new[] { typeof(MethodTooLongHighlighting) } 9 | )] 10 | public class MethodTooLongCheckVb : MethodTooLongCheck 11 | { 12 | protected override void Run( 13 | IMethodDeclaration element, 14 | ElementProblemAnalyzerData data, 15 | IHighlightingConsumer consumer 16 | ) 17 | { 18 | CheckAndAddHighlight(element, data, consumer); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("ReSharper Clean Code Plugin")] 5 | [assembly: AssemblyCompany("Martin Oehlert, Hadi Hariri, Matt Ellis")] 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 ® 2014-2019 Martin Oehlert 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.6.7.0")] 16 | [assembly: AssemblyFileVersion("5.6.7.0")] 17 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Any property can be overwritten from command-line via 2 | # -P= 3 | 4 | DotnetPluginId=MO.CleanCode 5 | DotnetSolution=src/dotnet/CleanCode.sln 6 | RiderPluginId=CleanCode 7 | 8 | BuildConfiguration=Debug 9 | 10 | PublishToken="_PLACEHOLDER_" 11 | 12 | # See https://www.jetbrains.com/intellij-repository/snapshots 13 | # 14 | # Examples: 15 | # Release: 2020.2 16 | # EAP: 2020.3-EAP2-SNAPSHOT 17 | # Nightly: 2020.3-SNAPSHOT 18 | ProductVersion=2025.3 19 | PluginVersion=2025.3.0 20 | 21 | # Kotlin 1.4 will bundle the stdlib dependency by default, causing problems with the version bundled with the IDE 22 | # https://blog.jetbrains.com/kotlin/2020/07/kotlin-1-4-rc-released/#stdlib-default 23 | kotlin.stdlib.default.dependency=false -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/MethodTooLong/MethodTooLongCheckCs.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.ReSharper.Feature.Services.Daemon; 2 | using JetBrains.ReSharper.Psi.CSharp.Tree; 3 | 4 | namespace CleanCode.Features.MethodTooLong 5 | { 6 | [ElementProblemAnalyzer( 7 | typeof(IMethodDeclaration), 8 | HighlightingTypes = new[] { typeof(MethodTooLongHighlighting) } 9 | )] 10 | public class MethodTooLongCheckCs : MethodTooLongCheck 11 | { 12 | protected override void Run( 13 | IMethodDeclaration element, 14 | ElementProblemAnalyzerData data, 15 | IHighlightingConsumer consumer 16 | ) 17 | { 18 | CheckAndAddHighlight(element, data, consumer); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/dotnet/Plugin.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2025.3.0 4 | CleanCode 5 | Automates some of the concepts in Uncle Bob's Clean Code book 6 | Martin Oehlert, Hadi Hariri, Matt Ellis 7 | Copyright $([System.DateTime]::Now.Year) Maintainers of CleanCode 8 | resharper plugin cleancode clean code 9 | https://github.com/MO2k4/CleanCode 10 | https://raw.github.com/MO2k4/CleanCode/master/license.txt 11 | https://raw.githubusercontent.com/MO2k4/CleanCode/master/logo.png 12 | 13 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ClassTooBig/ClassTooBigCheckVb.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.ReSharper.Feature.Services.Daemon; 2 | using JetBrains.ReSharper.Psi.VB.Tree; 3 | 4 | namespace CleanCode.Features.ClassTooBig 5 | { 6 | [ElementProblemAnalyzer( 7 | typeof(IClassDeclaration), 8 | HighlightingTypes = new[] { typeof(ClassTooBigHighlighting) } 9 | )] 10 | public class ClassTooBigCheckVb : ClassTooBigCheck 11 | { 12 | protected override void Run( 13 | IClassDeclaration element, 14 | ElementProblemAnalyzerData data, 15 | IHighlightingConsumer consumer 16 | ) 17 | { 18 | CheckIfClassIsTooBig(element.Name, element, data, consumer); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/rider/main/kotlin/com/jetbrains/rider/plugins/cleancode/CleanCodeBundle.kt: -------------------------------------------------------------------------------- 1 | package com.jetbrains.rider.plugins.cleancode 2 | 3 | import com.intellij.DynamicBundle 4 | import org.jetbrains.annotations.Nls 5 | import org.jetbrains.annotations.NonNls 6 | import org.jetbrains.annotations.PropertyKey 7 | 8 | class CleanCodeBundle : DynamicBundle(BUNDLE) { 9 | companion object { 10 | @NonNls 11 | private const val BUNDLE = "messages.CleanCodeBundle" 12 | private val INSTANCE: CleanCodeBundle = CleanCodeBundle() 13 | 14 | @Nls 15 | fun message( 16 | @PropertyKey(resourceBundle = BUNDLE) key: String, 17 | vararg params: Any 18 | ): String { 19 | return INSTANCE.getMessage(key, *params) 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /protocol/src/main/kotlin/model/rider/CleanCodeModel.kt: -------------------------------------------------------------------------------- 1 | package model.rider 2 | 3 | import com.jetbrains.rider.model.nova.ide.SolutionModel 4 | import com.jetbrains.rider.generator.nova.* 5 | import com.jetbrains.rider.generator.nova.PredefinedType.* 6 | 7 | @Suppress("unused") 8 | object CleanCodeModel : Ext(SolutionModel.Solution) { 9 | 10 | val MyEnum = enum { 11 | +"FirstValue" 12 | +"SecondValue" 13 | } 14 | 15 | val MyStructure = structdef { 16 | field("projectFile", string) 17 | field("target", string) 18 | } 19 | 20 | init { 21 | property("myString", string) 22 | property("myBool", bool) 23 | property("myEnum", MyEnum.nullable) 24 | 25 | map("data", string, string) 26 | 27 | signal("myStructure", MyStructure) 28 | } 29 | } -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheckVb.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.ReSharper.Feature.Services.Daemon; 2 | using JetBrains.ReSharper.Psi.VB.Tree; 3 | 4 | namespace CleanCode.Features.MethodNameNotMeaningful 5 | { 6 | [ElementProblemAnalyzer( 7 | typeof(IMethodDeclaration), 8 | HighlightingTypes = new[] { typeof(MethodNameNotMeaningfulHighlighting) } 9 | )] 10 | public class MethodNameNotMeaningfulCheckVb : MethodNameNotMeaningfulCheck 11 | { 12 | protected override void Run( 13 | IMethodDeclaration element, 14 | ElementProblemAnalyzerData data, 15 | IHighlightingConsumer consumer 16 | ) 17 | { 18 | CheckAndAddHighlighting(element, data, consumer); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheckCs.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.ReSharper.Feature.Services.Daemon; 2 | using JetBrains.ReSharper.Psi.CSharp.Tree; 3 | 4 | namespace CleanCode.Features.MethodNameNotMeaningful 5 | { 6 | [ElementProblemAnalyzer( 7 | typeof(IMethodDeclaration), 8 | HighlightingTypes = new[] { typeof(MethodNameNotMeaningfulHighlighting) } 9 | )] 10 | public class MethodNameNotMeaningfulCheckCs : MethodNameNotMeaningfulCheck 11 | { 12 | protected override void Run( 13 | IMethodDeclaration element, 14 | ElementProblemAnalyzerData data, 15 | IHighlightingConsumer consumer 16 | ) 17 | { 18 | CheckAndAddHighlighting(element, data, consumer); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.idea/runConfigurations/Generate_Protocol.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 16 | 18 | true 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ClassTooBig/ClassTooBigCheckCs.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.ReSharper.Feature.Services.Daemon; 2 | using JetBrains.ReSharper.Psi.CSharp.Tree; 3 | 4 | namespace CleanCode.Features.ClassTooBig 5 | { 6 | [ElementProblemAnalyzer( 7 | typeof(IClassDeclaration), 8 | HighlightingTypes = new[] { typeof(ClassTooBigHighlighting) } 9 | )] 10 | public class ClassTooBigCheckCs : ClassTooBigCheck 11 | { 12 | protected override void Run( 13 | IClassDeclaration element, 14 | ElementProblemAnalyzerData data, 15 | IHighlightingConsumer consumer 16 | ) 17 | { 18 | CheckIfClassIsTooBig( 19 | element.NameIdentifier, 20 | element, 21 | data, 22 | consumer 23 | ); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/InvalidateOnSettingsChange.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Settings; 2 | using JetBrains.Application.Settings; 3 | using JetBrains.Lifetimes; 4 | using JetBrains.ProjectModel; 5 | using JetBrains.ReSharper.Feature.Services.Daemon; 6 | 7 | namespace CleanCode 8 | { 9 | [SolutionComponent(JetBrains.Application.Parts.Instantiation.ContainerAsyncPrimaryThread)] 10 | public class InvalidateOnSettingsChange 11 | { 12 | public InvalidateOnSettingsChange( 13 | Lifetime lifetime, 14 | IDaemon daemon, 15 | ISettingsStore settingsStore 16 | ) 17 | { 18 | var settingsKey = settingsStore.Schema.GetKey(); 19 | settingsStore.AdviseChange( 20 | lifetime, 21 | settingsKey, 22 | () => daemon.Invalidate("settings have changed") 23 | ); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /publishPlugin.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string]$Configuration = "Release", 3 | [Parameter(Mandatory=$true)] 4 | [string]$Version, 5 | [Parameter(Mandatory=$true)] 6 | [string]$ApiKey 7 | ) 8 | 9 | Set-StrictMode -Version Latest 10 | $ErrorActionPreference = "Stop" 11 | $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent 12 | Set-Location $PSScriptRoot 13 | 14 | . ".\settings.ps1" 15 | 16 | $ChangelogText = ([Regex]::Matches([System.IO.File]::ReadAllText("CHANGELOG.md"), '(?s)(##.+?.+?)(?=##|$)').Captures | Select -First 10) -Join '' 17 | 18 | Invoke-Exe $MSBuildPath "/t:Restore;Rebuild;Pack" "$SolutionPath" "/v:minimal" "/p:Configuration=$Configuration" "/p:PackageOutputPath=$OutputDirectory" "/p:PackageVersion=$Version" "/p:PackageReleaseNotes=`"$ChangelogText`"" 19 | $PackageFile = "$OutputDirectory\$PluginId.$Version*.nupkg" 20 | Invoke-Exe $NuGetPath push $PackageFile -Source "https://plugins.jetbrains.com/api/v2/package" -ApiKey $ApiKey 21 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | // Provide repositories to resolve plugins 3 | repositories { 4 | maven { setUrl("https://cache-redirector.jetbrains.com/plugins.gradle.org") } 5 | maven { setUrl("https://cache-redirector.jetbrains.com/maven-central") } 6 | maven { setUrl("https://cache-redirector.jetbrains.com/dl.bintray.com/kotlin/kotlin-eap") } 7 | } 8 | resolutionStrategy { 9 | eachPlugin { 10 | // Gradle has to map a plugin dependency to Maven coordinates - '{groupId}:{artifactId}:{version}'. It tries 11 | // to do use '{plugin.id}:{plugin.id}.gradle.plugin:version'. 12 | // This doesn't work for rdgen, so we provide some help 13 | if (requested.id.id == "com.jetbrains.rdgen") { 14 | useModule("com.jetbrains.rd:rd-gen:${requested.version}") 15 | } 16 | } 17 | } 18 | } 19 | 20 | rootProject.name = "cleancode" 21 | 22 | include(":protocol") -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/TooManyPublicMethods/TooManyPublicMethodsCheckVb.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.ReSharper.Feature.Services.Daemon; 2 | using JetBrains.ReSharper.Psi; 3 | using JetBrains.ReSharper.Psi.VB.Tree; 4 | 5 | namespace CleanCode.Features.TooManyPublicMethods 6 | { 7 | [ElementProblemAnalyzer( 8 | typeof(IClassDeclaration), 9 | HighlightingTypes = new[] { typeof(TooManyPublicMethodsHighlighting) } 10 | )] 11 | public class TooManyPublicMethodsCheckVb : TooManyPublicMethodsCheck 12 | { 13 | protected override void Run( 14 | IClassDeclaration element, 15 | ElementProblemAnalyzerData data, 16 | IHighlightingConsumer consumer 17 | ) 18 | { 19 | CheckIfClassHasTooManyPublicMethods( 20 | element.Name, 21 | element, 22 | data, 23 | consumer, 24 | method => method.GetAccessRights() == AccessRights.PUBLIC 25 | ); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.idea/runConfigurations/rdgen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 16 | 18 | true 19 | true 20 | false 21 | false 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/TooManyPublicMethods/TooManyPublicMethodsCheckCs.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.ReSharper.Feature.Services.Daemon; 2 | using JetBrains.ReSharper.Psi; 3 | using JetBrains.ReSharper.Psi.CSharp.Tree; 4 | 5 | namespace CleanCode.Features.TooManyPublicMethods 6 | { 7 | [ElementProblemAnalyzer( 8 | typeof(IClassDeclaration), 9 | HighlightingTypes = new[] { typeof(TooManyPublicMethodsHighlighting) } 10 | )] 11 | public class TooManyPublicMethodsCheckCs : TooManyPublicMethodsCheck 12 | { 13 | protected override void Run( 14 | IClassDeclaration element, 15 | ElementProblemAnalyzerData data, 16 | IHighlightingConsumer consumer 17 | ) 18 | { 19 | CheckIfClassHasTooManyPublicMethods( 20 | element.NameIdentifier, 21 | element, 22 | data, 23 | consumer, 24 | method => method.GetAccessRights() == AccessRights.PUBLIC 25 | ); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.idea/runConfigurations/Rider.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 16 | 18 | true 19 | true 20 | false 21 | false 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Settings; 2 | using JetBrains.ReSharper.Feature.Services.Daemon; 3 | using JetBrains.ReSharper.Psi.Tree; 4 | 5 | namespace CleanCode.Features.ClassTooBig; 6 | 7 | public abstract class ClassTooBigCheck : ElementProblemAnalyzer 8 | { 9 | protected static void CheckIfClassIsTooBig( 10 | ITreeNode declaration, 11 | ITreeNode element, 12 | ElementProblemAnalyzerData data, 13 | IHighlightingConsumer consumer 14 | ) 15 | where TMethodDeclaration : ITreeNode 16 | { 17 | var maxLength = data.SettingsStore.GetValue( 18 | (CleanCodeSettings s) => s.MaximumMethodsInClass 19 | ); 20 | var statementCount = element.CountChildren(); 21 | 22 | if (statementCount <= maxLength) 23 | return; 24 | 25 | var documentRange = declaration.GetDocumentRange(); 26 | var highlighting = new ClassTooBigHighlighting(documentRange, maxLength, statementCount); 27 | consumer.AddHighlighting(highlighting); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Settings; 2 | using JetBrains.ReSharper.Feature.Services.Daemon; 3 | using JetBrains.ReSharper.Psi.Tree; 4 | 5 | namespace CleanCode.Features.MethodNameNotMeaningful; 6 | 7 | public abstract class MethodNameNotMeaningfulCheck : ElementProblemAnalyzer 8 | { 9 | protected static void CheckAndAddHighlighting( 10 | IDeclaration element, 11 | ElementProblemAnalyzerData data, 12 | IHighlightingConsumer consumer 13 | ) 14 | { 15 | if (element == null) 16 | return; 17 | 18 | var minimumMethodNameLength = data.SettingsStore.GetValue( 19 | (CleanCodeSettings s) => s.MinimumMeaningfulMethodNameLength 20 | ); 21 | var name = element.GetText(); 22 | 23 | if (name.Length >= minimumMethodNameLength) 24 | return; 25 | 26 | var documentRange = element.GetNameDocumentRange(); 27 | var highlighting = new MethodNameNotMeaningfulHighlighting(documentRange); 28 | consumer.AddHighlighting(highlighting); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/dotnet/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | Latest 4 | true 5 | false 6 | None 7 | obj\$(MSBuildProjectName)\ 8 | $(DefaultItemExcludes);obj\** 9 | bin\$(MSBuildProjectName)\$(Configuration)\ 10 | 11 | 12 | TRACE;DEBUG;JET_MODE_ASSERT 13 | 14 | 15 | 16 | $(SdkVersion.Substring(2,2))$(SdkVersion.Substring(5,1)).0.0 17 | 18 | 19 | 20 | JetResourceGenerator 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ChainedReferences/ChainedReferencesCheckVb.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Features; 2 | using CleanCode.Settings; 3 | using JetBrains.ReSharper.Feature.Services.Daemon; 4 | using JetBrains.ReSharper.Psi.VB.Tree; 5 | 6 | namespace CleanCode.Features.ChainedReferences 7 | { 8 | [ElementProblemAnalyzer( 9 | typeof(IVBStatement), 10 | HighlightingTypes = new[] { typeof(MaximumChainedReferencesHighlighting) } 11 | )] 12 | public class ChainedReferencesCheckVb : ChainedReferencesCheck 13 | { 14 | protected override void Run( 15 | IVBStatement element, 16 | ElementProblemAnalyzerData data, 17 | IHighlightingConsumer consumer 18 | ) 19 | { 20 | var threshold = data.SettingsStore.GetValue( 21 | (CleanCodeSettings s) => s.MaximumChainedReferences 22 | ); 23 | 24 | var includeLinq = data.SettingsStore.GetValue( 25 | (CleanCodeSettings s) => s.IncludeLinqInChainedReferences 26 | ); 27 | 28 | HighlightMethodChainsThatAreTooLong(element, consumer, threshold, includeLinq); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Resources; 2 | using JetBrains.DocumentModel; 3 | using JetBrains.ReSharper.Feature.Services.Daemon; 4 | using JetBrains.ReSharper.Psi.CSharp; 5 | 6 | namespace CleanCode.Features.FlagArguments 7 | { 8 | [RegisterConfigurableSeverity( 9 | SeverityID, 10 | null, 11 | CleanCodeHighlightingGroupIds.CleanCode, 12 | "Flag argument", 13 | "An argument that is used as a flag.", 14 | Severity.WARNING 15 | )] 16 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] 17 | public class FlagArgumentsHighlighting : IHighlighting 18 | { 19 | internal const string SeverityID = "FlagArgument"; 20 | private readonly DocumentRange _documentRange; 21 | 22 | public FlagArgumentsHighlighting(DocumentRange documentRange) 23 | { 24 | _documentRange = documentRange; 25 | } 26 | 27 | public DocumentRange CalculateRange() => _documentRange; 28 | 29 | public string ToolTip => Warnings.FlagArgument; 30 | 31 | public string ErrorStripeToolTip => ToolTip; 32 | 33 | public bool IsValid() => !string.IsNullOrWhiteSpace(ToolTip); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ChainedReferences/ChainedReferencesCheckCs.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Features; 2 | using CleanCode.Settings; 3 | using JetBrains.ReSharper.Feature.Services.Daemon; 4 | using JetBrains.ReSharper.Psi.CSharp.Tree; 5 | 6 | namespace CleanCode.Features.ChainedReferences 7 | { 8 | [ElementProblemAnalyzer( 9 | typeof(ICSharpStatement), 10 | HighlightingTypes = new[] { typeof(MaximumChainedReferencesHighlighting) } 11 | )] 12 | public class ChainedReferencesCheckCs : ChainedReferencesCheck 13 | { 14 | protected override void Run( 15 | ICSharpStatement element, 16 | ElementProblemAnalyzerData data, 17 | IHighlightingConsumer consumer 18 | ) 19 | { 20 | if (element.CanBeEmbedded) 21 | return; 22 | 23 | var threshold = data.SettingsStore.GetValue( 24 | (CleanCodeSettings s) => s.MaximumChainedReferences 25 | ); 26 | 27 | var includeLinq = data.SettingsStore.GetValue( 28 | (CleanCodeSettings s) => s.IncludeLinqInChainedReferences 29 | ); 30 | 31 | HighlightMethodChainsThatAreTooLong(element, consumer, threshold, includeLinq); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs: -------------------------------------------------------------------------------- 1 | using JetBrains.DocumentModel; 2 | using JetBrains.ReSharper.Feature.Services.Daemon; 3 | using JetBrains.ReSharper.Psi.CSharp; 4 | using JetBrains.ReSharper.Psi.VB; 5 | 6 | namespace CleanCode.Features.HollowNames 7 | { 8 | [RegisterConfigurableSeverity( 9 | SeverityID, 10 | null, 11 | CleanCodeHighlightingGroupIds.CleanCode, 12 | "Hollow type name", 13 | "This type has a name that doesn't express its intent.", 14 | Severity.SUGGESTION 15 | )] 16 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name + "," + VBLanguage.Name)] 17 | public class HollowTypeNameHighlighting : IHighlighting 18 | { 19 | internal const string SeverityID = "HollowTypeName"; 20 | private readonly DocumentRange _documentRange; 21 | 22 | public HollowTypeNameHighlighting(string toolTip, DocumentRange documentRange) 23 | { 24 | ToolTip = toolTip; 25 | _documentRange = documentRange; 26 | } 27 | 28 | public DocumentRange CalculateRange() => _documentRange; 29 | 30 | public string ToolTip { get; } 31 | 32 | public string ErrorStripeToolTip => ToolTip; 33 | 34 | public bool IsValid() => !string.IsNullOrWhiteSpace(ToolTip); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Create 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build: 13 | runs-on: windows-latest 14 | 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | 19 | - name: Install .NET 6 SDK 20 | uses: actions/setup-dotnet@v4 21 | with: 22 | dotnet-version: '6.x' 23 | 24 | - uses: actions/cache@v4 25 | with: 26 | path: | 27 | build/gradle-jvm 28 | ~/.nuget/packages 29 | ~/.gradle/caches 30 | ~/.gradle/wrapper 31 | key: ${{ runner.os }}-Build-${{ hashFiles('gradlew.bat', 'src/dotnet/*/*.csproj', 'src/dotnet/*.props', 'gradle-wrapper.properties') }} 32 | 33 | - name: Build Plugin 34 | run: ./gradlew buildPlugin 35 | 36 | - name: Publish Artifact 37 | uses: actions/upload-artifact@v4.3.3 38 | with: 39 | name: Artifacts 40 | path: output 41 | retention-days: 7 42 | 43 | - name: Publish plugins to jetbrains 44 | shell: cmd 45 | run: ./gradlew publishPlugin -PBuildConfiguration="Release" -PPublishToken="%PublishKey%" 46 | env: 47 | PublishKey: ${{ secrets.PublishKey }} 48 | if: github.event_name != 'pull_request' && github.ref == 'refs/heads/master' -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Resources; 2 | using JetBrains.DocumentModel; 3 | using JetBrains.ReSharper.Feature.Services.Daemon; 4 | using JetBrains.ReSharper.Psi.CSharp; 5 | using JetBrains.ReSharper.Psi.VB; 6 | 7 | namespace CleanCode.Features.MethodNameNotMeaningful 8 | { 9 | [RegisterConfigurableSeverity( 10 | SeverityID, 11 | null, 12 | CleanCodeHighlightingGroupIds.CleanCode, 13 | "Method name not meaningful", 14 | "This method name is too short to be meaningful.", 15 | Severity.WARNING 16 | )] 17 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name + "," + VBLanguage.Name)] 18 | public class MethodNameNotMeaningfulHighlighting : IHighlighting 19 | { 20 | internal const string SeverityID = "MethodNameNotMeaningful"; 21 | private readonly DocumentRange _documentRange; 22 | 23 | public MethodNameNotMeaningfulHighlighting(DocumentRange documentRange) 24 | { 25 | _documentRange = documentRange; 26 | } 27 | 28 | public DocumentRange CalculateRange() => _documentRange; 29 | 30 | public string ToolTip => Warnings.MethodNameNotMeaningful; 31 | 32 | public string ErrorStripeToolTip => ToolTip; 33 | 34 | public bool IsValid() => !string.IsNullOrWhiteSpace(ToolTip); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheckCs.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Settings; 2 | using JetBrains.ReSharper.Feature.Services.Daemon; 3 | using JetBrains.ReSharper.Psi.CSharp.Tree; 4 | using JetBrains.ReSharper.Psi.Tree; 5 | 6 | namespace CleanCode.Features.ExcessiveIndentation 7 | { 8 | [ElementProblemAnalyzer( 9 | typeof(IMethodDeclaration), 10 | HighlightingTypes = new[] { typeof(ExcessiveIndentHighlighting) } 11 | )] 12 | public class ExcessiveIndentationCheckCs : ElementProblemAnalyzer 13 | { 14 | protected override void Run( 15 | IMethodDeclaration element, 16 | ElementProblemAnalyzerData data, 17 | IHighlightingConsumer consumer 18 | ) 19 | { 20 | var maxIndentation = data.SettingsStore.GetValue( 21 | (CleanCodeSettings s) => s.MaximumIndentationDepth 22 | ); 23 | 24 | var childrenDepth = element.GetChildrenDepth(); 25 | if (childrenDepth > maxIndentation) 26 | { 27 | var documentRange = element.GetNameDocumentRange(); 28 | var highlighting = new ExcessiveIndentHighlighting( 29 | documentRange, 30 | maxIndentation, 31 | childrenDepth 32 | ); 33 | consumer.AddHighlighting(highlighting); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheckVb.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Settings; 2 | using JetBrains.ReSharper.Feature.Services.Daemon; 3 | using JetBrains.ReSharper.Psi.Tree; 4 | using JetBrains.ReSharper.Psi.VB.Tree; 5 | 6 | namespace CleanCode.Features.TooManyMethodArguments 7 | { 8 | [ElementProblemAnalyzer( 9 | typeof(IMethodDeclaration), 10 | HighlightingTypes = new[] { typeof(TooManyArgumentsHighlighting) } 11 | )] 12 | public class TooManyMethodArgumentsCheckVb : ElementProblemAnalyzer 13 | { 14 | protected override void Run( 15 | IMethodDeclaration element, 16 | ElementProblemAnalyzerData data, 17 | IHighlightingConsumer consumer 18 | ) 19 | { 20 | var maxParameters = data.SettingsStore.GetValue( 21 | (CleanCodeSettings s) => s.MaximumMethodParameters 22 | ); 23 | var parameterDeclarations = element.ParameterDeclarations; 24 | 25 | var parameterCount = parameterDeclarations.Count; 26 | if (parameterCount > maxParameters) 27 | { 28 | var highlighting = new TooManyArgumentsHighlighting( 29 | element.GetNameDocumentRange(), 30 | maxParameters, 31 | parameterCount 32 | ); 33 | consumer.AddHighlighting(highlighting); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheckCs.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Settings; 2 | using JetBrains.ReSharper.Feature.Services.Daemon; 3 | using JetBrains.ReSharper.Psi.CSharp.Tree; 4 | using JetBrains.ReSharper.Psi.Tree; 5 | 6 | namespace CleanCode.Features.TooManyMethodArguments 7 | { 8 | [ElementProblemAnalyzer( 9 | typeof(IMethodDeclaration), 10 | HighlightingTypes = new[] { typeof(TooManyArgumentsHighlighting) } 11 | )] 12 | public class TooManyMethodArgumentsCheckCs : ElementProblemAnalyzer 13 | { 14 | protected override void Run( 15 | IMethodDeclaration element, 16 | ElementProblemAnalyzerData data, 17 | IHighlightingConsumer consumer 18 | ) 19 | { 20 | var maxParameters = data.SettingsStore.GetValue( 21 | (CleanCodeSettings s) => s.MaximumMethodParameters 22 | ); 23 | var parameterDeclarations = element.ParameterDeclarations; 24 | 25 | var parameterCount = parameterDeclarations.Count; 26 | if (parameterCount > maxParameters) 27 | { 28 | var highlighting = new TooManyArgumentsHighlighting( 29 | element.GetNameDocumentRange(), 30 | maxParameters, 31 | parameterCount 32 | ); 33 | consumer.AddHighlighting(highlighting); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /protocol/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.jetbrains.rd.generator.gradle.RdGenTask 2 | 3 | plugins { 4 | id("org.jetbrains.kotlin.jvm") 5 | id("com.jetbrains.rdgen") version libs.versions.rdGen 6 | } 7 | 8 | dependencies { 9 | implementation(libs.kotlinStdLib) 10 | implementation(libs.rdGen) 11 | implementation( 12 | project( 13 | mapOf( 14 | "path" to ":", 15 | "configuration" to "riderModel" 16 | ) 17 | ) 18 | ) 19 | } 20 | 21 | val DotnetPluginId: String by rootProject 22 | val RiderPluginId: String by rootProject 23 | 24 | rdgen { 25 | val csOutput = File(rootDir, "src/dotnet/${DotnetPluginId}") 26 | val ktOutput = File(rootDir, "src/rider/main/kotlin/com/jetbrains/rider/plugins/${RiderPluginId.replace('.','/').lowercase()}") 27 | 28 | verbose = true 29 | packages = "model.rider" 30 | 31 | generator { 32 | language = "kotlin" 33 | transform = "asis" 34 | root = "com.jetbrains.rider.model.nova.ide.IdeRoot" 35 | namespace = "com.jetbrains.rider.model" 36 | directory = "$ktOutput" 37 | } 38 | 39 | generator { 40 | language = "csharp" 41 | transform = "reversed" 42 | root = "com.jetbrains.rider.model.nova.ide.IdeRoot" 43 | namespace = "JetBrains.Rider.Model" 44 | directory = "$csOutput" 45 | } 46 | } 47 | 48 | tasks.withType { 49 | val classPath = sourceSets["main"].runtimeClasspath 50 | dependsOn(classPath) 51 | classpath(classPath) 52 | } -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using CleanCode.Resources; 3 | using JetBrains.DocumentModel; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp; 6 | using JetBrains.ReSharper.Psi.VB; 7 | 8 | namespace CleanCode.Features.ClassTooBig 9 | { 10 | [RegisterConfigurableSeverity( 11 | SeverityID, 12 | null, 13 | CleanCodeHighlightingGroupIds.CleanCode, 14 | "Class too big", 15 | "This class contains too many methods", 16 | Severity.SUGGESTION 17 | )] 18 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name + "," + VBLanguage.Name)] 19 | public class ClassTooBigHighlighting : IHighlighting 20 | { 21 | internal const string SeverityID = "ClassTooBig"; 22 | 23 | private readonly DocumentRange _documentRange; 24 | 25 | public ClassTooBigHighlighting(DocumentRange documentRange, int threshold, int currentValue) 26 | { 27 | ToolTip = string.Format( 28 | CultureInfo.CurrentCulture, 29 | Warnings.ClassTooBig, 30 | currentValue, 31 | threshold 32 | ); 33 | _documentRange = documentRange; 34 | } 35 | 36 | public DocumentRange CalculateRange() => _documentRange; 37 | 38 | public string ToolTip { get; } 39 | 40 | public string ErrorStripeToolTip => ToolTip; 41 | 42 | public bool IsValid() => !string.IsNullOrWhiteSpace(ToolTip); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/TooManyPublicMethods/TooManyPublicMethodsCheck.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using CleanCode.Settings; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.Tree; 6 | 7 | namespace CleanCode.Features.TooManyPublicMethods 8 | { 9 | public abstract class TooManyPublicMethodsCheck : ElementProblemAnalyzer 10 | { 11 | protected static void CheckIfClassHasTooManyPublicMethods( 12 | ITreeNode declaration, 13 | ITreeNode element, 14 | ElementProblemAnalyzerData data, 15 | IHighlightingConsumer consumer, 16 | Func isPublicMethod 17 | ) 18 | where TMethodDeclaration : ITreeNode 19 | { 20 | var maxPublicMethods = data.SettingsStore.GetValue( 21 | (CleanCodeSettings s) => s.MaximumPublicMethodsInClass 22 | ); 23 | 24 | var publicMethodCount = element 25 | .Children() 26 | .OfType() 27 | .Count(isPublicMethod); 28 | 29 | if (publicMethodCount <= maxPublicMethods) 30 | return; 31 | 32 | var documentRange = declaration.GetDocumentRange(); 33 | var highlighting = new TooManyPublicMethodsHighlighting( 34 | documentRange, 35 | maxPublicMethods, 36 | publicMethodCount 37 | ); 38 | consumer.AddHighlighting(highlighting); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using CleanCode.Resources; 3 | using JetBrains.DocumentModel; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp; 6 | 7 | namespace CleanCode.Features.ExcessiveIndentation 8 | { 9 | [RegisterConfigurableSeverity( 10 | SeverityID, 11 | null, 12 | CleanCodeHighlightingGroupIds.CleanCode, 13 | "Excessive indentation", 14 | "The nesting in this method is excessive.", 15 | Severity.WARNING 16 | )] 17 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] 18 | public class ExcessiveIndentHighlighting : IHighlighting 19 | { 20 | internal const string SeverityID = "ExcessiveIndentation"; 21 | private readonly DocumentRange _documentRange; 22 | 23 | public ExcessiveIndentHighlighting( 24 | DocumentRange documentRange, 25 | int threshold, 26 | int currentValue 27 | ) 28 | { 29 | ToolTip = string.Format( 30 | CultureInfo.CurrentCulture, 31 | Warnings.ExcessiveDepth, 32 | currentValue, 33 | threshold 34 | ); 35 | _documentRange = documentRange; 36 | } 37 | 38 | public DocumentRange CalculateRange() => _documentRange; 39 | 40 | public string ToolTip { get; } 41 | 42 | public string ErrorStripeToolTip => ToolTip; 43 | 44 | public bool IsValid() => !string.IsNullOrWhiteSpace(ToolTip); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using CleanCode.Resources; 3 | using JetBrains.DocumentModel; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp; 6 | using JetBrains.ReSharper.Psi.VB; 7 | 8 | namespace CleanCode.Features.MethodTooLong 9 | { 10 | [RegisterConfigurableSeverity( 11 | SeverityID, 12 | null, 13 | CleanCodeHighlightingGroupIds.CleanCode, 14 | "Method too long", 15 | "The method is bigger than it should be.", 16 | Severity.SUGGESTION 17 | )] 18 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name + "," + VBLanguage.Name)] 19 | public class MethodTooLongHighlighting : IHighlighting 20 | { 21 | internal const string SeverityID = "MethodTooLong"; 22 | private readonly DocumentRange _documentRange; 23 | 24 | public MethodTooLongHighlighting( 25 | DocumentRange documentRange, 26 | int threshold, 27 | int currentValue 28 | ) 29 | { 30 | ToolTip = string.Format( 31 | CultureInfo.CurrentCulture, 32 | Warnings.MethodTooLong, 33 | currentValue, 34 | threshold 35 | ); 36 | _documentRange = documentRange; 37 | } 38 | 39 | public DocumentRange CalculateRange() => _documentRange; 40 | 41 | public string ToolTip { get; } 42 | 43 | public string ErrorStripeToolTip => ToolTip; 44 | 45 | public bool IsValid() => !string.IsNullOrWhiteSpace(ToolTip); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/TooManyDependencies/TooManyDependenciesCheckCs.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using CleanCode.Settings; 3 | using JetBrains.ReSharper.Feature.Services.Daemon; 4 | using JetBrains.ReSharper.Psi.CSharp.Tree; 5 | using JetBrains.ReSharper.Psi.Tree; 6 | using JetBrains.ReSharper.Psi.Util; 7 | 8 | namespace CleanCode.Features.TooManyDependencies 9 | { 10 | [ElementProblemAnalyzer( 11 | typeof(IConstructorDeclaration), 12 | HighlightingTypes = new[] { typeof(TooManyDependenciesHighlighting) } 13 | )] 14 | public class TooManyDependenciesCheckCs : ElementProblemAnalyzer 15 | { 16 | protected override void Run( 17 | IConstructorDeclaration element, 18 | ElementProblemAnalyzerData data, 19 | IHighlightingConsumer consumer 20 | ) 21 | { 22 | var maxDependencies = data.SettingsStore.GetValue( 23 | (CleanCodeSettings s) => s.MaximumConstructorDependencies 24 | ); 25 | var dependencies = element.ParameterDeclarations.Select(declaration => 26 | (declaration.DeclaredElement?.Type).IsInterfaceType() 27 | ); 28 | 29 | var dependenciesCount = dependencies.Count(); 30 | if (dependenciesCount > maxDependencies) 31 | { 32 | var highlighting = new TooManyDependenciesHighlighting( 33 | element.GetNameDocumentRange(), 34 | maxDependencies, 35 | dependenciesCount 36 | ); 37 | consumer.AddHighlighting(highlighting); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/TooManyDependencies/TooManyDependenciesCheckVb.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using CleanCode.Settings; 3 | using JetBrains.ReSharper.Feature.Services.Daemon; 4 | using JetBrains.ReSharper.Psi.Tree; 5 | using JetBrains.ReSharper.Psi.Util; 6 | using JetBrains.ReSharper.Psi.VB.Tree; 7 | 8 | namespace CleanCode.Features.TooManyDependencies 9 | { 10 | [ElementProblemAnalyzer( 11 | typeof(IConstructorDeclaration), 12 | HighlightingTypes = new[] { typeof(TooManyDependenciesHighlighting) } 13 | )] 14 | public class TooManyDependenciesCheckVb : ElementProblemAnalyzer 15 | { 16 | protected override void Run( 17 | IConstructorDeclaration element, 18 | ElementProblemAnalyzerData data, 19 | IHighlightingConsumer consumer 20 | ) 21 | { 22 | var maxDependencies = data.SettingsStore.GetValue( 23 | (CleanCodeSettings s) => s.MaximumConstructorDependencies 24 | ); 25 | var dependencies = element.ParameterDeclarations.Select(declaration => 26 | (declaration.DeclaredElement?.Type).IsInterfaceType() 27 | ); 28 | 29 | var dependenciesCount = dependencies.Count(); 30 | if (dependenciesCount > maxDependencies) 31 | { 32 | var highlighting = new TooManyDependenciesHighlighting( 33 | element.GetNameDocumentRange(), 34 | maxDependencies, 35 | dependenciesCount 36 | ); 37 | consumer.AddHighlighting(highlighting); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using CleanCode.Resources; 3 | using JetBrains.DocumentModel; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp; 6 | using JetBrains.ReSharper.Psi.VB; 7 | 8 | namespace CleanCode.Features.TooManyMethodArguments 9 | { 10 | [RegisterConfigurableSeverity( 11 | SeverityID, 12 | null, 13 | CleanCodeHighlightingGroupIds.CleanCode, 14 | "Too many arguments", 15 | "Too many arguments passed to a method.", 16 | Severity.WARNING 17 | )] 18 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name + "," + VBLanguage.Name)] 19 | public class TooManyArgumentsHighlighting : IHighlighting 20 | { 21 | internal const string SeverityID = "TooManyArguments"; 22 | private readonly DocumentRange _documentRange; 23 | 24 | public TooManyArgumentsHighlighting( 25 | DocumentRange documentRange, 26 | int threshold, 27 | int currentValue 28 | ) 29 | { 30 | ToolTip = string.Format( 31 | CultureInfo.CurrentCulture, 32 | Warnings.TooManyMethodArguments, 33 | currentValue, 34 | threshold 35 | ); 36 | 37 | _documentRange = documentRange; 38 | } 39 | 40 | public DocumentRange CalculateRange() => _documentRange; 41 | 42 | public string ToolTip { get; } 43 | 44 | public string ErrorStripeToolTip => ToolTip; 45 | 46 | public bool IsValid() => !string.IsNullOrWhiteSpace(ToolTip); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using CleanCode.Resources; 3 | using JetBrains.DocumentModel; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp; 6 | using JetBrains.ReSharper.Psi.VB; 7 | 8 | namespace CleanCode.Features.TooManyDependencies 9 | { 10 | [RegisterConfigurableSeverity( 11 | SeverityID, 12 | null, 13 | CleanCodeHighlightingGroupIds.CleanCode, 14 | "Too many dependencies", 15 | "Too many dependencies passed into constructor.", 16 | Severity.WARNING 17 | )] 18 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name + "," + VBLanguage.Name)] 19 | public class TooManyDependenciesHighlighting : IHighlighting 20 | { 21 | internal const string SeverityID = "TooManyDependencies"; 22 | private readonly DocumentRange _documentRange; 23 | 24 | public TooManyDependenciesHighlighting( 25 | DocumentRange documentRange, 26 | int threshold, 27 | int currentValue 28 | ) 29 | { 30 | ToolTip = string.Format( 31 | CultureInfo.CurrentCulture, 32 | Warnings.TooManyDependencies, 33 | currentValue, 34 | threshold 35 | ); 36 | _documentRange = documentRange; 37 | } 38 | 39 | public DocumentRange CalculateRange() => _documentRange; 40 | 41 | public string ToolTip { get; } 42 | 43 | public string ErrorStripeToolTip => ToolTip; 44 | 45 | public bool IsValid() => !string.IsNullOrWhiteSpace(ToolTip); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/MethodTooLong/MethodTooManyDeclarationsHighlighting.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using CleanCode.Resources; 3 | using JetBrains.DocumentModel; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp; 6 | using JetBrains.ReSharper.Psi.VB; 7 | 8 | namespace CleanCode.Features.MethodTooLong 9 | { 10 | [RegisterConfigurableSeverity( 11 | SeverityID, 12 | null, 13 | CleanCodeHighlightingGroupIds.CleanCode, 14 | "Too many Declarations", 15 | "The method has more declarations than there should be.", 16 | Severity.SUGGESTION 17 | )] 18 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name + "," + VBLanguage.Name)] 19 | public class MethodTooManyDeclarationsHighlighting : IHighlighting 20 | { 21 | internal const string SeverityID = "TooManyDeclarations"; 22 | private readonly DocumentRange _documentRange; 23 | 24 | public MethodTooManyDeclarationsHighlighting( 25 | DocumentRange documentRange, 26 | int threshold, 27 | int currentValue 28 | ) 29 | { 30 | ToolTip = string.Format( 31 | CultureInfo.CurrentCulture, 32 | Warnings.TooManyDeclarations, 33 | currentValue, 34 | threshold 35 | ); 36 | _documentRange = documentRange; 37 | } 38 | 39 | public DocumentRange CalculateRange() => _documentRange; 40 | 41 | public string ToolTip { get; } 42 | 43 | public string ErrorStripeToolTip => ToolTip; 44 | 45 | public bool IsValid() => !string.IsNullOrWhiteSpace(ToolTip); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/TooManyPublicMethods/TooManyPublicMethodsHighlighting.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using CleanCode.Resources; 3 | using JetBrains.DocumentModel; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp; 6 | using JetBrains.ReSharper.Psi.VB; 7 | 8 | namespace CleanCode.Features.TooManyPublicMethods 9 | { 10 | [RegisterConfigurableSeverity( 11 | SeverityID, 12 | null, 13 | CleanCodeHighlightingGroupIds.CleanCode, 14 | "Too many public methods", 15 | "This class exposes too many public methods", 16 | Severity.SUGGESTION 17 | )] 18 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name + "," + VBLanguage.Name)] 19 | public class TooManyPublicMethodsHighlighting : IHighlighting 20 | { 21 | internal const string SeverityID = "TooManyPublicMethods"; 22 | 23 | private readonly DocumentRange _documentRange; 24 | 25 | public TooManyPublicMethodsHighlighting( 26 | DocumentRange documentRange, 27 | int threshold, 28 | int currentValue 29 | ) 30 | { 31 | ToolTip = string.Format( 32 | CultureInfo.CurrentCulture, 33 | Warnings.TooManyPublicMethods, 34 | currentValue, 35 | threshold 36 | ); 37 | _documentRange = documentRange; 38 | } 39 | 40 | public DocumentRange CalculateRange() => _documentRange; 41 | 42 | public string ToolTip { get; } 43 | 44 | public string ErrorStripeToolTip => ToolTip; 45 | 46 | public bool IsValid() => !string.IsNullOrWhiteSpace(ToolTip); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /settings.ps1: -------------------------------------------------------------------------------- 1 | $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent 2 | $PluginId = "MO.CleanCode" 3 | $SolutionPath = "$PSScriptRoot\src\dotnet\CleanCode.sln" 4 | $SourceBasePath = "$PSScriptRoot\src\dotnet" 5 | 6 | $VsWhereOutput = [xml] (& "$PSScriptRoot\tools\vswhere.exe" -format xml -products *) 7 | $VisualStudio = $VsWhereOutput.instances.instance | 8 | Where-Object { $_.channelId -match "Release" } | 9 | Sort-Object -Property installationVersion | 10 | Select-Object -Last 1 11 | 12 | $VisualStudioBaseDirectory = $VisualStudio.installationPath 13 | $VisualStudioMajorVersion = ($VisualStudio.installationVersion -split '\.')[0] 14 | $VisualStudioInstanceId = $VisualStudio.instanceId 15 | $DevEnvPath = Get-ChildItem "$VisualStudioBaseDirectory\*\IDE\devenv.exe" 16 | $MSBuildPath = Get-ChildItem "$VisualStudioBaseDirectory\MSBuild\*\Bin\MSBuild.exe" 17 | 18 | $OutputDirectory = "$PSScriptRoot\output" 19 | $NuGetPath = "$PSScriptRoot\tools\nuget.exe" 20 | 21 | Function Invoke-Exe { 22 | param( 23 | [parameter(mandatory=$true,position=0)] [ValidateNotNullOrEmpty()] [string] $Executable, 24 | [Parameter(ValueFromRemainingArguments=$true)][String[]] $Arguments, 25 | [parameter(mandatory=$false)] [array] $ValidExitCodes = @(0) 26 | ) 27 | 28 | Write-Host "> $Executable $Arguments" 29 | $rc = Start-Process -FilePath $Executable -ArgumentList $Arguments -NoNewWindow -Passthru 30 | $rc.Handle # to initialize handle according to https://stackoverflow.com/a/23797762/2684760 31 | $rc.WaitForExit() 32 | if (-Not $ValidExitCodes.Contains($rc.ExitCode)) { 33 | throw "'$Executable $Arguments' failed with exit code $($rc.ExitCode), valid exit codes: $ValidExitCodes" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using CleanCode.Resources; 3 | using JetBrains.DocumentModel; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp; 6 | using JetBrains.ReSharper.Psi.VB; 7 | 8 | namespace CleanCode.Features.ChainedReferences 9 | { 10 | [RegisterConfigurableSeverity( 11 | SeverityID, 12 | null, 13 | CleanCodeHighlightingGroupIds.CleanCode, 14 | "Too many chained references", 15 | "Too many chained references can break the Law of Demeter.", 16 | Severity.WARNING 17 | )] 18 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name + "," + VBLanguage.Name)] 19 | public class MaximumChainedReferencesHighlighting : IHighlighting 20 | { 21 | private const string SeverityID = "TooManyChainedReferences"; 22 | 23 | private readonly DocumentRange _documentRange; 24 | 25 | public MaximumChainedReferencesHighlighting( 26 | DocumentRange documentRange, 27 | int threshold, 28 | int currentValue 29 | ) 30 | { 31 | ToolTip = string.Format( 32 | CultureInfo.CurrentCulture, 33 | Warnings.ChainedReferences, 34 | currentValue, 35 | threshold 36 | ); 37 | 38 | _documentRange = documentRange; 39 | } 40 | 41 | public DocumentRange CalculateRange() => _documentRange; 42 | 43 | public string ToolTip { get; } 44 | 45 | public string ErrorStripeToolTip => ToolTip; 46 | 47 | public bool IsValid() => !string.IsNullOrWhiteSpace(ToolTip); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using CleanCode.Resources; 3 | using JetBrains.DocumentModel; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.CSharp; 6 | using JetBrains.ReSharper.Psi.VB; 7 | 8 | namespace CleanCode.Features.ComplexExpression 9 | { 10 | [RegisterConfigurableSeverity( 11 | SeverityID, 12 | null, 13 | CleanCodeHighlightingGroupIds.CleanCode, 14 | "Condition expression too complex", 15 | "The expression in the condition is too complex.", 16 | Severity.WARNING 17 | )] 18 | [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name + "," + VBLanguage.Name)] 19 | public class ComplexConditionExpressionHighlighting : IHighlighting 20 | { 21 | internal const string SeverityID = "ComplexConditionExpression"; 22 | 23 | private readonly DocumentRange _documentRange; 24 | 25 | public ComplexConditionExpressionHighlighting( 26 | DocumentRange documentRange, 27 | int threshold, 28 | int currentValue 29 | ) 30 | { 31 | ToolTip = string.Format( 32 | CultureInfo.CurrentCulture, 33 | Warnings.ExpressionTooComplex, 34 | currentValue, 35 | threshold 36 | ); 37 | _documentRange = documentRange; 38 | } 39 | 40 | public DocumentRange CalculateRange() => _documentRange; 41 | 42 | public string ToolTip { get; } 43 | 44 | public string ErrorStripeToolTip => ToolTip; 45 | 46 | public bool IsValid() => !string.IsNullOrWhiteSpace(ToolTip); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/dotnet/MO.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 | -------------------------------------------------------------------------------- /src/dotnet/CleanCode.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.329 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanCode", "MO.CleanCode\MO.CleanCode.csproj", "{75D73FB6-B8EC-413B-86A9-566A58E1BE4F}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanCode.Rider", "MO.CleanCode\MO.CleanCode.Rider.csproj", "{084172D1-A9C6-46D0-96AD-05C5B09A5E5D}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "misc", "misc", "{4A9ABB95-3762-448B-B5BF-099E46DB22DE}" 11 | ProjectSection(SolutionItems) = preProject 12 | rider\main\resources\META-INF\plugin.xml = rider\main\resources\META-INF\plugin.xml 13 | Plugin.props = Plugin.props 14 | README.md = ..\README.md 15 | EndProjectSection 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|Any CPU = Debug|Any CPU 20 | Release|Any CPU = Release|Any CPU 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {75D73FB6-B8EC-413B-86A9-566A58E1BE4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {75D73FB6-B8EC-413B-86A9-566A58E1BE4F}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {75D73FB6-B8EC-413B-86A9-566A58E1BE4F}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {75D73FB6-B8EC-413B-86A9-566A58E1BE4F}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {084172D1-A9C6-46D0-96AD-05C5B09A5E5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {084172D1-A9C6-46D0-96AD-05C5B09A5E5D}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {084172D1-A9C6-46D0-96AD-05C5B09A5E5D}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {084172D1-A9C6-46D0-96AD-05C5B09A5E5D}.Release|Any CPU.Build.0 = Release|Any CPU 31 | EndGlobalSection 32 | GlobalSection(SolutionProperties) = preSolution 33 | HideSolutionNode = FALSE 34 | EndGlobalSection 35 | GlobalSection(ExtensibilityGlobals) = postSolution 36 | SolutionGuid = {FC3F5149-307B-428E-B054-6D5767D05BD8} 37 | EndGlobalSection 38 | EndGlobal 39 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/HollowNames/HollowNamesCheck.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using CleanCode.Resources; 6 | using CleanCode.Settings; 7 | using JetBrains.Application.Settings; 8 | using JetBrains.ReSharper.Feature.Services.Daemon; 9 | using JetBrains.ReSharper.Psi.Tree; 10 | 11 | namespace CleanCode.Features.HollowNames; 12 | 13 | public abstract class HollowNamesCheck : ElementProblemAnalyzer 14 | { 15 | private static readonly string[] Separator = { "," }; 16 | 17 | protected static void CheckAndAddHighlighting( 18 | IDeclaration element, 19 | ElementProblemAnalyzerData data, 20 | IHighlightingConsumer consumer 21 | ) 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 static string[] GetSuffixes(IContextBoundSettingsStore dataSettingsStore) 31 | { 32 | var suffixes = dataSettingsStore.GetValue( 33 | (CleanCodeSettings s) => s.MeaninglessClassNameSuffixes 34 | ); 35 | return suffixes.Split(Separator, StringSplitOptions.RemoveEmptyEntries); 36 | } 37 | 38 | private static string GetFirstMatchOrDefault(string declaredName, IEnumerable suffixes) 39 | { 40 | return suffixes.FirstOrDefault(declaredName.EndsWith); 41 | } 42 | 43 | private static void AddHighlighting( 44 | string bannedSuffix, 45 | IHighlightingConsumer consumer, 46 | ITreeNode treeNode 47 | ) 48 | { 49 | var documentRange = treeNode.GetDocumentRange(); 50 | var toolTip = string.Format( 51 | CultureInfo.CurrentCulture, 52 | Warnings.HollowTypeName, 53 | bannedSuffix 54 | ); 55 | var highlighting = new HollowTypeNameHighlighting(toolTip, documentRange); 56 | consumer.AddHighlighting(highlighting); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/dotnet/MO.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, nameof(MaximumConstructorDependencies))] 10 | public int MaximumConstructorDependencies { get; set; } 11 | 12 | [SettingsEntry(3, nameof(MaximumMethodParameters))] 13 | public int MaximumMethodParameters { get; set; } 14 | 15 | [SettingsEntry(15, nameof(MaximumMethodStatements))] 16 | public int MaximumMethodStatements { get; set; } 17 | 18 | [SettingsEntry(6, nameof(MaximumDeclarationsInMethod))] 19 | public int MaximumDeclarationsInMethod { get; set; } 20 | 21 | [SettingsEntry(3, nameof(MaximumIndentationDepth))] 22 | public int MaximumIndentationDepth { get; set; } 23 | 24 | [SettingsEntry(20, nameof(MaximumMethodsInClass))] 25 | public int MaximumMethodsInClass { get; set; } 26 | 27 | [SettingsEntry(2, nameof(MaximumChainedReferences))] 28 | public int MaximumChainedReferences { get; set; } 29 | 30 | [SettingsEntry(4, nameof(MinimumMeaningfulMethodNameLength))] 31 | public int MinimumMeaningfulMethodNameLength { get; set; } 32 | 33 | [SettingsEntry( 34 | "Handler,Manager,Processor,Controller,Helper", 35 | nameof(MeaninglessClassNameSuffixes) 36 | )] 37 | public string MeaninglessClassNameSuffixes { get; set; } 38 | 39 | [SettingsEntry(1, nameof(MaximumExpressionsInCondition))] 40 | public int MaximumExpressionsInCondition { get; set; } 41 | 42 | [SettingsEntry(true, nameof(IsFlagAnalysisEnabled))] 43 | public bool IsFlagAnalysisEnabled { get; set; } 44 | 45 | [SettingsEntry(15, nameof(MaximumPublicMethodsInClass))] 46 | public int MaximumPublicMethodsInClass { get; set; } 47 | 48 | [SettingsEntry(false, nameof(IncludeLinqInChainedReferences))] 49 | public bool IncludeLinqInChainedReferences { get; set; } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/MO.CleanCode.Rider.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net472 4 | MO.CleanCode 5 | CleanCode 6 | false 7 | false 8 | CleanCode.ruleset 9 | 10 | 11 | 16 | 17 | all 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | True 30 | True 31 | Settings.resx 32 | 33 | 34 | True 35 | True 36 | Warnings.resx 37 | 38 | 39 | 40 | 41 | ResXFileCodeGenerator 42 | Settings.Designer.cs 43 | 44 | 45 | ResXFileCodeGenerator 46 | Warnings.Designer.cs 47 | 48 | 49 | 50 | 51 | Designer 52 | MSBuild:Compile 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/MO.CleanCode.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net472 4 | MO.CleanCode 5 | CleanCode 6 | false 7 | CleanCode.ruleset 8 | 9 | 10 | 15 | 16 | all 17 | runtime; build; native; contentfiles; analyzers; buildtransitive 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | True 31 | True 32 | Settings.resx 33 | 34 | 35 | True 36 | True 37 | Warnings.resx 38 | 39 | 40 | 41 | 42 | ResXFileCodeGenerator 43 | Settings.Designer.cs 44 | 45 | 46 | ResXFileCodeGenerator 47 | Warnings.Designer.cs 48 | 49 | 50 | 51 | 52 | Designer 53 | MSBuild:Compile 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Clean Code ReSharper Plugin Project 2 | 3 | [![Build Status](https://github.com/MO2k4/CleanCode/actions/workflows/main.yml/badge.svg)](https://github.com/MO2k4/CleanCode/actions/workflows/main.yml) 4 | [![Rider](https://img.shields.io/jetbrains/plugin/v/12924-cleancode?label=Rider)](https://plugins.jetbrains.com/plugin/12924-cleancode) 5 | [![ReSharper](https://img.shields.io/resharper/v/MO.CleanCode?label=ReSharper)](https://plugins.jetbrains.com/plugin/11677-cleancode) 6 | 7 | ### CleanCode 8 | 9 | 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). 10 | 11 | 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: 12 | 13 | * **Too many dependencies** - warns when a constructor has too many interfaces passed in. 14 | * **Excessive indentation** - warns if a class contains members with too much indentation. 15 | * **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. 16 | * **Method too long** - warns when a method contains too many statements. 17 | * **Class too big** - warns if a class has too many method declarations. 18 | * **Too many method parameters** - warns if a method has too many parameters. 19 | * **Method name not meaningful** - simple check that a method name is longer than a certain threshold. 20 | * **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. 21 | * **Condition complexity** - warns if the condition in an `if` statement contains too many expressions. 22 | * **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. 23 | 24 | The limits used by each analysis are configurable in the options page. 25 | 26 | ### Upcoming features 27 | 28 | Please log feature requests and bugs in [Issues](https://github.com/MO2k4/CleanCode/issues). Note that this version only supports C# and VB.Net. 29 | 30 | ## Installing 31 | 32 | Install from ReSharper → Extension Manager. 33 | 34 | ## Groundwork 35 | 36 | This project is a fork from [Hadi Hariri](https://github.com/hhariri/CleanCode) work. 37 | 38 | ## License 39 | 40 | Licensed under MIT (c) 2012 - 2017 Hadi Hariri and Contributors 41 | 42 | 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) 43 | -------------------------------------------------------------------------------- /src/rider/main/resources/META-INF/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | MO.CleanCode-rider 3 | CleanCode 4 | _PLACEHOLDER_ 5 | Github CleanCode 6 | 7 | com.intellij.modules.rider 8 | 9 | 10 | An experiment in trying to automate some of concepts described in Uncle Bob's books on Clean Code.

12 |

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:

13 |
    14 |
  • Too many dependencies - warns when a constructor has too many interfaces passed in.
  • 15 |
  • Excessive indentation - warns if a class contains members with too much indentation.
  • 16 |
  • Too many chained references - warns if an expression has too many chained statements, is potentially violating the 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.
  • 17 |
  • Method too long - warns when a method contains too many statements.
  • 18 |
  • Class too big - warns if a class has too many method declarations.
  • 19 |
  • Too many method parameters - warns if a method has too many parameters.
  • 20 |
  • Method name not meaningful - simple check that a method name is longer than a certain threshold.
  • 21 |
  • 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.
  • 22 |
  • Condition complexity - warns if the condition in an if statement contains too many expressions.
  • 23 |
  • 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.
  • 24 |
25 | ]]> 26 |
27 | 28 | messages.CleanCodeBundle 29 | 30 | 31 | 37 | 38 |
-------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheckCs.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using CleanCode.Settings; 3 | using JetBrains.ReSharper.Feature.Services.Daemon; 4 | using JetBrains.ReSharper.Psi.CSharp.Tree; 5 | using JetBrains.ReSharper.Psi.Tree; 6 | 7 | namespace CleanCode.Features.ComplexExpression 8 | { 9 | [ElementProblemAnalyzer( 10 | typeof(IIfStatement), 11 | typeof(ILoopWithConditionStatement), 12 | typeof(IConditionalTernaryExpression), 13 | typeof(IAssignmentExpression), 14 | typeof(IExpressionInitializer), 15 | HighlightingTypes = new[] { typeof(ComplexConditionExpressionHighlighting) } 16 | )] 17 | public class ComplexConditionExpressionCheckCs : ElementProblemAnalyzer 18 | { 19 | protected override void Run( 20 | ICSharpTreeNode element, 21 | ElementProblemAnalyzerData data, 22 | IHighlightingConsumer consumer 23 | ) 24 | { 25 | var expression = GetExpression(element); 26 | if (expression != null) 27 | CheckExpression(expression, data, consumer); 28 | } 29 | 30 | private static IExpression GetExpression(ITreeNode node) 31 | { 32 | switch (node) 33 | { 34 | case ILoopWithConditionStatement loopWithConditionStatement: 35 | return loopWithConditionStatement.Condition; 36 | case IIfStatement ifStatement: 37 | return ifStatement.Condition; 38 | case IConditionalTernaryExpression conditionalTernaryExpression: 39 | return conditionalTernaryExpression.ConditionOperand; 40 | case IAssignmentExpression assignmentExpression: 41 | return assignmentExpression.Source; 42 | case IExpressionInitializer expressionInitializer: 43 | return expressionInitializer.Value; 44 | default: 45 | return null; 46 | } 47 | } 48 | 49 | private static void CheckExpression( 50 | IExpression expression, 51 | ElementProblemAnalyzerData data, 52 | IHighlightingConsumer consumer 53 | ) 54 | { 55 | var maxExpressions = data.SettingsStore.GetValue( 56 | (CleanCodeSettings s) => s.MaximumExpressionsInCondition 57 | ); 58 | var expressionCount = expression.GetChildrenRecursive().Count(); 59 | 60 | if (expressionCount > maxExpressions) 61 | { 62 | var documentRange = expression.GetDocumentRange(); 63 | var highlighting = new ComplexConditionExpressionHighlighting( 64 | documentRange, 65 | maxExpressions, 66 | expressionCount 67 | ); 68 | consumer.AddHighlighting(highlighting); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## 5.6.21 9 | 10 | - Add new configuration for flag analysis 11 | 12 | ## 5.6.20 13 | 14 | - Updated to SDK-Version 2021.2.1 15 | 16 | ## 5.6.19 17 | 18 | - Updated to SDK-Version 2020.3.2 19 | 20 | ## 5.6.18 21 | 22 | - Updated to Sdk-Version 2020.2.0 23 | 24 | ## 5.6.17 25 | 26 | - Updated to Sdk-Version 2020.1.3 27 | 28 | ## 5.6.16 29 | 30 | - Updated to Sdk-Version 2020.1.0 31 | 32 | ## 5.6.15 33 | 34 | - Updated to Sdk-Version 2019.3.4 35 | 36 | ## 5.6.14 37 | 38 | - Updated to Sdk-Version 2019.3.2 39 | 40 | ## 5.6.13 41 | 42 | - Updated to Sdk-Version 2019.3.1 43 | 44 | ## 5.6.12 45 | 46 | - Updated to Sdk-Version 2019.3.0 47 | 48 | ## 5.6.11 49 | 50 | - Updated to Sdk-Version 2019.2.3 51 | 52 | ## 5.6.10 53 | 54 | - Updated to Sdk-Version 2019.2.2 55 | 56 | ## 5.6.9 57 | 58 | - Changed SettingsDialog 59 | 60 | ## 5.6.8 61 | 62 | - Added JetBrains Rider Support 63 | 64 | ## 5.6.7 65 | 66 | - Updated to ReSharper 2019.2.1 67 | 68 | ## 5.6.6 69 | 70 | - Updated to ReSharper 2019.1.1 71 | 72 | ## 5.6.5 73 | 74 | - Updated to ReSharper 2019.1 75 | 76 | ## 5.6.4 77 | 78 | - Updated to ReSharper 2018.3.4 79 | 80 | ## 5.6.3 81 | 82 | - Updated to ReSharper 2018.3.3 83 | - Changed project structure to .Net-Core 84 | 85 | ## 5.6.1 86 | 87 | - Updated to ReSharper 2018.3.2W 88 | 89 | ## 5.6.1 90 | 91 | - Updated to ReSharper 2018.3.1 92 | 93 | ## 5.6.0 94 | 95 | - Updated to ReSharper 2018.3 96 | 97 | ## 5.5.0 98 | 99 | - Updated to ReSharper 2018.2 100 | 101 | ## 5.4.0 102 | 103 | - Updated to ReSharper 2018.1 104 | 105 | ## 5.3.3 106 | 107 | - Highlighting CurrentValue/Threshold in Message 108 | - Added VB.Net Support 109 | 110 | ## 5.3.0 111 | 112 | - Updated to ReSharper 2017.3 113 | 114 | ## 5.2.0 115 | 116 | - Updated to ReSharper 2017.2 117 | 118 | ## 5.1.0 119 | 120 | - Updated to ReSharper 2017.1 121 | 122 | ## 5.0.3 123 | 124 | - Stop marking abstract methods too long (#19) 125 | 126 | ## 5.0.2 127 | 128 | - Method parameter and type parameter declarations mistakenly used for "method too long" check (#12) 129 | 130 | ## 5.0.1 131 | 132 | - Updated to ReSharper 2016.2 133 | - Fix minor installer issue 134 | 135 | ## 4.0.0 136 | 137 | - Warning if a method uses flag parameters 138 | - Warning if a method contains too many nested blocks 139 | - Warning if a method name is too short to be meaningful 140 | - Warning if an epression is breaking the Law of Demeter 141 | - Warning if a constructor has too many parameters, indicating too many dependencies 142 | - Warning if a method has too many arguments 143 | - Suggestion highlight if class has too many methods 144 | - Suggestion highlight if method has too many statements 145 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheckVb.cs: -------------------------------------------------------------------------------- 1 | using CleanCode.Extension; 2 | using CleanCode.Settings; 3 | using JetBrains.ReSharper.Feature.Services.Daemon; 4 | using JetBrains.ReSharper.Psi.Tree; 5 | using JetBrains.ReSharper.Psi.VB.Tree; 6 | 7 | namespace CleanCode.Features.ComplexExpression 8 | { 9 | [ElementProblemAnalyzer( 10 | typeof(IBlockIfStatement), 11 | typeof(IElseIfStatement), 12 | typeof(IWhileStatement), 13 | typeof(IForEachStatement), 14 | typeof(IForStatement), 15 | typeof(IConditionalExpression), 16 | typeof(IExpressionStatement), 17 | typeof(ILineIfStatement), 18 | HighlightingTypes = new[] { typeof(ComplexConditionExpressionHighlighting) } 19 | )] 20 | public class ComplexConditionExpressionCheckVb : ElementProblemAnalyzer 21 | { 22 | protected override void Run( 23 | IVBTreeNode element, 24 | ElementProblemAnalyzerData data, 25 | IHighlightingConsumer consumer 26 | ) 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 | switch (node) 36 | { 37 | case IBlockIfStatement blockIfStatement: 38 | return blockIfStatement.Expression; 39 | case IElseIfStatement elseIfStatement: 40 | return elseIfStatement.Expression; 41 | case IWhileStatement whileStatement: 42 | return whileStatement.Expression; 43 | case IForEachStatement forEachStatement: 44 | return forEachStatement.Expression; 45 | case IForStatement forStatement: 46 | return forStatement.StepExpression; 47 | case IConditionalExpression conditionalExpression: 48 | return conditionalExpression.Condition; 49 | case IExpressionStatement expressionStatement: 50 | return expressionStatement.Expression; 51 | case ILineIfStatement lineIfStatement: 52 | return lineIfStatement.Expression; 53 | default: 54 | return null; 55 | } 56 | } 57 | 58 | private static void CheckExpression( 59 | IExpression expression, 60 | ElementProblemAnalyzerData data, 61 | IHighlightingConsumer consumer 62 | ) 63 | { 64 | var maxExpressions = data.SettingsStore.GetValue( 65 | (CleanCodeSettings s) => s.MaximumExpressionsInCondition 66 | ); 67 | var expressionCount = GetExpressionCount(expression); 68 | 69 | if (expressionCount > maxExpressions) 70 | { 71 | var documentRange = expression.GetDocumentRange(); 72 | var highlighting = new ComplexConditionExpressionHighlighting( 73 | documentRange, 74 | maxExpressions, 75 | expressionCount 76 | ); 77 | consumer.AddHighlighting(highlighting); 78 | } 79 | } 80 | 81 | private static int GetExpressionCount(IExpression expression) 82 | { 83 | return expression.GetExpressionCount() 84 | + expression.GetExpressionCount() 85 | + expression.GetExpressionCount(); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/FlagArguments/FlagArgumentsCheckCs.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using CleanCode.Settings; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi; 6 | using JetBrains.ReSharper.Psi.CSharp.Tree; 7 | using JetBrains.ReSharper.Psi.Tree; 8 | using JetBrains.ReSharper.Psi.Util; 9 | 10 | namespace CleanCode.Features.FlagArguments 11 | { 12 | [ElementProblemAnalyzer( 13 | typeof(IMethodDeclaration), 14 | HighlightingTypes = new[] { typeof(FlagArgumentsHighlighting) } 15 | )] 16 | public class FlagArgumentsCheckCs : ElementProblemAnalyzer 17 | { 18 | protected override void Run( 19 | IMethodDeclaration element, 20 | ElementProblemAnalyzerData data, 21 | IHighlightingConsumer consumer 22 | ) 23 | { 24 | var isFlagAnalysisEnabled = data.SettingsStore.GetValue( 25 | (CleanCodeSettings s) => s.IsFlagAnalysisEnabled 26 | ); 27 | if (!isFlagAnalysisEnabled) 28 | return; 29 | 30 | var parameterDeclarations = element.ParameterDeclarations.Where(parameterDeclaration => 31 | IsFlagArgument(parameterDeclaration, element.Body) 32 | ); 33 | 34 | foreach (var parameterDeclaration in parameterDeclarations) 35 | AddHighlighting(consumer, parameterDeclaration); 36 | } 37 | 38 | private static bool IsFlagArgument( 39 | ITypeOwnerDeclaration typeOwnerDeclaration, 40 | ITreeNode node 41 | ) 42 | { 43 | return IsOfTypeThatCanBeUsedAsFlag(typeOwnerDeclaration) 44 | && GetReferencesTo(typeOwnerDeclaration.DeclaredElement, node).Any(); 45 | } 46 | 47 | private static bool IsOfTypeThatCanBeUsedAsFlag(ITypeOwnerDeclaration arg) 48 | { 49 | var type = arg.Type; 50 | return type.IsBool() || type.IsEnumType(); 51 | } 52 | 53 | private static IEnumerable GetReferencesTo( 54 | IDeclaredElement declaredElement, 55 | ITreeNode body 56 | ) 57 | { 58 | var ifStatements = body.GetChildrenRecursive(); 59 | var allConditions = ifStatements.Select(statement => statement.Condition); 60 | var allReferencesInConditions = allConditions.SelectMany(expression => 61 | expression.GetFlattenedHierarchyOfType() 62 | ); 63 | 64 | return GetReferencesToArgument(allReferencesInConditions, declaredElement); 65 | } 66 | 67 | private static IEnumerable GetReferencesToArgument( 68 | IEnumerable allReferencesInConditions, 69 | IDeclaredElement declaredElementInArgument 70 | ) 71 | { 72 | return allReferencesInConditions.Where(reference => 73 | IsReferenceToArgument(reference, declaredElementInArgument) 74 | ); 75 | } 76 | 77 | private static bool IsReferenceToArgument( 78 | IReferenceExpression referenceExpression, 79 | IDeclaredElement toFind 80 | ) 81 | { 82 | if (referenceExpression == null) 83 | { 84 | return false; 85 | } 86 | 87 | var resolveResultWithInfo = referenceExpression.Reference.GetResolveResult(); 88 | var declaredElement = resolveResultWithInfo.DeclaredElement; 89 | 90 | return declaredElement != null && declaredElement.ShortName == toFind.ShortName; 91 | } 92 | 93 | private static void AddHighlighting( 94 | IHighlightingConsumer consumer, 95 | ICSharpParameterDeclaration parameterDeclaration 96 | ) 97 | { 98 | var documentRange = parameterDeclaration.GetDocumentRange(); 99 | var highlighting = new FlagArgumentsHighlighting(documentRange); 100 | consumer.AddHighlighting(highlighting); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using CleanCode.Settings; 3 | using JetBrains.Annotations; 4 | using JetBrains.ReSharper.Feature.Services.Daemon; 5 | using JetBrains.ReSharper.Psi.Tree; 6 | 7 | namespace CleanCode.Features.MethodTooLong; 8 | 9 | public abstract class MethodTooLongCheck : ElementProblemAnalyzer 10 | { 11 | protected static void CheckAndAddHighlight( 12 | TMethodDeclaration element, 13 | ElementProblemAnalyzerData data, 14 | IHighlightingConsumer consumer 15 | ) 16 | where TMethodDeclaration : IDeclaration 17 | { 18 | var highlighting = GetHighlighting(element, data); 19 | if (highlighting != null) 20 | consumer.AddHighlighting(highlighting); 21 | } 22 | 23 | private static IHighlighting GetHighlighting( 24 | TMethodDeclaration element, 25 | ElementProblemAnalyzerData data 26 | ) 27 | where TMethodDeclaration : IDeclaration 28 | { 29 | var maxStatements = data.SettingsStore.GetValue( 30 | (CleanCodeSettings s) => s.MaximumMethodStatements 31 | ); 32 | var maxDeclarations = data.SettingsStore.GetValue( 33 | (CleanCodeSettings s) => s.MaximumDeclarationsInMethod 34 | ); 35 | 36 | var highlight = CheckStatementCount(element, maxStatements); 37 | if (highlight != null) 38 | return highlight; 39 | 40 | return element switch 41 | { 42 | JetBrains.ReSharper.Psi.CSharp.Tree.IMethodDeclaration declaration => 43 | CheckDeclarationCount(declaration, maxDeclarations), 44 | JetBrains.ReSharper.Psi.VB.Tree.IMethodDeclaration declaration => CheckDeclarationCount( 45 | declaration, 46 | maxDeclarations 47 | ), 48 | _ => throw new ArgumentOutOfRangeException(nameof(element), element, null), 49 | }; 50 | } 51 | 52 | [CanBeNull] 53 | private static MethodTooLongHighlighting CheckStatementCount( 54 | IDeclaration element, 55 | int maxStatements 56 | ) 57 | { 58 | var statementCount = element.CountChildren(); 59 | return statementCount > maxStatements 60 | ? new MethodTooLongHighlighting( 61 | element.GetNameDocumentRange(), 62 | maxStatements, 63 | statementCount 64 | ) 65 | : null; 66 | } 67 | 68 | [CanBeNull] 69 | private static MethodTooManyDeclarationsHighlighting CheckDeclarationCount( 70 | JetBrains.ReSharper.Psi.CSharp.Tree.IMethodDeclaration element, 71 | int maxDeclarations 72 | ) 73 | { 74 | // Only look in the method body for declarations, otherwise we see 75 | // parameters + type parameters. We can ignore arrow expressions, as 76 | // they must be a single expression and won't have declarations 77 | var declarationCount = element.Body?.CountChildren() ?? 0; 78 | return declarationCount > maxDeclarations 79 | ? new MethodTooManyDeclarationsHighlighting( 80 | element.GetNameDocumentRange(), 81 | maxDeclarations, 82 | declarationCount 83 | ) 84 | : null; 85 | } 86 | 87 | [CanBeNull] 88 | private static MethodTooManyDeclarationsHighlighting CheckDeclarationCount( 89 | JetBrains.ReSharper.Psi.VB.Tree.IMethodDeclaration element, 90 | int maxDeclarations 91 | ) 92 | { 93 | // Only look in the method body for declarations, otherwise we see 94 | // parameters + type parameters. We can ignore arrow expressions, as 95 | // they must be a single expression and won't have declarations 96 | var declarationCount = element.Block?.CountChildren() ?? 0; 97 | return declarationCount > maxDeclarations 98 | ? new MethodTooManyDeclarationsHighlighting( 99 | element.GetNameDocumentRange(), 100 | maxDeclarations, 101 | declarationCount 102 | ) 103 | : null; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using CleanCode.Features; 3 | using JetBrains.ReSharper.Feature.Services.Daemon; 4 | using JetBrains.ReSharper.Psi; 5 | using JetBrains.ReSharper.Psi.Tree; 6 | using JetBrains.ReSharper.Psi.VB.Tree; 7 | 8 | namespace CleanCode.Features.ChainedReferences; 9 | 10 | public abstract class ChainedReferencesCheck : ElementProblemAnalyzer 11 | { 12 | protected static void HighlightMethodChainsThatAreTooLong( 13 | ITreeNode statement, 14 | IHighlightingConsumer consumer, 15 | int threshold, 16 | bool includeLinq = false 17 | ) 18 | { 19 | var children = statement.Children(); 20 | 21 | foreach (var treeNode in children) 22 | { 23 | if (treeNode is IReferenceExpression referenceExpression) 24 | { 25 | HighlightReferenceExpressionIfNeeded( 26 | referenceExpression, 27 | consumer, 28 | threshold, 29 | includeLinq 30 | ); 31 | } 32 | else 33 | { 34 | HighlightMethodChainsThatAreTooLong(treeNode, consumer, threshold, includeLinq); 35 | } 36 | } 37 | } 38 | 39 | private static void HighlightReferenceExpressionIfNeeded( 40 | IReferenceExpression referenceExpression, 41 | IHighlightingConsumer consumer, 42 | int threshold, 43 | bool includeLinq 44 | ) 45 | { 46 | var types = new HashSet(); 47 | 48 | var nextReferenceExpression = referenceExpression; 49 | var chainLength = 0; 50 | 51 | while (nextReferenceExpression != null) 52 | { 53 | // Skip LINQ methods if not including them in the count 54 | if (!includeLinq && IsLinqMethod(nextReferenceExpression)) 55 | { 56 | nextReferenceExpression = ExtensionMethodsVb.TryGetFirstReferenceExpression( 57 | nextReferenceExpression 58 | ); 59 | continue; 60 | } 61 | 62 | var childReturnType = ExtensionMethodsCsharp.TryGetClosedReturnTypeFrom( 63 | nextReferenceExpression 64 | ); 65 | 66 | if (childReturnType != null) 67 | { 68 | types.Add(childReturnType); 69 | chainLength++; 70 | } 71 | 72 | nextReferenceExpression = ExtensionMethodsVb.TryGetFirstReferenceExpression( 73 | nextReferenceExpression 74 | ); 75 | nextReferenceExpression = ExtensionMethodsVb.TryGetFirstReferenceExpression( 76 | nextReferenceExpression 77 | ); 78 | } 79 | 80 | var isFluentChain = types.Count == 1; 81 | if (!isFluentChain && chainLength > threshold) 82 | { 83 | AddHighlighting(referenceExpression, consumer, threshold, chainLength); 84 | } 85 | } 86 | 87 | private static bool IsLinqMethod(IReferenceExpression expression) 88 | { 89 | if (expression == null) 90 | return false; 91 | 92 | var reference = expression.Reference; 93 | var resolveResult = reference.Resolve(); 94 | var declaredElement = resolveResult.DeclaredElement; 95 | 96 | // Check if it's a method in the System.Linq namespace 97 | if (declaredElement is IMethod method) 98 | { 99 | var containingType = method.GetContainingType(); 100 | if (containingType == null) 101 | return false; 102 | 103 | var ns = containingType.GetContainingNamespace(); 104 | return ns != null && ns.QualifiedName.Contains("System.Linq"); 105 | } 106 | 107 | return false; 108 | } 109 | 110 | private static void AddHighlighting( 111 | IReferenceExpression reference, 112 | IHighlightingConsumer consumer, 113 | int threshold, 114 | int currentValue 115 | ) 116 | { 117 | var nameIdentifier = reference.NameIdentifier; 118 | var documentRange = nameIdentifier.GetDocumentRange(); 119 | var highlighting = new MaximumChainedReferencesHighlighting( 120 | documentRange, 121 | threshold, 122 | currentValue 123 | ); 124 | consumer.AddHighlighting(highlighting); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /runVisualStudio.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | $RootSuffix = "CognitiveComplexity", 3 | $Version = "9999.0.0" 4 | ) 5 | 6 | Set-StrictMode -Version Latest 7 | $ErrorActionPreference = "Stop" 8 | $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent 9 | Set-Location $PSScriptRoot 10 | 11 | . ".\settings.ps1" 12 | 13 | $UserProjectXmlFile = "$SourceBasePath\$PluginId\$PluginId.csproj.user" 14 | 15 | if (!(Test-Path "$UserProjectXmlFile")) { 16 | # Get versions from Plugin.props file 17 | $PluginPropsFile = "$SourceBasePath\Plugin.props" 18 | $PluginPropsXml = [xml] (Get-Content "$PluginPropsFile") 19 | $SdkVersionNode = $PluginPropsXml.SelectSingleNode(".//SdkVersion") 20 | $VersionSplit = $SdkVersionNode.InnerText.Split(".") 21 | $MajorVersion = "$($VersionSplit[0]).$($VersionSplit[1])" 22 | 23 | # Determine download link 24 | $ReleaseUrl = "https://data.services.jetbrains.com/products/releases?code=RSU&type=eap&type=release&majorVersion=$MajorVersion" 25 | $VersionEntry = $(Invoke-WebRequest -UseBasicParsing $ReleaseUrl | ConvertFrom-Json).RSU[0] 26 | ## TODO: check versions 27 | $DownloadLink = [uri] ($VersionEntry.downloads.windows.link.replace(".exe", ".Checked.exe")) 28 | 29 | # Download installer 30 | $InstallerFile = "$PSScriptRoot\build\installer\$($DownloadLink.Segments[-1])" 31 | if (!(Test-Path $InstallerFile)) { 32 | mkdir -Force $(Split-Path $InstallerFile -Parent) > $null 33 | Write-Output "Downloading $($DownloadLink.Segments[-2].TrimEnd("/")) installer" 34 | (New-Object System.Net.WebClient).DownloadFile($DownloadLink, $InstallerFile) 35 | } else { 36 | Write-Output "Using cached installer from $InstallerFile" 37 | } 38 | 39 | # Execute installer 40 | Write-Output "Installing experimental hive" 41 | Invoke-Exe $InstallerFile "/VsVersion=$VisualStudioMajorVersion.0" "/SpecificProductNames=ReSharper" "/Hive=$RootSuffix" "/Silent=True" 42 | 43 | $Installations = @(Get-ChildItem "$env:LOCALAPPDATA\JetBrains\ReSharperPlatformVs$VisualStudioMajorVersion\vAny_$VisualStudioInstanceId$RootSuffix\NuGet.Config") 44 | if ($Installations.Count -ne 1) { Write-Error "Found no or multiple installation directories: $Installations" } 45 | $InstallationDirectory = $Installations.Directory 46 | Write-Host "Found installation directory at $InstallationDirectory" 47 | 48 | # Adapt packages.config 49 | if (Test-Path "$InstallationDirectory\packages.config") { 50 | $PackagesXml = [xml] (Get-Content "$InstallationDirectory\packages.config") 51 | } else { 52 | $PackagesXml = [xml] ("") 53 | } 54 | 55 | if ($null -eq $PackagesXml.SelectSingleNode(".//package[@id='$PluginId']/@id")) { 56 | $PluginNode = $PackagesXml.CreateElement('package') 57 | $PluginNode.setAttribute("id", "$PluginId") 58 | $PluginNode.setAttribute("version", "$Version") 59 | 60 | $PackagesNode = $PackagesXml.SelectSingleNode("//packages") 61 | $PackagesNode.AppendChild($PluginNode) > $null 62 | 63 | $PackagesXml.Save("$InstallationDirectory\packages.config") 64 | } 65 | 66 | # Adapt user project file 67 | $HostIdentifier = "$($InstallationDirectory.Parent.Name)_$($InstallationDirectory.Name.Split('_')[-1])" 68 | 69 | Set-Content -Path "$UserProjectXmlFile" -Value "" 70 | 71 | $ProjectXml = [xml] (Get-Content "$UserProjectXmlFile") 72 | $HostIdentifierNode = $ProjectXml.SelectSingleNode(".//HostFullIdentifier") 73 | $HostIdentifierNode.InnerText = $HostIdentifier 74 | $ProjectXml.Save("$UserProjectXmlFile") 75 | 76 | # Install plugin 77 | $PluginRepository = "$env:LOCALAPPDATA\JetBrains\plugins" 78 | Remove-Item "$PluginRepository\${PluginId}.${Version}" -Recurse -ErrorAction Ignore 79 | Invoke-Exe $MSBuildPath "/t:Restore;Rebuild;Pack" "$SolutionPath" "/v:minimal" "/p:PackageVersion=$Version" "/p:PackageOutputPath=`"$OutputDirectory`"" 80 | Invoke-Exe $NuGetPath install $PluginId -OutputDirectory "$PluginRepository" -Source "$OutputDirectory" -DependencyVersion Ignore 81 | 82 | Write-Output "Re-installing experimental hive" 83 | Invoke-Exe "$InstallerFile" "/VsVersion=$VisualStudioMajorVersion.0" "/SpecificProductNames=ReSharper" "/Hive=$RootSuffix" "/Silent=True" 84 | } else { 85 | Write-Warning "Plugin is already installed. To trigger reinstall, delete $UserProjectXmlFile." 86 | } 87 | 88 | Invoke-Exe $MSBuildPath "/t:Restore;Rebuild" "$SolutionPath" "/v:minimal" 89 | Invoke-Exe $DevEnvPath "/rootSuffix $RootSuffix" "/ReSharper.Internal" "/ReSharper.LogFile $PSScriptRoot\ReSharper.log" "/ReSharper.LogLevel Trace" -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Features/ExtensionMethodsCsharp.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 ExtensionMethodsCsharp 13 | { 14 | public static int CountChildren(this ITreeNode node) 15 | where T : ITreeNode 16 | { 17 | var treeNodes = node.Children().ToList(); 18 | 19 | var childOfType = treeNodes.OfType(); 20 | var count = childOfType.Count(); 21 | 22 | foreach (var childNodes in treeNodes) 23 | { 24 | count += CountChildren(childNodes); 25 | } 26 | return count; 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) 47 | where T : class, ITreeNode 48 | { 49 | var list = new List(); 50 | if (root is T rootAsType) 51 | list.Add(rootAsType); 52 | 53 | list.AddRange(root.GetChildrenRecursive()); 54 | 55 | return list; 56 | } 57 | 58 | public static IEnumerable GetChildrenRecursive(this ITreeNode node) 59 | where T : ITreeNode 60 | { 61 | var nodeChildren = node.Children().ToList(); 62 | 63 | var list = new List(); 64 | 65 | var childOfType = nodeChildren.OfType(); 66 | list.AddRange(childOfType); 67 | 68 | foreach (var childNode in nodeChildren) 69 | { 70 | var childrenOfType = GetChildrenRecursive(childNode); 71 | list.AddRange(childrenOfType); 72 | } 73 | 74 | return list; 75 | } 76 | 77 | private static bool IsNodeThatIncreasesDepth(ITreeNode node) 78 | { 79 | switch (node) 80 | { 81 | case IIfStatement _: 82 | return true; 83 | case IForeachStatement _: 84 | return true; 85 | case IForStatement _: 86 | return true; 87 | case ISwitchStatement _: 88 | return true; 89 | } 90 | 91 | return false; 92 | } 93 | 94 | public static IType TryGetClosedReturnTypeFrom(ITreeNode treeNode) 95 | { 96 | switch (treeNode) 97 | { 98 | case IReferenceExpression reference: 99 | return TryGetClosedReturnTypeFromReference(reference.Reference); 100 | case IInvocationExpression invocationExpression: 101 | return TryGetClosedReturnTypeFromReference(invocationExpression.Reference); 102 | default: 103 | return null; 104 | } 105 | } 106 | 107 | public static IReferenceExpression TryGetFirstReferenceExpression(ITreeNode currentNode) 108 | { 109 | var childNodes = currentNode.Children(); 110 | var firstChildNode = childNodes.FirstOrDefault(); 111 | 112 | if (firstChildNode == null) 113 | return null; 114 | 115 | return firstChildNode as IReferenceExpression 116 | ?? TryGetFirstReferenceExpression(firstChildNode); 117 | } 118 | 119 | private static IType TryGetClosedReturnTypeFromReference(IReference reference) 120 | { 121 | var resolveResultWithInfo = GetResolveResult(reference); 122 | var declaredElement = resolveResultWithInfo.DeclaredElement; 123 | 124 | if (declaredElement is IParametersOwner parametersOwner) 125 | { 126 | var returnType = parametersOwner.ReturnType; 127 | return returnType.IsOpenType 128 | ? GetClosedType(resolveResultWithInfo, returnType) 129 | : returnType; 130 | } 131 | 132 | return null; 133 | } 134 | 135 | private static IType GetClosedType( 136 | ResolveResultWithInfo resolveResultWithInfo, 137 | IType returnType 138 | ) 139 | { 140 | return resolveResultWithInfo.Result.Substitution.Apply(returnType); 141 | } 142 | 143 | public static ResolveResultWithInfo GetResolveResult(this IReference reference) 144 | { 145 | return reference.Resolve(); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem GRADLE JVM WRAPPER START MARKER 40 | 41 | setlocal 42 | set BUILD_DIR=%LOCALAPPDATA%\gradle-jvm 43 | set JVM_TARGET_DIR=%BUILD_DIR%\jdk-17.0.3.1_windows-x64_bin-d6ede5\ 44 | 45 | set JVM_URL=https://download.oracle.com/java/17/archive/jdk-17.0.3.1_windows-x64_bin.zip 46 | 47 | set IS_TAR_GZ=0 48 | set JVM_TEMP_FILE=gradle-jvm.zip 49 | 50 | if /I "%JVM_URL:~-7%"==".tar.gz" ( 51 | set IS_TAR_GZ=1 52 | set JVM_TEMP_FILE=gradle-jvm.tar.gz 53 | ) 54 | 55 | set POWERSHELL=%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe 56 | 57 | if not exist "%JVM_TARGET_DIR%" MD "%JVM_TARGET_DIR%" 58 | 59 | if not exist "%JVM_TARGET_DIR%.flag" goto downloadAndExtractJvm 60 | 61 | set /p CURRENT_FLAG=<"%JVM_TARGET_DIR%.flag" 62 | if "%CURRENT_FLAG%" == "%JVM_URL%" goto continueWithJvm 63 | 64 | :downloadAndExtractJvm 65 | 66 | PUSHD "%BUILD_DIR%" 67 | if errorlevel 1 goto fail 68 | 69 | echo Downloading %JVM_URL% to %BUILD_DIR%\%JVM_TEMP_FILE% 70 | if exist "%JVM_TEMP_FILE%" DEL /F "%JVM_TEMP_FILE%" 71 | "%POWERSHELL%" -nologo -noprofile -Command "Set-StrictMode -Version 3.0; $ErrorActionPreference = \"Stop\"; (New-Object Net.WebClient).DownloadFile('%JVM_URL%', '%JVM_TEMP_FILE%')" 72 | if errorlevel 1 goto fail 73 | 74 | POPD 75 | 76 | RMDIR /S /Q "%JVM_TARGET_DIR%" 77 | if errorlevel 1 goto fail 78 | 79 | MKDIR "%JVM_TARGET_DIR%" 80 | if errorlevel 1 goto fail 81 | 82 | PUSHD "%JVM_TARGET_DIR%" 83 | if errorlevel 1 goto fail 84 | 85 | echo Extracting %BUILD_DIR%\%JVM_TEMP_FILE% to %JVM_TARGET_DIR% 86 | 87 | if "%IS_TAR_GZ%"=="1" ( 88 | tar xf "..\\%JVM_TEMP_FILE%" 89 | ) else ( 90 | "%POWERSHELL%" -nologo -noprofile -command "Set-StrictMode -Version 3.0; $ErrorActionPreference = \"Stop\"; Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('..\\%JVM_TEMP_FILE%', '.');" 91 | ) 92 | if errorlevel 1 goto fail 93 | 94 | DEL /F "..\%JVM_TEMP_FILE%" 95 | if errorlevel 1 goto fail 96 | 97 | POPD 98 | 99 | echo %JVM_URL%>"%JVM_TARGET_DIR%.flag" 100 | if errorlevel 1 goto fail 101 | 102 | :continueWithJvm 103 | 104 | set JAVA_HOME= 105 | for /d %%d in ("%JVM_TARGET_DIR%"*) do if exist "%%d\bin\java.exe" set JAVA_HOME=%%d 106 | if not exist "%JAVA_HOME%\bin\java.exe" ( 107 | echo Unable to find java.exe under %JVM_TARGET_DIR% 108 | goto fail 109 | ) 110 | 111 | endlocal & set JAVA_HOME=%JAVA_HOME% 112 | 113 | @rem GRADLE JVM WRAPPER END MARKER 114 | 115 | @rem Find java.exe 116 | if defined JAVA_HOME goto findJavaFromJavaHome 117 | 118 | set JAVA_EXE=java.exe 119 | %JAVA_EXE% -version >NUL 2>&1 120 | if %ERRORLEVEL% equ 0 goto execute 121 | 122 | echo. 1>&2 123 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 124 | echo. 1>&2 125 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 126 | echo location of your Java installation. 1>&2 127 | 128 | goto fail 129 | 130 | :findJavaFromJavaHome 131 | set JAVA_HOME=%JAVA_HOME:"=% 132 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 133 | 134 | if exist "%JAVA_EXE%" goto execute 135 | 136 | echo. 1>&2 137 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 138 | echo. 1>&2 139 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 140 | echo location of your Java installation. 1>&2 141 | 142 | goto fail 143 | 144 | :execute 145 | @rem Setup the command line 146 | 147 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 148 | 149 | 150 | @rem Execute Gradle 151 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 152 | 153 | :end 154 | @rem End local scope for the variables with windows NT shell 155 | if %ERRORLEVEL% equ 0 goto mainEnd 156 | 157 | :fail 158 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 159 | rem the _cmd.exe /c_ return code! 160 | set EXIT_CODE=%ERRORLEVEL% 161 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 162 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 163 | exit /b %EXIT_CODE% 164 | 165 | :mainEnd 166 | if "%OS%"=="Windows_NT" endlocal 167 | 168 | :omega -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Settings/CleanCodeOptionsPage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using CleanCode.Resources.Icons; 4 | using JetBrains.Application.Settings; 5 | using JetBrains.Application.UI.Options; 6 | using JetBrains.Application.UI.Options.OptionsDialog; 7 | using JetBrains.IDE.UI.Extensions; 8 | using JetBrains.IDE.UI.Options; 9 | using JetBrains.Lifetimes; 10 | using JetBrains.ReSharper.Feature.Services.Daemon.OptionPages; 11 | using JetBrains.UI.RichText; 12 | 13 | namespace CleanCode.Settings 14 | { 15 | [OptionsPage( 16 | PageId, 17 | "Clean Code", 18 | typeof(SettingsThemedIcons.CleanCode), 19 | ParentId = CodeInspectionPage.PID 20 | )] 21 | public class CleanCodeOptionsPage : BeSimpleOptionsPage 22 | { 23 | private const string PageId = "CleanCodeAnalysisOptionsPage"; 24 | 25 | public CleanCodeOptionsPage( 26 | Lifetime lifetime, 27 | OptionsPageContext optionsPageContext, 28 | OptionsSettingsSmartContext optionsSettingsSmartContext 29 | ) 30 | : base(lifetime, optionsPageContext, optionsSettingsSmartContext) 31 | { 32 | CreateSettingsArea("Single Responsibility", CreateSingleResponsibilitySettings); 33 | CreateSettingsArea("Coupling", CreateCouplingSettingsArea); 34 | CreateSettingsArea("Legibility", CreateLegibilitySettingsArea); 35 | CreateSettingsArea("Complexity", CreateComplexitySettingsArea); 36 | 37 | CreateFooterArea(); 38 | } 39 | 40 | private void CreateFooterArea() 41 | { 42 | AddSpacer(); 43 | AddRichText( 44 | CreateItalicText( 45 | "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)" 46 | ) 47 | ); 48 | } 49 | 50 | private static RichText CreateItalicText(string value) => 51 | new(value, new TextStyle(JetFontStyles.Italic)); 52 | 53 | private void CreateComplexitySettingsArea() 54 | { 55 | AddText("Reduce complexity in individual statements."); 56 | AddIntOption( 57 | (CleanCodeSettings s) => s.MaximumExpressionsInCondition, 58 | Resources.Settings.MaximumExpressionsInsideACondition 59 | ); 60 | } 61 | 62 | private void CreateLegibilitySettingsArea() 63 | { 64 | AddText("Names should be meaningful."); 65 | 66 | AddIntOption( 67 | (CleanCodeSettings s) => s.MinimumMeaningfulMethodNameLength, 68 | Resources.Settings.MinimumMethodNameLength 69 | ); 70 | AddStringOption( 71 | (CleanCodeSettings s) => s.MeaninglessClassNameSuffixes, 72 | Resources.Settings.MeaninglessNameSuffixes 73 | ); 74 | } 75 | 76 | private void CreateCouplingSettingsArea() 77 | { 78 | AddText("Avoid excessive coupling between classes."); 79 | 80 | AddIntOption( 81 | (CleanCodeSettings s) => s.MaximumConstructorDependencies, 82 | Resources.Settings.MaximumConstructorDependencies 83 | ); 84 | AddIntOption( 85 | (CleanCodeSettings s) => s.MaximumChainedReferences, 86 | Resources.Settings.MaximumChainedReferences 87 | ); 88 | AddBoolOption( 89 | (CleanCodeSettings s) => s.IncludeLinqInChainedReferences, 90 | Resources.Settings.IncludeLinqInChainedReferences 91 | ); 92 | } 93 | 94 | private void CreateSingleResponsibilitySettings() 95 | { 96 | AddText( 97 | "A class should only have a single responsibility. Do not do too much in a class or method." 98 | ); 99 | 100 | AddIntOption( 101 | (CleanCodeSettings s) => s.MaximumMethodsInClass, 102 | Resources.Settings.MaximumMethodsPerClass 103 | ); 104 | AddIntOption( 105 | (CleanCodeSettings s) => s.MaximumPublicMethodsInClass, 106 | Resources.Settings.MaximumPublicMethodsPerClass 107 | ); 108 | AddIntOption( 109 | (CleanCodeSettings s) => s.MaximumMethodParameters, 110 | Resources.Settings.MaximumMethodDeclarationParameters 111 | ); 112 | AddIntOption( 113 | (CleanCodeSettings s) => s.MaximumMethodStatements, 114 | Resources.Settings.MaximumStatementsPerMethod 115 | ); 116 | AddIntOption( 117 | (CleanCodeSettings s) => s.MaximumDeclarationsInMethod, 118 | Resources.Settings.DeclarationsMaximum 119 | ); 120 | AddIntOption( 121 | (CleanCodeSettings s) => s.MaximumIndentationDepth, 122 | Resources.Settings.MaximumLevelOfNestingInAMethod 123 | ); 124 | AddSpacer(); 125 | AddBoolOption( 126 | (CleanCodeSettings cleanCodeSettings) => cleanCodeSettings.IsFlagAnalysisEnabled, 127 | Resources.Settings.IsFlagAnalysisEnabled 128 | ); 129 | } 130 | 131 | private void CreateSettingsArea(string headerText, Action createSettingsArea) 132 | { 133 | AddHeader(headerText); 134 | 135 | using (Indent()) 136 | createSettingsArea(); 137 | } 138 | 139 | private void AddIntOption( 140 | Expression> expression, 141 | string description 142 | ) 143 | { 144 | var valueProperty = OptionsSettingsSmartContext.GetValueProperty(Lifetime, expression); 145 | AddControl( 146 | valueProperty.GetBeSpinner(Lifetime, 0, 1000).WithDescription(description, Lifetime) 147 | ); 148 | } 149 | 150 | private void AddStringOption( 151 | Expression> expression, 152 | string description 153 | ) 154 | { 155 | var valueProperty = OptionsSettingsSmartContext.GetValueProperty(Lifetime, expression); 156 | AddControl(valueProperty.GetBeTextBox(Lifetime).WithDescription(description, Lifetime)); 157 | } 158 | 159 | private void AddBoolOption( 160 | Expression> expression, 161 | string description 162 | ) 163 | { 164 | var valueProperty = OptionsSettingsSmartContext.GetValueProperty(Lifetime, expression); 165 | AddControl(valueProperty.GetBeCheckBox(Lifetime, description)); 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/dotnet/MO.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 | 154 | Is flag analysis active. 155 | 156 | 157 | Maximum public methods per class 158 | 159 | 160 | Include LINQ methods in chained references count 161 | 162 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Resources/Warnings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Dieser Code wurde von einem Tool generiert. 4 | // Laufzeitversion:4.0.30319.42000 5 | // 6 | // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn 7 | // der Code erneut generiert wird. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CleanCode.Resources { 12 | using System; 13 | 14 | 15 | /// 16 | /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. 17 | /// 18 | // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert 19 | // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. 20 | // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen 21 | // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal 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 | /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal 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 | /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle 51 | /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Sucht eine lokalisierte Zeichenfolge, die Too many chained references. This might be violating the Law of Demeter. ({0} / {1}) ähnelt. 65 | /// 66 | internal static string ChainedReferences { 67 | get { 68 | return ResourceManager.GetString("ChainedReferences", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// Sucht eine lokalisierte Zeichenfolge, die Class contains too many methods. This might be violating the Single Responsibility Principle. ({0} / {1}) ähnelt. 74 | /// 75 | internal static string ClassTooBig { 76 | get { 77 | return ResourceManager.GetString("ClassTooBig", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// Sucht eine lokalisierte Zeichenfolge, die Excessive depth of nested code blocks. ({0} / {1}) ähnelt. 83 | /// 84 | internal static string ExcessiveDepth { 85 | get { 86 | return ResourceManager.GetString("ExcessiveDepth", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// Sucht eine lokalisierte Zeichenfolge, die This expression is too complex. ({0} / {1}) ähnelt. 92 | /// 93 | internal static string ExpressionTooComplex { 94 | get { 95 | return ResourceManager.GetString("ExpressionTooComplex", resourceCulture); 96 | } 97 | } 98 | 99 | /// 100 | /// Sucht eine lokalisierte Zeichenfolge, die This argument is used as a flag in the method. This might be violating the Single Responsibility Principle. ähnelt. 101 | /// 102 | internal static string FlagArgument { 103 | get { 104 | return ResourceManager.GetString("FlagArgument", resourceCulture); 105 | } 106 | } 107 | 108 | /// 109 | /// Sucht eine lokalisierte Zeichenfolge, die The usage of the suffix '{0}' is discouraged because it's too generic. Choose a meaningful name instead to clarify its intent and responsibilities. ähnelt. 110 | /// 111 | internal static string HollowTypeName { 112 | get { 113 | return ResourceManager.GetString("HollowTypeName", resourceCulture); 114 | } 115 | } 116 | 117 | /// 118 | /// Sucht eine lokalisierte Zeichenfolge, die The name of this method is too short to be meaningful. ähnelt. 119 | /// 120 | internal static string MethodNameNotMeaningful { 121 | get { 122 | return ResourceManager.GetString("MethodNameNotMeaningful", resourceCulture); 123 | } 124 | } 125 | 126 | /// 127 | /// Sucht eine lokalisierte Zeichenfolge, die This method is too long, indicating that it has too much responsibility. ({0} / {1}) ähnelt. 128 | /// 129 | internal static string MethodTooLong { 130 | get { 131 | return ResourceManager.GetString("MethodTooLong", resourceCulture); 132 | } 133 | } 134 | 135 | /// 136 | /// Sucht eine lokalisierte Zeichenfolge, die This method has too many declarations. ({0} / {1}) ähnelt. 137 | /// 138 | internal static string TooManyDeclarations { 139 | get { 140 | return ResourceManager.GetString("TooManyDeclarations", resourceCulture); 141 | } 142 | } 143 | 144 | /// 145 | /// Sucht eine lokalisierte Zeichenfolge, die There are too many interfaces being passed in to this constructor. It might be violating the Single Responsibility Principle. ({0} / {1}) ähnelt. 146 | /// 147 | internal static string TooManyDependencies { 148 | get { 149 | return ResourceManager.GetString("TooManyDependencies", resourceCulture); 150 | } 151 | } 152 | 153 | /// 154 | /// Sucht eine lokalisierte Zeichenfolge, die This method requires too many arguments. ({0} / {1}) ähnelt. 155 | /// 156 | internal static string TooManyMethodArguments { 157 | get { 158 | return ResourceManager.GetString("TooManyMethodArguments", resourceCulture); 159 | } 160 | } 161 | 162 | /// 163 | /// Looks up a localized string similar to Class contains too many public methods. This might be violating the Single Responsibility Principle and exposing too much of its implementation. ({0} / {1}). 164 | /// 165 | internal static string TooManyPublicMethods { 166 | get { 167 | return ResourceManager.GetString("TooManyPublicMethods", resourceCulture); 168 | } 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/dotnet/MO.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. ({0} / {1}) 122 | 123 | 124 | This method requires too many arguments. ({0} / {1}) 125 | 126 | 127 | This method is too long, indicating that it has too much responsibility. ({0} / {1}) 128 | 129 | 130 | Excessive depth of nested code blocks. ({0} / {1}) 131 | 132 | 133 | Class contains too many methods. This might be violating the Single Responsibility Principle. ({0} / {1}) 134 | 135 | 136 | Too many chained references. This might be violating the Law of Demeter. ({0} / {1}) 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. ({0} / {1}) 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 | 151 | This method has too many declarations. ({0} / {1}) 152 | 153 | 154 | Class contains too many public methods. This might be violating the Single Responsibility Principle and exposing too much of its implementation. ({0} / {1}) 155 | 156 | -------------------------------------------------------------------------------- /src/dotnet/MO.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", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal 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 | internal 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 | internal 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 | internal static string DeclarationsMaximum { 67 | get { 68 | return ResourceManager.GetString("DeclarationsMaximum", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// Looks up a localized string similar to Is flag analysis active.. 74 | /// 75 | internal static string IsFlagAnalysisEnabled { 76 | get { 77 | return ResourceManager.GetString("IsFlagAnalysisEnabled", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// Looks up a localized string similar to Include LINQ methods in chained references count. 83 | /// 84 | internal static string IncludeLinqInChainedReferences { 85 | get { 86 | return ResourceManager.GetString("IncludeLinqInChainedReferences", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// Looks up a localized string similar to Maximum chained references. 92 | /// 93 | internal static string MaximumChainedReferences { 94 | get { 95 | return ResourceManager.GetString("MaximumChainedReferences", resourceCulture); 96 | } 97 | } 98 | 99 | /// 100 | /// Looks up a localized string similar to Maximum interface dependencies for a constructor. 101 | /// 102 | internal static string MaximumConstructorDependencies { 103 | get { 104 | return ResourceManager.GetString("MaximumConstructorDependencies", resourceCulture); 105 | } 106 | } 107 | 108 | /// 109 | /// Looks up a localized string similar to Maximum expressions inside a condition. 110 | /// 111 | internal static string MaximumExpressionsInsideACondition { 112 | get { 113 | return ResourceManager.GetString("MaximumExpressionsInsideACondition", resourceCulture); 114 | } 115 | } 116 | 117 | /// 118 | /// Looks up a localized string similar to Maximum level of nesting in a method. 119 | /// 120 | internal static string MaximumLevelOfNestingInAMethod { 121 | get { 122 | return ResourceManager.GetString("MaximumLevelOfNestingInAMethod", resourceCulture); 123 | } 124 | } 125 | 126 | /// 127 | /// Looks up a localized string similar to Maximum method declaration parameters. 128 | /// 129 | internal static string MaximumMethodDeclarationParameters { 130 | get { 131 | return ResourceManager.GetString("MaximumMethodDeclarationParameters", resourceCulture); 132 | } 133 | } 134 | 135 | /// 136 | /// Looks up a localized string similar to Maximum methods per class. 137 | /// 138 | internal static string MaximumMethodsPerClass { 139 | get { 140 | return ResourceManager.GetString("MaximumMethodsPerClass", resourceCulture); 141 | } 142 | } 143 | 144 | /// 145 | /// Looks up a localized string similar to Maximum statements per method. 146 | /// 147 | internal static string MaximumStatementsPerMethod 148 | { 149 | get 150 | { 151 | return ResourceManager.GetString("MaximumStatementsPerMethod", resourceCulture); 152 | } 153 | } 154 | 155 | /// 156 | /// Looks up a localized string similar to List of meaningless suffixes. 157 | /// 158 | internal static string MeaninglessNameSuffixes { 159 | get { 160 | return ResourceManager.GetString("MeaninglessNameSuffixes", resourceCulture); 161 | } 162 | } 163 | 164 | /// 165 | /// Looks up a localized string similar to Separate items with commas. 166 | /// 167 | internal static string MeaninglessNameSuffixesTooltip { 168 | get { 169 | return ResourceManager.GetString("MeaninglessNameSuffixesTooltip", resourceCulture); 170 | } 171 | } 172 | 173 | /// 174 | /// Looks up a localized string similar to Maximum public methods per class. 175 | /// 176 | internal static string MaximumPublicMethodsPerClass 177 | { 178 | get 179 | { 180 | return ResourceManager.GetString("MaximumPublicMethodsPerClass", resourceCulture); 181 | } 182 | } 183 | 184 | /// 185 | /// Looks up a localized string similar to Minimum method name length. 186 | /// 187 | internal static string MinimumMethodNameLength { 188 | get { 189 | return ResourceManager.GetString("MinimumMethodNameLength", resourceCulture); 190 | } 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Dieser Code wurde von einem Tool generiert. 4 | // Laufzeitversion:4.0.30319.42000 5 | // 6 | // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn 7 | // der Code erneut generiert wird. 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="MO.CleanCode;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xa" + 13 | "ml", IconNames=new string[] { 14 | "CleanCode"})] 15 | 16 | namespace CleanCode.Resources.Icons 17 | { 18 | 19 | 20 | /// 21 | /// 22 | /// Autogenerated identifier classes and identifier objects to Themed Icons registered with . 23 | /// 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. 24 | /// 25 | /// 26 | /// 27 | /// This code was compile-time generated to support Themed Icons in the JetBrains application. 28 | /// 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. 29 | ///

XAML

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

Attributes

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

CodeBehind

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

Icons Origin

53 | /// 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. 54 | ///
55 | public sealed class SettingsThemedIcons 56 | { 57 | 58 | /// 59 | /// 60 | /// Autogenerated identifier class for the CleanCode Themed Icon. 61 | /// 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. 62 | /// 63 | /// 64 | /// 65 | /// For details on Themed Icons and their use, see Remarks on class. 66 | /// 67 | /// 68 | /// 69 | /// <Image Source="{icons:ThemedIcon myres:SettingsThemedIcons+CleanCode}" /> <!-- XAML --> 70 | /// 71 | /// 72 | /// [Item(Name="Sample", Icon=typeof(SettingsThemedIcons.CleanCode))] // C# Type attribute 73 | /// 74 | /// 75 | /// IconId iconid = SettingsThemedIcons.CleanCode.Id; // IconId identifier object 76 | /// 77 | /// 78 | /// themediconmanager.GetIcon<SettingsThemedIcons.CleanCode>() // Icon image for rendering 79 | /// 80 | [global::JetBrains.UI.Icons.CompiledIcons.CompiledIconClassAttribute("MO.CleanCode;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xa" + 81 | "ml", 0, "CleanCode")] 82 | public sealed class CleanCode : global::JetBrains.UI.Icons.CompiledIcons.CompiledIconClass 83 | { 84 | 85 | /// 86 | /// 87 | /// Autogenerated identifier object for the CleanCode Themed Icon. 88 | /// Identifier objects should be used where an value is expected. In attributes, XAML, or generic parameters use the containing identifier class. 89 | /// 90 | /// 91 | /// 92 | /// For details on Themed Icons and their use, see Remarks on class. 93 | /// 94 | /// 95 | /// 96 | /// <Image Source="{icons:ThemedIcon myres:SettingsThemedIcons+CleanCode}" /> <!-- XAML --> 97 | /// 98 | /// 99 | /// [Item(Name="Sample", Icon=typeof(SettingsThemedIcons.CleanCode))] // C# Type attribute 100 | /// 101 | /// 102 | /// IconId iconid = SettingsThemedIcons.CleanCode.Id; // IconId identifier object 103 | /// 104 | /// 105 | /// themediconmanager.GetIcon<SettingsThemedIcons.CleanCode>() // Icon image for rendering 106 | /// 107 | public static global::JetBrains.UI.Icons.IconId Id = new global::JetBrains.UI.Icons.CompiledIcons.CompiledIconId("MO.CleanCode;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xa" + 108 | "ml", 0, "CleanCode"); 109 | } 110 | } 111 | } 112 | 113 | 114 | public sealed class RenderedIcons_ByPackResourceNameHash_648FB37D75A94B00E240CCFFFBB8EFDD 115 | { 116 | 117 | public static byte[] CleanCode____png__x1 = new byte[] { 118 | 137, 119 | 80, 120 | 78, 121 | 71, 122 | 13, 123 | 10, 124 | 26, 125 | 10, 126 | 0, 127 | 0, 128 | 0, 129 | 13, 130 | 73, 131 | 72, 132 | 68, 133 | 82, 134 | 0, 135 | 0, 136 | 0, 137 | 16, 138 | 0, 139 | 0, 140 | 0, 141 | 16, 142 | 8, 143 | 6, 144 | 0, 145 | 0, 146 | 0, 147 | 31, 148 | 243, 149 | 255, 150 | 97, 151 | 0, 152 | 0, 153 | 0, 154 | 1, 155 | 115, 156 | 82, 157 | 71, 158 | 66, 159 | 0, 160 | 174, 161 | 206, 162 | 28, 163 | 233, 164 | 0, 165 | 0, 166 | 0, 167 | 4, 168 | 103, 169 | 65, 170 | 77, 171 | 65, 172 | 0, 173 | 0, 174 | 177, 175 | 143, 176 | 11, 177 | 252, 178 | 97, 179 | 5, 180 | 0, 181 | 0, 182 | 0, 183 | 9, 184 | 112, 185 | 72, 186 | 89, 187 | 115, 188 | 0, 189 | 0, 190 | 14, 191 | 195, 192 | 0, 193 | 0, 194 | 14, 195 | 195, 196 | 1, 197 | 199, 198 | 111, 199 | 168, 200 | 100, 201 | 0, 202 | 0, 203 | 0, 204 | 19, 205 | 73, 206 | 68, 207 | 65, 208 | 84, 209 | 56, 210 | 79, 211 | 99, 212 | 24, 213 | 5, 214 | 163, 215 | 96, 216 | 20, 217 | 140, 218 | 2, 219 | 48, 220 | 96, 221 | 96, 222 | 0, 223 | 0, 224 | 4, 225 | 16, 226 | 0, 227 | 1, 228 | 167, 229 | 68, 230 | 124, 231 | 99, 232 | 0, 233 | 0, 234 | 0, 235 | 0, 236 | 73, 237 | 69, 238 | 78, 239 | 68, 240 | 174, 241 | 66, 242 | 96, 243 | 130}; 244 | 245 | public static byte[] CleanCode____png__x2 = new byte[] { 246 | 137, 247 | 80, 248 | 78, 249 | 71, 250 | 13, 251 | 10, 252 | 26, 253 | 10, 254 | 0, 255 | 0, 256 | 0, 257 | 13, 258 | 73, 259 | 72, 260 | 68, 261 | 82, 262 | 0, 263 | 0, 264 | 0, 265 | 32, 266 | 0, 267 | 0, 268 | 0, 269 | 32, 270 | 8, 271 | 6, 272 | 0, 273 | 0, 274 | 0, 275 | 115, 276 | 122, 277 | 122, 278 | 244, 279 | 0, 280 | 0, 281 | 0, 282 | 1, 283 | 115, 284 | 82, 285 | 71, 286 | 66, 287 | 0, 288 | 174, 289 | 206, 290 | 28, 291 | 233, 292 | 0, 293 | 0, 294 | 0, 295 | 4, 296 | 103, 297 | 65, 298 | 77, 299 | 65, 300 | 0, 301 | 0, 302 | 177, 303 | 143, 304 | 11, 305 | 252, 306 | 97, 307 | 5, 308 | 0, 309 | 0, 310 | 0, 311 | 9, 312 | 112, 313 | 72, 314 | 89, 315 | 115, 316 | 0, 317 | 0, 318 | 14, 319 | 195, 320 | 0, 321 | 0, 322 | 14, 323 | 195, 324 | 1, 325 | 199, 326 | 111, 327 | 168, 328 | 100, 329 | 0, 330 | 0, 331 | 0, 332 | 26, 333 | 73, 334 | 68, 335 | 65, 336 | 84, 337 | 88, 338 | 71, 339 | 237, 340 | 193, 341 | 1, 342 | 1, 343 | 0, 344 | 0, 345 | 0, 346 | 130, 347 | 32, 348 | 255, 349 | 175, 350 | 110, 351 | 72, 352 | 64, 353 | 0, 354 | 0, 355 | 0, 356 | 192, 357 | 185, 358 | 26, 359 | 16, 360 | 32, 361 | 0, 362 | 1, 363 | 157, 364 | 120, 365 | 73, 366 | 67, 367 | 0, 368 | 0, 369 | 0, 370 | 0, 371 | 73, 372 | 69, 373 | 78, 374 | 68, 375 | 174, 376 | 66, 377 | 96, 378 | 130}; 379 | } 380 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 87 | APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit 88 | 89 | # Use the maximum available, or set MAX_FD != -1 to use that value. 90 | MAX_FD=maximum 91 | 92 | warn () { 93 | echo "$*" 94 | } >&2 95 | 96 | die () { 97 | echo 98 | echo "$*" 99 | echo 100 | exit 1 101 | } >&2 102 | 103 | # OS specific support (must be 'true' or 'false'). 104 | cygwin=false 105 | msys=false 106 | darwin=false 107 | nonstop=false 108 | case "$( uname )" in #( 109 | CYGWIN* ) cygwin=true ;; #( 110 | Darwin* ) darwin=true ;; #( 111 | MSYS* | MINGW* ) msys=true ;; #( 112 | NONSTOP* ) nonstop=true ;; 113 | esac 114 | 115 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 116 | 117 | 118 | # GRADLE JVM WRAPPER START MARKER 119 | BUILD_DIR="${HOME}/.local/share/gradle-jvm" 120 | JVM_ARCH=$(uname -m) 121 | JVM_TEMP_FILE=$BUILD_DIR/gradle-jvm-temp.tar.gz 122 | if [ "$darwin" = "true" ]; then 123 | case $JVM_ARCH in 124 | x86_64) 125 | JVM_URL=https://download.oracle.com/java/17/archive/jdk-17.0.3.1_macos-x64_bin.tar.gz 126 | JVM_TARGET_DIR=$BUILD_DIR/jdk-17.0.3.1_macos-x64_bin-1bcf03 127 | ;; 128 | arm64) 129 | JVM_URL=https://download.oracle.com/java/17/archive/jdk-17.0.3.1_macos-aarch64_bin.tar.gz 130 | JVM_TARGET_DIR=$BUILD_DIR/jdk-17.0.3.1_macos-aarch64_bin-297fa2 131 | ;; 132 | *) 133 | die "Unknown architecture $JVM_ARCH" 134 | ;; 135 | esac 136 | elif [ "$cygwin" = "true" ] || [ "$msys" = "true" ]; then 137 | JVM_URL=https://download.oracle.com/java/17/archive/jdk-17.0.3.1_windows-x64_bin.zip 138 | JVM_TARGET_DIR=$BUILD_DIR/jdk-17.0.3.1_windows-x64_bin-d6ede5 139 | else 140 | JVM_ARCH=$(linux$(getconf LONG_BIT) uname -m) 141 | case $JVM_ARCH in 142 | x86_64) 143 | JVM_URL=https://download.oracle.com/java/17/archive/jdk-17.0.3.1_linux-x64_bin.tar.gz 144 | JVM_TARGET_DIR=$BUILD_DIR/jdk-17.0.3.1_linux-x64_bin-9324ae 145 | ;; 146 | aarch64) 147 | JVM_URL=https://download.oracle.com/java/17/archive/jdk-17.0.3.1_linux-aarch64_bin.tar.gz 148 | JVM_TARGET_DIR=$BUILD_DIR/jdk-17.0.3.1_linux-aarch64_bin-319da6 149 | ;; 150 | *) 151 | die "Unknown architecture $JVM_ARCH" 152 | ;; 153 | esac 154 | fi 155 | 156 | set -e 157 | 158 | if [ -e "$JVM_TARGET_DIR/.flag" ] && [ -n "$(ls "$JVM_TARGET_DIR")" ] && [ "x$(cat "$JVM_TARGET_DIR/.flag")" = "x${JVM_URL}" ]; then 159 | # Everything is up-to-date in $JVM_TARGET_DIR, do nothing 160 | true 161 | else 162 | echo "Downloading $JVM_URL to $JVM_TEMP_FILE" 163 | 164 | rm -f "$JVM_TEMP_FILE" 165 | mkdir -p "$BUILD_DIR" 166 | if command -v curl >/dev/null 2>&1; then 167 | if [ -t 1 ]; then CURL_PROGRESS="--progress-bar"; else CURL_PROGRESS="--silent --show-error"; fi 168 | # shellcheck disable=SC2086 169 | curl $CURL_PROGRESS -L --output "${JVM_TEMP_FILE}" "$JVM_URL" 2>&1 170 | elif command -v wget >/dev/null 2>&1; then 171 | if [ -t 1 ]; then WGET_PROGRESS=""; else WGET_PROGRESS="-nv"; fi 172 | wget $WGET_PROGRESS -O "${JVM_TEMP_FILE}" "$JVM_URL" 2>&1 173 | else 174 | die "ERROR: Please install wget or curl" 175 | fi 176 | 177 | echo "Extracting $JVM_TEMP_FILE to $JVM_TARGET_DIR" 178 | rm -rf "$JVM_TARGET_DIR" 179 | mkdir -p "$JVM_TARGET_DIR" 180 | 181 | case "$JVM_URL" in 182 | *".zip") unzip "$JVM_TEMP_FILE" -d "$JVM_TARGET_DIR" ;; 183 | *) tar -x -f "$JVM_TEMP_FILE" -C "$JVM_TARGET_DIR" ;; 184 | esac 185 | 186 | rm -f "$JVM_TEMP_FILE" 187 | 188 | echo "$JVM_URL" >"$JVM_TARGET_DIR/.flag" 189 | fi 190 | 191 | JAVA_HOME= 192 | for d in "$JVM_TARGET_DIR" "$JVM_TARGET_DIR"/* "$JVM_TARGET_DIR"/Contents/Home "$JVM_TARGET_DIR"/*/Contents/Home; do 193 | if [ -e "$d/bin/java" ]; then 194 | JAVA_HOME="$d" 195 | fi 196 | done 197 | 198 | if [ '!' -e "$JAVA_HOME/bin/java" ]; then 199 | die "Unable to find bin/java under $JVM_TARGET_DIR" 200 | fi 201 | 202 | # Make it available for child processes 203 | export JAVA_HOME 204 | 205 | set +e 206 | 207 | # GRADLE JVM WRAPPER END MARKER 208 | 209 | # Determine the Java command to use to start the JVM. 210 | if [ -n "$JAVA_HOME" ] ; then 211 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 212 | # IBM's JDK on AIX uses strange locations for the executables 213 | JAVACMD=$JAVA_HOME/jre/sh/java 214 | else 215 | JAVACMD=$JAVA_HOME/bin/java 216 | fi 217 | if [ ! -x "$JAVACMD" ] ; then 218 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 219 | 220 | Please set the JAVA_HOME variable in your environment to match the 221 | location of your Java installation." 222 | fi 223 | else 224 | JAVACMD=java 225 | if ! command -v java >/dev/null 2>&1 226 | then 227 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 228 | 229 | Please set the JAVA_HOME variable in your environment to match the 230 | location of your Java installation." 231 | fi 232 | fi 233 | 234 | # Increase the maximum file descriptors if we can. 235 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 236 | case $MAX_FD in #( 237 | max*) 238 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 239 | # shellcheck disable=SC2039,SC3045 240 | MAX_FD=$( ulimit -H -n ) || 241 | warn "Could not query maximum file descriptor limit" 242 | esac 243 | case $MAX_FD in #( 244 | '' | soft) :;; #( 245 | *) 246 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 247 | # shellcheck disable=SC2039,SC3045 248 | ulimit -n "$MAX_FD" || 249 | warn "Could not set maximum file descriptor limit to $MAX_FD" 250 | esac 251 | fi 252 | 253 | # Collect all arguments for the java command, stacking in reverse order: 254 | # * args from the command line 255 | # * the main class name 256 | # * -classpath 257 | # * -D...appname settings 258 | # * --module-path (only if needed) 259 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 260 | 261 | # For Cygwin or MSYS, switch paths to Windows format before running java 262 | if "$cygwin" || "$msys" ; then 263 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 264 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 265 | 266 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 267 | 268 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 269 | for arg do 270 | if 271 | case $arg in #( 272 | -*) false ;; # don't mess with options #( 273 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 274 | [ -e "$t" ] ;; #( 275 | *) false ;; 276 | esac 277 | then 278 | arg=$( cygpath --path --ignore --mixed "$arg" ) 279 | fi 280 | # Roll the args list around exactly as many times as the number of 281 | # args, so each arg winds up back in the position where it started, but 282 | # possibly modified. 283 | # 284 | # NB: a `for` loop captures its iteration list before it begins, so 285 | # changing the positional parameters here affects neither the number of 286 | # iterations, nor the values presented in `arg`. 287 | shift # remove old arg 288 | set -- "$@" "$arg" # push replacement arg 289 | done 290 | fi 291 | 292 | 293 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 294 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 295 | 296 | # Collect all arguments for the java command: 297 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 298 | # and any embedded shellness will be escaped. 299 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 300 | # treated as '${Hostname}' itself on the command line. 301 | 302 | set -- \ 303 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 304 | -classpath "$CLASSPATH" \ 305 | org.gradle.wrapper.GradleWrapperMain \ 306 | "$@" 307 | 308 | # Stop when "xargs" is not available. 309 | if ! command -v xargs >/dev/null 2>&1 310 | then 311 | die "xargs is not available" 312 | fi 313 | 314 | # Use "xargs" to parse quoted args. 315 | # 316 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 317 | # 318 | # In Bash we could simply go: 319 | # 320 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 321 | # set -- "${ARGS[@]}" "$@" 322 | # 323 | # but POSIX shell has neither arrays nor command substitution, so instead we 324 | # post-process each arg (as a line of input to sed) to backslash-escape any 325 | # character that might be a shell metacharacter, then use eval to reverse 326 | # that process (while maintaining the separation between arguments), and wrap 327 | # the whole thing up as a single "set" statement. 328 | # 329 | # This will of course break if any of these variables contains a newline or 330 | # an unmatched quote. 331 | # 332 | 333 | eval "set -- $( 334 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 335 | xargs -n1 | 336 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 337 | tr '\n' ' ' 338 | )" '"$@"' 339 | 340 | exec "$JAVACMD" "$@" -------------------------------------------------------------------------------- /src/dotnet/MO.CleanCode/CleanCode.ruleset: -------------------------------------------------------------------------------- 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 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | --------------------------------------------------------------------------------