From a0d20ff13283e7e70828e8d9d291e96733d4470e Mon Sep 17 00:00:00 2001 From: Luis Ruiz Date: Mon, 2 Jun 2014 16:59:55 +0200 Subject: [PATCH 01/50] Check for Flag Arguments Based on The "Clean Code" book, passed a boolean into a function is a bad practice to avoid, because functions with flags arguments do one than more thing, one if the flag is true and another if the flag is false. --- CleanCode/src/CleanCode/CleanCode.8.2.csproj | 3 + .../CleanCode/CleanCodeDaemonStageProcess.cs | 5 +- .../FlagsMethodArgumentsChange.cs | 45 ++++++++++++ .../FlagsMethodArgumentsCheck.cs | 43 +++++++++++ .../FlagsMethodArguments/Highlighting.cs | 73 +++++++++++++++++++ .../CleanCode/Resources/Warnings.Designer.cs | 9 +++ .../src/CleanCode/Resources/Warnings.resx | 3 + .../CleanCode/Settings/CleanCodeSettings.cs | 5 ++ 8 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 CleanCode/src/CleanCode/Features/FlagsMethodArguments/FlagsMethodArgumentsChange.cs create mode 100644 CleanCode/src/CleanCode/Features/FlagsMethodArguments/FlagsMethodArgumentsCheck.cs create mode 100644 CleanCode/src/CleanCode/Features/FlagsMethodArguments/Highlighting.cs diff --git a/CleanCode/src/CleanCode/CleanCode.8.2.csproj b/CleanCode/src/CleanCode/CleanCode.8.2.csproj index df96a5e..a9432fa 100644 --- a/CleanCode/src/CleanCode/CleanCode.8.2.csproj +++ b/CleanCode/src/CleanCode/CleanCode.8.2.csproj @@ -51,6 +51,9 @@ + + + diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 3272abf..3d1e03c 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -28,6 +28,7 @@ using System; using CleanCode.Features.ClassTooBig; using CleanCode.Features.ExcessiveIndentation; +using CleanCode.Features.FlagsMethodArguments; using CleanCode.Features.MethodNameNotMeaningful; using CleanCode.Features.MethodTooLong; using CleanCode.Features.TooManyChainedReferences; @@ -45,7 +46,7 @@ namespace CleanCode public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase { private readonly IContextBoundSettingsStore settingsStore; - + private readonly FlagsMethodArgumentsCheck flagsMethodArgumentsCheck; private readonly MethodTooLongCheck methodTooLongCheck; private readonly ClassTooBigCheck classTooBigCheck; private readonly TooManyMethodArgumentsCheck tooManyArgumentsCheck; @@ -67,6 +68,7 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); methodNamesNotMeaningfulCheck = new MethodNamesNotMeaningfulCheck(settingsStore); tooManyChainedReferencesCheck = new TooManyChainedReferencesCheck(settingsStore); + flagsMethodArgumentsCheck = new FlagsMethodArgumentsCheck(settingsStore); } public override void Execute(Action commiter) @@ -80,6 +82,7 @@ public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration tooManyArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); excessiveIndentationCheck.ExecuteIfEnabled(methodDeclaration, context); methodNamesNotMeaningfulCheck.ExecuteIfEnabled(methodDeclaration, context); + flagsMethodArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); } public override void VisitConstructorDeclaration(IConstructorDeclaration constructorDeclaration, IHighlightingConsumer context) diff --git a/CleanCode/src/CleanCode/Features/FlagsMethodArguments/FlagsMethodArgumentsChange.cs b/CleanCode/src/CleanCode/Features/FlagsMethodArguments/FlagsMethodArgumentsChange.cs new file mode 100644 index 0000000..d9e2044 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/FlagsMethodArguments/FlagsMethodArgumentsChange.cs @@ -0,0 +1,45 @@ +#region License +// Copyright (C) 2012 Hadi Hariri and Contributors +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall +// be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT +// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.DataFlow; +using JetBrains.ProjectModel; +using JetBrains.ReSharper.Daemon; + +namespace CleanCode.Features.FlagsMethodArguments +{ + [SolutionComponent] + public class FlagsMethodArgumentsChange + { + public FlagsMethodArgumentsChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + { + var minMethodNameLenght = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.FlagMethodArgumentsMinimum); + settingsStore.AdviseChange(lifetime, minMethodNameLenght, daemon.Invalidate); + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/FlagsMethodArguments/FlagsMethodArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/FlagsMethodArguments/FlagsMethodArgumentsCheck.cs new file mode 100644 index 0000000..eb217d0 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/FlagsMethodArguments/FlagsMethodArgumentsCheck.cs @@ -0,0 +1,43 @@ +using CleanCode.Resources; +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.CSharp.Stages; +using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.Tree; +using System.Linq; + +namespace CleanCode.Features.FlagsMethodArguments +{ + public class FlagsMethodArgumentsCheck : SimpleCheck + { + public FlagsMethodArgumentsCheck(IContextBoundSettingsStore settingsStore) + : base(settingsStore) + { + } + + protected override void ExecuteCore(IMethodDeclaration methodDeclaration, IHighlightingConsumer consumer) + { + var threshold = Threshold; + + var numberOfFlagsArgument = methodDeclaration.ParameterDeclarations.Count( + declaration => declaration.Type.ToString() == typeof(System.Boolean).FullName); + + if (numberOfFlagsArgument > threshold) + { + var highlighting = new Highlighting(Warnings.FlagMethodArguments); + consumer.AddHighlighting(highlighting, methodDeclaration.GetNameDocumentRange()); + } + } + + protected override int Threshold + { + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.FlagMethodArgumentsMinimum); } + } + + protected override bool IsEnabled + { + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.FlagMethodArgumentsEnabled); } + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/FlagsMethodArguments/Highlighting.cs b/CleanCode/src/CleanCode/Features/FlagsMethodArguments/Highlighting.cs new file mode 100644 index 0000000..5911f28 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/FlagsMethodArguments/Highlighting.cs @@ -0,0 +1,73 @@ +#region License +// Copyright (C) 2012 Hadi Hariri and Contributors +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall +// be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT +// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using CleanCode.Features.FlagsMethodArguments; +using JetBrains.ReSharper.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, + HighlightingGroupIds.CodeSmell, "Flags Method Arguments", + "This method does more than one thing. Please review it.", + Severity.WARNING, false)] + +namespace CleanCode.Features.FlagsMethodArguments +{ + /// + /// The highlighting that warns about high complexity + /// + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class Highlighting : IHighlighting + { + internal const string SeverityID = "FlagsMethodArguments"; + private readonly string tooltip; + + public Highlighting(string toolTip) + { + tooltip = toolTip; + } + + public string ToolTip + { + get { return tooltip; } + } + + public string ErrorStripeToolTip + { + get { return tooltip; } + } + + public int NavigationOffsetPatch + { + get { return 0; } + } + + public bool IsValid() + { + return true; + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs index 040065e..1a1c522 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs @@ -87,6 +87,15 @@ public static string ExcessiveDepth { } } + /// + /// Looks up a localized string similar to This method does more than one thing. Passing a boolean into a function is a truly terrible practice.. + /// + public static string FlagMethodArguments { + get { + return ResourceManager.GetString("FlagMethodArguments", resourceCulture); + } + } + /// /// Looks up a localized string similar to The name of this method is too short to be meaningful.. /// diff --git a/CleanCode/src/CleanCode/Resources/Warnings.resx b/CleanCode/src/CleanCode/Resources/Warnings.resx index f51cc2a..6e4eb77 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.resx +++ b/CleanCode/src/CleanCode/Resources/Warnings.resx @@ -138,4 +138,7 @@ The name of this method is too short to be meaningful. + + This method does more than one thing. Passing a boolean into a function is a truly terrible practice. + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs index 7cad180..41d64ca 100644 --- a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs +++ b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs @@ -69,5 +69,10 @@ public class CleanCodeSettings public bool MethodNameNotMeaningfulMinimumEnabled { get; set; } [SettingsEntry(4, "MethodNameNotMeaningfulMinimum")] public int MethodNameNotMeaningfulMinimum { get; set; } + + [SettingsEntry(0, "FlagMethodArgumentsMinimum")] + public int FlagMethodArgumentsMinimum { get; set; } + [SettingsEntry(true, "FlagMethodArgumentsEnabled")] + public bool FlagMethodArgumentsEnabled { get; set; } } } \ No newline at end of file From 87df7e020235ab190bcb4906b3af51c47e098e72 Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Mon, 16 Jun 2014 12:37:25 +0200 Subject: [PATCH 02/50] Attempt to solve method chained warning when using Fluent Interfaces --- .../CleanCode/Features/ExtensionMethods.cs | 22 ++++++ .../TooManyChainedReferencesCheck.cs | 76 ++++++++++++++++--- 2 files changed, 86 insertions(+), 12 deletions(-) diff --git a/CleanCode/src/CleanCode/Features/ExtensionMethods.cs b/CleanCode/src/CleanCode/Features/ExtensionMethods.cs index d12ef11..a55b2e2 100644 --- a/CleanCode/src/CleanCode/Features/ExtensionMethods.cs +++ b/CleanCode/src/CleanCode/Features/ExtensionMethods.cs @@ -5,6 +5,8 @@ namespace CleanCode.Features { + using System.Collections.Generic; + public static class ExtensionMethods { public static int CountChildren(this ITreeNode node) where T : ITreeNode @@ -21,6 +23,26 @@ public static int CountChildren(this ITreeNode node) where T : ITreeNode return count; } + + + public static IEnumerable GetChildrenRecursive(this ITreeNode node) where T : ITreeNode + { + var nodeChildren = node.Children().ToList(); + + var list = new List(); + + var childOfType = nodeChildren.OfType(); + list.AddRange(childOfType); + + foreach (var childNode in nodeChildren) + { + var childrenOfType = GetChildrenRecursive(childNode); + list.AddRange(childrenOfType); + } + + return list; + } + public static int GetChildrenDepth(this ITreeNode node) { diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs index 6105eda..578ed9b 100644 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs @@ -1,4 +1,3 @@ -using CleanCode.Features.ChainedReferences; using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; @@ -6,9 +5,16 @@ using JetBrains.ReSharper.Daemon.Stages; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; +using System.Collections.Generic; +using System.Linq; +using CleanCode.Features.ChainedReferences; +using JetBrains.ReSharper.Psi; + namespace CleanCode.Features.TooManyChainedReferences { + using JetBrains.DocumentModel; + public class TooManyChainedReferencesCheck : SimpleCheck { public TooManyChainedReferencesCheck(IContextBoundSettingsStore settingsStore) @@ -16,30 +22,76 @@ public TooManyChainedReferencesCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IReferenceExpression methodDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IReferenceExpression referenceExpression, IHighlightingConsumer consumer) { - if (methodDeclaration != null && !ParentIsReference(methodDeclaration)) + if (referenceExpression != null) { - ProcessReference(methodDeclaration, consumer); + ProcessReference(referenceExpression, consumer); } } private void ProcessReference(IReferenceExpression reference, IHighlightingConsumer consumer) { - var length = reference.CountChildren(); - var maximumChainedReferences = Threshold; + + var count = reference.CountChildren(); - if (length > maximumChainedReferences) + if (count >= Threshold) { - var highlighting = new Highlighting(Warnings.ChainedReferences); - consumer.AddHighlighting(highlighting, reference.GetDocumentRange()); + var rootType = GetReturnTypeFrom(reference.Reference); + + if (IsStillUnknown(rootType)) + { + return; + } + + var childrenTypes = this.GetTypesFromChildren(reference); + + if (!EveryTypeIsTheSame(rootType, childrenTypes)) + { + AddHighlightning(reference, consumer); + } } } - private static bool ParentIsReference(ITreeNode element) + private IEnumerable GetTypesFromChildren(IReferenceExpression reference) + { + var children = reference.GetChildrenRecursive(); + + var typesFromChildren = children.Select(expression => this.GetReturnTypeFrom(expression.Reference)); + return typesFromChildren; + } + + private static void AddHighlightning(IReferenceExpression reference, IHighlightingConsumer consumer) { - var reference = element.Parent as IReferenceExpression; - return reference != null; + var highlighting = new Highlighting(Warnings.ChainedReferences); + var nameIdentifier = reference.NameIdentifier; + consumer.AddHighlighting(highlighting, nameIdentifier.GetDocumentRange()); + } + + private static bool EveryTypeIsTheSame(IType type, IEnumerable typesFromChildren) + { + return typesFromChildren.Any(otherType => Equals(type, otherType)); + } + + private static bool IsStillUnknown(IType type) + { + return type == null; + } + + private IType GetReturnTypeFrom(IReferenceExpressionReference reference) + { + if (reference.CurrentResolveResult != null) + { + var declaredElement = reference.CurrentResolveResult.DeclaredElement; + var parameternsOwner = declaredElement as IParametersOwner; + if (parameternsOwner != null) + { + var r = parameternsOwner.ReturnType; + return r; + } + } + + return null; } protected override int Threshold From 71c178b4c5ffd69505c4d52b4739f7379164696e Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Mon, 16 Jun 2014 14:29:41 +0200 Subject: [PATCH 03/50] Using removed. --- .../TooManyChainedReferences/TooManyChainedReferencesCheck.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs index 578ed9b..325b0ac 100644 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs @@ -7,14 +7,11 @@ using JetBrains.ReSharper.Psi.Tree; using System.Collections.Generic; using System.Linq; -using CleanCode.Features.ChainedReferences; using JetBrains.ReSharper.Psi; namespace CleanCode.Features.TooManyChainedReferences { - using JetBrains.DocumentModel; - public class TooManyChainedReferencesCheck : SimpleCheck { public TooManyChainedReferencesCheck(IContextBoundSettingsStore settingsStore) From a34d01cf02e9664397674a325ad02f45f29af412 Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Mon, 16 Jun 2014 15:28:00 +0200 Subject: [PATCH 04/50] Using Resolve to force CurrentResolveResult not null --- .../TooManyChainedReferencesCheck.cs | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs index 325b0ac..ddc3105 100644 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs @@ -29,12 +29,14 @@ protected override void ExecuteCore(IReferenceExpression referenceExpression, IH private void ProcessReference(IReferenceExpression reference, IHighlightingConsumer consumer) { - var count = reference.CountChildren(); if (count >= Threshold) { - var rootType = GetReturnTypeFrom(reference.Reference); + var referenceExpressionReference = reference.Reference; + referenceExpressionReference.Resolve(); + + var rootType = GetReturnTypeFrom(referenceExpressionReference); if (IsStillUnknown(rootType)) { @@ -43,10 +45,10 @@ private void ProcessReference(IReferenceExpression reference, IHighlightingConsu var childrenTypes = this.GetTypesFromChildren(reference); - if (!EveryTypeIsTheSame(rootType, childrenTypes)) + if (SomeTypeIsDifferent(rootType, childrenTypes)) { AddHighlightning(reference, consumer); - } + } } } @@ -55,7 +57,11 @@ private IEnumerable GetTypesFromChildren(IReferenceExpression reference) var children = reference.GetChildrenRecursive(); var typesFromChildren = children.Select(expression => this.GetReturnTypeFrom(expression.Reference)); - return typesFromChildren; + + var list = typesFromChildren.ToList(); + list.RemoveAt(list.Count - 1); + + return list; } private static void AddHighlightning(IReferenceExpression reference, IHighlightingConsumer consumer) @@ -65,9 +71,9 @@ private static void AddHighlightning(IReferenceExpression reference, IHighlighti consumer.AddHighlighting(highlighting, nameIdentifier.GetDocumentRange()); } - private static bool EveryTypeIsTheSame(IType type, IEnumerable typesFromChildren) + private static bool SomeTypeIsDifferent(IType type, IEnumerable typesFromChildren) { - return typesFromChildren.Any(otherType => Equals(type, otherType)); + return typesFromChildren.Any(otherType => !type.Equals(otherType)); } private static bool IsStillUnknown(IType type) @@ -77,15 +83,16 @@ private static bool IsStillUnknown(IType type) private IType GetReturnTypeFrom(IReferenceExpressionReference reference) { + reference.Resolve(); + if (reference.CurrentResolveResult != null) { var declaredElement = reference.CurrentResolveResult.DeclaredElement; var parameternsOwner = declaredElement as IParametersOwner; if (parameternsOwner != null) { - var r = parameternsOwner.ReturnType; - return r; - } + return parameternsOwner.ReturnType; + } } return null; From 2328f8b56be189b653afe4011ecf2e3805a5dc25 Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Mon, 16 Jun 2014 18:11:03 +0200 Subject: [PATCH 05/50] Type matching using Equals :( --- .../TooManyChainedReferencesCheck.cs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs index ddc3105..33a3440 100644 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs @@ -54,14 +54,9 @@ private void ProcessReference(IReferenceExpression reference, IHighlightingConsu private IEnumerable GetTypesFromChildren(IReferenceExpression reference) { - var children = reference.GetChildrenRecursive(); - + var children = reference.GetChildrenRecursive().Where(expression => expression.Reference.IsQualified); var typesFromChildren = children.Select(expression => this.GetReturnTypeFrom(expression.Reference)); - - var list = typesFromChildren.ToList(); - list.RemoveAt(list.Count - 1); - - return list; + return typesFromChildren; } private static void AddHighlightning(IReferenceExpression reference, IHighlightingConsumer consumer) @@ -73,7 +68,8 @@ private static void AddHighlightning(IReferenceExpression reference, IHighlighti private static bool SomeTypeIsDifferent(IType type, IEnumerable typesFromChildren) { - return typesFromChildren.Any(otherType => !type.Equals(otherType)); + bool someTypeIsDifferent = typesFromChildren.Any(otherType => !type.ToString().Equals(otherType.ToString())); + return someTypeIsDifferent; } private static bool IsStillUnknown(IType type) @@ -92,7 +88,7 @@ private IType GetReturnTypeFrom(IReferenceExpressionReference reference) if (parameternsOwner != null) { return parameternsOwner.ReturnType; - } + } } return null; From 9423f27fc7005f47dae342bc80b7b5a66df767ff Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Tue, 17 Jun 2014 09:57:26 +0200 Subject: [PATCH 06/50] Temporal fix for Fluent Interfaces and Method Chaining --- .../TooManyChainedReferencesCheck.cs | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs index 33a3440..3f58488 100644 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs @@ -12,6 +12,8 @@ namespace CleanCode.Features.TooManyChainedReferences { + using JetBrains.ReSharper.Psi.Resolve; + public class TooManyChainedReferencesCheck : SimpleCheck { public TooManyChainedReferencesCheck(IContextBoundSettingsStore settingsStore) @@ -29,33 +31,43 @@ protected override void ExecuteCore(IReferenceExpression referenceExpression, IH private void ProcessReference(IReferenceExpression reference, IHighlightingConsumer consumer) { - var count = reference.CountChildren(); + var chainedReferencesCount = reference.CountChildren(); - if (count >= Threshold) + if (chainedReferencesCount >= this.Threshold) { - var referenceExpressionReference = reference.Reference; - referenceExpressionReference.Resolve(); - - var rootType = GetReturnTypeFrom(referenceExpressionReference); + var rootType = GetRootType(reference); - if (IsStillUnknown(rootType)) + if (IsTypeStillUnknown(rootType)) { return; } - var childrenTypes = this.GetTypesFromChildren(reference); - - if (SomeTypeIsDifferent(rootType, childrenTypes)) + if (this.RootTypeAndChainedReferencesTypesAreDifferent(reference, rootType)) { AddHighlightning(reference, consumer); } } } + private static IType GetRootType(IReferenceExpression reference) + { + var referenceOfReference = reference.Reference; + referenceOfReference.Resolve(); + + var rootType = GetReturnTypeFrom(referenceOfReference); + return rootType; + } + + private bool RootTypeAndChainedReferencesTypesAreDifferent(IReferenceExpression reference, IType rootType) + { + var childrenTypes = this.GetTypesFromChildren(reference); + return SomeTypeIsDifferent(rootType, childrenTypes); + } + private IEnumerable GetTypesFromChildren(IReferenceExpression reference) { var children = reference.GetChildrenRecursive().Where(expression => expression.Reference.IsQualified); - var typesFromChildren = children.Select(expression => this.GetReturnTypeFrom(expression.Reference)); + var typesFromChildren = children.Select(expression => GetReturnTypeFrom(expression.Reference)); return typesFromChildren; } @@ -68,16 +80,21 @@ private static void AddHighlightning(IReferenceExpression reference, IHighlighti private static bool SomeTypeIsDifferent(IType type, IEnumerable typesFromChildren) { - bool someTypeIsDifferent = typesFromChildren.Any(otherType => !type.ToString().Equals(otherType.ToString())); + bool someTypeIsDifferent = typesFromChildren.Any(otherType => Equals(type, otherType)); return someTypeIsDifferent; } - private static bool IsStillUnknown(IType type) + private static bool Equals(IType type, IType otherType) + { + return !type.ToString().Equals(otherType.ToString()); + } + + private static bool IsTypeStillUnknown(IType type) { return type == null; } - private IType GetReturnTypeFrom(IReferenceExpressionReference reference) + private static IType GetReturnTypeFrom(IReference reference) { reference.Resolve(); From d913853149e11a1f56b4f454dbe870f67ab5e794 Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Wed, 18 Jun 2014 17:45:36 +0200 Subject: [PATCH 07/50] Different approach for excluding Fluent Interface chains from chained references check. --- .../CleanCode/CleanCodeDaemonStageProcess.cs | 8 +- .../TooManyChainedReferencesCheck.cs | 116 +++++++++++++++--- 2 files changed, 104 insertions(+), 20 deletions(-) diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 3272abf..81ed351 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -82,14 +82,14 @@ public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration methodNamesNotMeaningfulCheck.ExecuteIfEnabled(methodDeclaration, context); } - public override void VisitConstructorDeclaration(IConstructorDeclaration constructorDeclaration, IHighlightingConsumer context) + public override void VisitCSharpStatement(ICSharpStatement cSharpStatementParam, IHighlightingConsumer context) { - tooManyDependenciesCheck.ExecuteIfEnabled(constructorDeclaration, context); + tooManyChainedReferencesCheck.ExecuteIfEnabled(cSharpStatementParam, context); } - public override void VisitReferenceExpression(IReferenceExpression referenceExpressionParam, IHighlightingConsumer context) + public override void VisitConstructorDeclaration(IConstructorDeclaration constructorDeclaration, IHighlightingConsumer context) { - tooManyChainedReferencesCheck.ExecuteIfEnabled(referenceExpressionParam, context); + tooManyDependenciesCheck.ExecuteIfEnabled(constructorDeclaration, context); } public override void VisitClassDeclaration(IClassDeclaration classDeclaration, IHighlightingConsumer context) diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs index 3f58488..e7ea9a3 100644 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs @@ -12,41 +12,107 @@ namespace CleanCode.Features.TooManyChainedReferences { + using JetBrains; using JetBrains.ReSharper.Psi.Resolve; - public class TooManyChainedReferencesCheck : SimpleCheck + public class TooManyChainedReferencesCheck : SimpleCheck { public TooManyChainedReferencesCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IReferenceExpression referenceExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IStatement referenceExpression, IHighlightingConsumer consumer) { if (referenceExpression != null) { - ProcessReference(referenceExpression, consumer); + this.HighlightMethodChainsThatAreTooLong(referenceExpression, consumer); } } - private void ProcessReference(IReferenceExpression reference, IHighlightingConsumer consumer) + private void HighlightMethodChainsThatAreTooLong(ITreeNode statement, IHighlightingConsumer consumer) { - var chainedReferencesCount = reference.CountChildren(); + var children = statement.Children(); - if (chainedReferencesCount >= this.Threshold) + foreach (var treeNode in children) { - var rootType = GetRootType(reference); + var referenceExpression = treeNode as IReferenceExpression; + if (referenceExpression != null) + { + this.HightlightReferenceExpressionIfNeeded(referenceExpression, consumer); + } + else + { + HighlightMethodChainsThatAreTooLong(treeNode, consumer); + } + } + } - if (IsTypeStillUnknown(rootType)) + private void HightlightReferenceExpressionIfNeeded(IReferenceExpression referenceExpression, IHighlightingConsumer consumer) + { + var equalityComparer = new TypeEqualityComparer(); + var types = new HashSet(equalityComparer); + + ITreeNode child = referenceExpression; + int chainedCount = 0; + + while (child != null) + { + var childReturnType = this.GetReturnTypeFrom(child); + + if (childReturnType != null) { - return; + types.Add(childReturnType); } - if (this.RootTypeAndChainedReferencesTypesAreDifferent(reference, rootType)) + child = GetFirstChild(child); + chainedCount++; + } + + var isFluentChain = types.Count == 1; + + if (!isFluentChain) + { + if (chainedCount > Threshold) { - AddHighlightning(reference, consumer); + AddHighlightning(referenceExpression, consumer); } + } + } + + private IType GetReturnTypeFrom(ITreeNode treeNode) + { + IType type = null; + var reference = treeNode as IReferenceExpression; + if (reference != null) + { + type = GetReturnTypeFromReference(reference.Reference); + } + + var invocationExpression = treeNode as IInvocationExpression; + if (invocationExpression != null) + { + type = GetReturnTypeFromReference(invocationExpression.Reference); } + + return type; + } + + private static ITreeNode GetFirstChild(ITreeNode referenceExpression) + { + return referenceExpression.Children().FirstOrDefault(); + } + + private IList GetChainedNodes(ITreeNode statement) + { + var list = new List(); + var firstOrDefault = statement.Children().FirstOrDefault(); + if (firstOrDefault != null) + { + list.Add(firstOrDefault); + list.AddRange(this.GetChainedNodes(firstOrDefault)); + } + return list; } private static IType GetRootType(IReferenceExpression reference) @@ -54,7 +120,7 @@ private static IType GetRootType(IReferenceExpression reference) var referenceOfReference = reference.Reference; referenceOfReference.Resolve(); - var rootType = GetReturnTypeFrom(referenceOfReference); + var rootType = GetReturnTypeFromReference(referenceOfReference); return rootType; } @@ -67,7 +133,7 @@ private bool RootTypeAndChainedReferencesTypesAreDifferent(IReferenceExpression private IEnumerable GetTypesFromChildren(IReferenceExpression reference) { var children = reference.GetChildrenRecursive().Where(expression => expression.Reference.IsQualified); - var typesFromChildren = children.Select(expression => GetReturnTypeFrom(expression.Reference)); + var typesFromChildren = children.Select(expression => GetReturnTypeFromReference(expression.Reference)); return typesFromChildren; } @@ -86,7 +152,12 @@ private static bool SomeTypeIsDifferent(IType type, IEnumerable typesFrom private static bool Equals(IType type, IType otherType) { - return !type.ToString().Equals(otherType.ToString()); + if (type == null || otherType == null) + { + return false; + } + + return type.ToString().Equals(otherType.ToString()); } private static bool IsTypeStillUnknown(IType type) @@ -94,7 +165,7 @@ private static bool IsTypeStillUnknown(IType type) return type == null; } - private static IType GetReturnTypeFrom(IReference reference) + private static IType GetReturnTypeFromReference(IReference reference) { reference.Resolve(); @@ -105,7 +176,7 @@ private static IType GetReturnTypeFrom(IReference reference) if (parameternsOwner != null) { return parameternsOwner.ReturnType; - } + } } return null; @@ -121,4 +192,17 @@ protected override bool IsEnabled get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesEnabled); } } } + + internal class TypeEqualityComparer : IEqualityComparer + { + public bool Equals(IType x, IType y) + { + return x.ToString().Equals(y.ToString()); + } + + public int GetHashCode(IType obj) + { + return obj.ToString().GetHashCode(); + } + } } \ No newline at end of file From 268b27638e203e27cd10e1aba94ea759d171f2f3 Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Wed, 18 Jun 2014 23:58:49 +0200 Subject: [PATCH 08/50] Method chaining ignores fluent interface chains :) still using "ToString" to compare ITypes. To be refined. --- CleanCode/src/CleanCode/CleanCode.8.2.csproj | 1 + .../CleanCode/CleanCodeDaemonStageProcess.cs | 8 ++ .../Features/ClassTooBig/ClassTooBigCheck.cs | 6 +- .../ExcessiveIndentationCheck.cs | 6 +- .../MethodNamesNotMeaningfulCheck.cs | 8 +- .../MethodTooLong/MethodTooLongCheck.cs | 6 +- .../src/CleanCode/Features/SimpleCheck.cs | 2 +- .../TooManyChainedReferencesCheck.cs | 123 +++++------------- .../TypeEqualityComparer.cs | 18 +++ .../TooManyDependenciesCheck.cs | 6 +- .../TooManyMethodArgumentsCheck.cs | 6 +- 11 files changed, 82 insertions(+), 108 deletions(-) create mode 100644 CleanCode/src/CleanCode/Features/TooManyChainedReferences/TypeEqualityComparer.cs diff --git a/CleanCode/src/CleanCode/CleanCode.8.2.csproj b/CleanCode/src/CleanCode/CleanCode.8.2.csproj index df96a5e..cf221c9 100644 --- a/CleanCode/src/CleanCode/CleanCode.8.2.csproj +++ b/CleanCode/src/CleanCode/CleanCode.8.2.csproj @@ -77,6 +77,7 @@ + Code diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 81ed351..86ed1f6 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -33,6 +33,7 @@ using CleanCode.Features.TooManyChainedReferences; using CleanCode.Features.TooManyDependencies; using CleanCode.Features.TooManyMethodArguments; +using JetBrains.Application.Progress; using JetBrains.Application.Settings; using JetBrains.ReSharper.Daemon; using JetBrains.ReSharper.Daemon.CSharp.Stages; @@ -44,6 +45,7 @@ namespace CleanCode { public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase { + private readonly IDaemonProcess daemonProcess; private readonly IContextBoundSettingsStore settingsStore; private readonly MethodTooLongCheck methodTooLongCheck; @@ -57,6 +59,7 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile file, IContextBoundSettingsStore settingsStore) : base(daemonProcess, file) { + this.daemonProcess = daemonProcess; this.settingsStore = settingsStore; // Simple checks. @@ -72,6 +75,11 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil public override void Execute(Action commiter) { HighlightInFile((file, consumer) => file.ProcessDescendants(this, consumer), commiter, settingsStore); + if (daemonProcess.InterruptFlag) + { + throw new ProcessCancelledException(); + } + } public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration, IHighlightingConsumer context) diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs index 0abbc53..1334687 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs @@ -15,14 +15,14 @@ public ClassTooBigCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IClassDeclaration classDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IClassDeclaration statement, IHighlightingConsumer consumer) { var maxLength = Threshold; - var statementCount = classDeclaration.CountChildren(); + var statementCount = statement.CountChildren(); if (statementCount > maxLength) { - var declarationIdentifier = classDeclaration.NameIdentifier; + var declarationIdentifier = statement.NameIdentifier; var documentRange = declarationIdentifier.GetDocumentRange(); var highlighting = new Highlighting(Warnings.ClassTooBig); consumer.AddHighlighting(highlighting, documentRange); diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs index 6252577..88d19a0 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs @@ -15,15 +15,15 @@ public ExcessiveIndentationCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingConsumer consumer) { var maxIndentation = Threshold; - var depth = classDeclaration.GetChildrenDepth(); + var depth = statement.GetChildrenDepth(); if (depth > maxIndentation) { var highlighting = new Highlighting(Warnings.ExcessiveDepth); - consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, statement.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNamesNotMeaningfulCheck.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNamesNotMeaningfulCheck.cs index c190ab4..e04e8be 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNamesNotMeaningfulCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNamesNotMeaningfulCheck.cs @@ -15,21 +15,21 @@ public MethodNamesNotMeaningfulCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration methodDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingConsumer consumer) { var minimumMethodNameLenght = Threshold; - if (methodDeclaration.NameIdentifier == null) + if (statement.NameIdentifier == null) { return; } - var name = methodDeclaration.NameIdentifier.GetText(); + var name = statement.NameIdentifier.GetText(); var methodNameLenght = name.Length; if (methodNameLenght < minimumMethodNameLenght) { var highlighting = new Highlighting(Warnings.MethodNameNotMeaningful); - consumer.AddHighlighting(highlighting, methodDeclaration.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, statement.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs index 479df4a..30f4d81 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs @@ -15,15 +15,15 @@ public MethodTooLongCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration element, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingConsumer consumer) { var maxLength = Threshold; - var statementCount = element.CountChildren(); + var statementCount = statement.CountChildren(); if (statementCount > maxLength) { var highlighting = new Highlighting(Warnings.Warning_MethodTooLong); - consumer.AddHighlighting(highlighting, element.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, statement.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/SimpleCheck.cs b/CleanCode/src/CleanCode/Features/SimpleCheck.cs index 372431c..f09e8f8 100644 --- a/CleanCode/src/CleanCode/Features/SimpleCheck.cs +++ b/CleanCode/src/CleanCode/Features/SimpleCheck.cs @@ -22,7 +22,7 @@ public void ExecuteIfEnabled(TElement methodDeclaration, IHighlightingConsumer c ExecuteCore(methodDeclaration, context); } - protected abstract void ExecuteCore(TElement element, IHighlightingConsumer consumer); + protected abstract void ExecuteCore(TElement statement, IHighlightingConsumer consumer); protected abstract TThreshold Threshold { get; } diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs index e7ea9a3..a7f3494 100644 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; @@ -12,21 +13,20 @@ namespace CleanCode.Features.TooManyChainedReferences { - using JetBrains; using JetBrains.ReSharper.Psi.Resolve; - public class TooManyChainedReferencesCheck : SimpleCheck + public class TooManyChainedReferencesCheck : SimpleCheck { public TooManyChainedReferencesCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IStatement referenceExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(ICSharpStatement statement, IHighlightingConsumer consumer) { - if (referenceExpression != null) + if (statement != null && !statement.IsEmbeddedStatement) { - this.HighlightMethodChainsThatAreTooLong(referenceExpression, consumer); + this.HighlightMethodChainsThatAreTooLong(statement, consumer); } } @@ -53,31 +53,31 @@ private void HightlightReferenceExpressionIfNeeded(IReferenceExpression referenc var equalityComparer = new TypeEqualityComparer(); var types = new HashSet(equalityComparer); - ITreeNode child = referenceExpression; - int chainedCount = 0; - - while (child != null) + var nextReferenceExpression = referenceExpression; + var chainLength = 0; + + while (nextReferenceExpression != null) { - var childReturnType = this.GetReturnTypeFrom(child); + var childReturnType = this.GetReturnTypeFrom(nextReferenceExpression); if (childReturnType != null) { types.Add(childReturnType); + chainLength++; } - child = GetFirstChild(child); - chainedCount++; + nextReferenceExpression = TryGetFirstReferenceExpression(nextReferenceExpression); } var isFluentChain = types.Count == 1; if (!isFluentChain) { - if (chainedCount > Threshold) + if (chainLength > Threshold) { AddHighlightning(referenceExpression, consumer); } - } + } } private IType GetReturnTypeFrom(ITreeNode treeNode) @@ -98,43 +98,26 @@ private IType GetReturnTypeFrom(ITreeNode treeNode) return type; } - private static ITreeNode GetFirstChild(ITreeNode referenceExpression) + private static IReferenceExpression TryGetFirstReferenceExpression(ITreeNode currentNode) { - return referenceExpression.Children().FirstOrDefault(); - } + var childNodes = currentNode.Children(); + var firstChildNode = childNodes.FirstOrDefault(); - private IList GetChainedNodes(ITreeNode statement) - { - var list = new List(); - var firstOrDefault = statement.Children().FirstOrDefault(); - if (firstOrDefault != null) + if (firstChildNode == null) { - list.Add(firstOrDefault); - list.AddRange(this.GetChainedNodes(firstOrDefault)); + return null; } - return list; - } - - private static IType GetRootType(IReferenceExpression reference) - { - var referenceOfReference = reference.Reference; - referenceOfReference.Resolve(); - - var rootType = GetReturnTypeFromReference(referenceOfReference); - return rootType; - } + else + { + var referenceExpression = firstChildNode as IReferenceExpression; - private bool RootTypeAndChainedReferencesTypesAreDifferent(IReferenceExpression reference, IType rootType) - { - var childrenTypes = this.GetTypesFromChildren(reference); - return SomeTypeIsDifferent(rootType, childrenTypes); - } + if (referenceExpression == null) + { + referenceExpression = TryGetFirstReferenceExpression(firstChildNode); + } - private IEnumerable GetTypesFromChildren(IReferenceExpression reference) - { - var children = reference.GetChildrenRecursive().Where(expression => expression.Reference.IsQualified); - var typesFromChildren = children.Select(expression => GetReturnTypeFromReference(expression.Reference)); - return typesFromChildren; + return referenceExpression; + } } private static void AddHighlightning(IReferenceExpression reference, IHighlightingConsumer consumer) @@ -144,42 +127,19 @@ private static void AddHighlightning(IReferenceExpression reference, IHighlighti consumer.AddHighlighting(highlighting, nameIdentifier.GetDocumentRange()); } - private static bool SomeTypeIsDifferent(IType type, IEnumerable typesFromChildren) - { - bool someTypeIsDifferent = typesFromChildren.Any(otherType => Equals(type, otherType)); - return someTypeIsDifferent; - } - - private static bool Equals(IType type, IType otherType) + private static IType GetReturnTypeFromReference(IReference reference) { - if (type == null || otherType == null) + if (reference.CurrentResolveResult == null) { - return false; + reference.Resolve(); } - return type.ToString().Equals(otherType.ToString()); - } + Debug.Assert(reference.CurrentResolveResult != null, "reference.CurrentResolveResult != null"); - private static bool IsTypeStillUnknown(IType type) - { - return type == null; - } - - private static IType GetReturnTypeFromReference(IReference reference) - { - reference.Resolve(); + var declaredElement = reference.CurrentResolveResult.DeclaredElement; + var parameternsOwner = declaredElement as IParametersOwner; - if (reference.CurrentResolveResult != null) - { - var declaredElement = reference.CurrentResolveResult.DeclaredElement; - var parameternsOwner = declaredElement as IParametersOwner; - if (parameternsOwner != null) - { - return parameternsOwner.ReturnType; - } - } - - return null; + return parameternsOwner != null ? parameternsOwner.ReturnType : null; } protected override int Threshold @@ -192,17 +152,4 @@ protected override bool IsEnabled get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesEnabled); } } } - - internal class TypeEqualityComparer : IEqualityComparer - { - public bool Equals(IType x, IType y) - { - return x.ToString().Equals(y.ToString()); - } - - public int GetHashCode(IType obj) - { - return obj.ToString().GetHashCode(); - } - } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TypeEqualityComparer.cs b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TypeEqualityComparer.cs new file mode 100644 index 0000000..7537ad9 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TypeEqualityComparer.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using JetBrains.ReSharper.Psi; + +namespace CleanCode.Features.TooManyChainedReferences +{ + internal class TypeEqualityComparer : IEqualityComparer + { + public bool Equals(IType x, IType y) + { + return x.ToString().Equals(y.ToString()); + } + + public int GetHashCode(IType obj) + { + return obj.ToString().GetHashCode(); + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs index 98abf73..344fef7 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs @@ -17,11 +17,11 @@ public TooManyDependenciesCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IConstructorDeclaration constructorDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IConstructorDeclaration statement, IHighlightingConsumer consumer) { var maxDependencies = Threshold; - var depedencies = constructorDeclaration.ParameterDeclarations.Select( + var depedencies = statement.ParameterDeclarations.Select( declaration => declaration.DeclaredElement != null && declaration.DeclaredElement.Type.IsInterfaceType()); @@ -30,7 +30,7 @@ protected override void ExecuteCore(IConstructorDeclaration constructorDeclarati if (dependenciesCount > maxDependencies) { var highlighting = new Highlighting(Warnings.TooManyDependencies); - consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, statement.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs index aa3955c..f2242c0 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs @@ -15,15 +15,15 @@ public TooManyMethodArgumentsCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration methodDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingConsumer consumer) { - var parameterDeclarations = methodDeclaration.ParameterDeclarations; + var parameterDeclarations = statement.ParameterDeclarations; var maxParameters = Threshold; if (parameterDeclarations.Count > maxParameters) { var highlighting = new Highlighting(Warnings.TooManyMethodArguments); - consumer.AddHighlighting(highlighting, methodDeclaration.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, statement.GetNameDocumentRange()); } } From 150efd7cfc4b0a97682e4b98eefc572e0c8d639d Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Thu, 19 Jun 2014 22:23:25 +0200 Subject: [PATCH 09/50] Updated to work without EqualityComparer Works with generic return types (thanks to Matt Ellis!) --- CleanCode/src/CleanCode/CleanCode.8.2.csproj | 8 +- .../CleanCode/CleanCodeDaemonStageProcess.cs | 8 +- .../ChainedReferencesCheck.cs} | 90 +++------------ .../Highlighting.cs | 4 +- .../InvalidateOnMaximumChainedCalls.cs | 2 +- .../TypeEqualityComparer.cs | 2 +- .../CleanCode/Features/ExtensionMethods.cs | 107 ++++++++++++++---- .../src/CleanCode/Features/SimpleCheck.cs | 1 + CleanCode/src/NuGet.Packager/Package.nuspec | 2 +- 9 files changed, 115 insertions(+), 109 deletions(-) rename CleanCode/src/CleanCode/Features/{TooManyChainedReferences/TooManyChainedReferencesCheck.cs => ChainedReferences/ChainedReferencesCheck.cs} (51%) rename CleanCode/src/CleanCode/Features/{TooManyChainedReferences => ChainedReferences}/Highlighting.cs (95%) rename CleanCode/src/CleanCode/Features/{TooManyChainedReferences => ChainedReferences}/InvalidateOnMaximumChainedCalls.cs (97%) rename CleanCode/src/CleanCode/Features/{TooManyChainedReferences => ChainedReferences}/TypeEqualityComparer.cs (87%) diff --git a/CleanCode/src/CleanCode/CleanCode.8.2.csproj b/CleanCode/src/CleanCode/CleanCode.8.2.csproj index cf221c9..92a060f 100644 --- a/CleanCode/src/CleanCode/CleanCode.8.2.csproj +++ b/CleanCode/src/CleanCode/CleanCode.8.2.csproj @@ -51,9 +51,9 @@ - - - + + + @@ -77,7 +77,7 @@ - + Code diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 86ed1f6..95db43f 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -26,11 +26,11 @@ #endregion using System; +using CleanCode.Features.ChainedReferences; using CleanCode.Features.ClassTooBig; using CleanCode.Features.ExcessiveIndentation; using CleanCode.Features.MethodNameNotMeaningful; using CleanCode.Features.MethodTooLong; -using CleanCode.Features.TooManyChainedReferences; using CleanCode.Features.TooManyDependencies; using CleanCode.Features.TooManyMethodArguments; using JetBrains.Application.Progress; @@ -54,7 +54,7 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase private readonly ExcessiveIndentationCheck excessiveIndentationCheck; private readonly TooManyDependenciesCheck tooManyDependenciesCheck; private readonly MethodNamesNotMeaningfulCheck methodNamesNotMeaningfulCheck; - private readonly TooManyChainedReferencesCheck tooManyChainedReferencesCheck; + private readonly ChainedReferencesCheck chainedReferencesCheck; public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile file, IContextBoundSettingsStore settingsStore) : base(daemonProcess, file) @@ -69,7 +69,7 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil excessiveIndentationCheck = new ExcessiveIndentationCheck(settingsStore); tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); methodNamesNotMeaningfulCheck = new MethodNamesNotMeaningfulCheck(settingsStore); - tooManyChainedReferencesCheck = new TooManyChainedReferencesCheck(settingsStore); + chainedReferencesCheck = new ChainedReferencesCheck(settingsStore); } public override void Execute(Action commiter) @@ -92,7 +92,7 @@ public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration public override void VisitCSharpStatement(ICSharpStatement cSharpStatementParam, IHighlightingConsumer context) { - tooManyChainedReferencesCheck.ExecuteIfEnabled(cSharpStatementParam, context); + chainedReferencesCheck.ExecuteIfEnabled(cSharpStatementParam, context); } public override void VisitConstructorDeclaration(IConstructorDeclaration constructorDeclaration, IHighlightingConsumer context) diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs similarity index 51% rename from CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs rename to CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs index a7f3494..d8cd175 100644 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TooManyChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs @@ -1,23 +1,21 @@ -using System.Diagnostics; +using System.Collections.Generic; +using System.Linq; using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; using JetBrains.ReSharper.Daemon.CSharp.Stages; using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.ExtensionsAPI.Resolve; +using JetBrains.ReSharper.Psi.Resolve; using JetBrains.ReSharper.Psi.Tree; -using System.Collections.Generic; -using System.Linq; -using JetBrains.ReSharper.Psi; - -namespace CleanCode.Features.TooManyChainedReferences +namespace CleanCode.Features.ChainedReferences { - using JetBrains.ReSharper.Psi.Resolve; - - public class TooManyChainedReferencesCheck : SimpleCheck + public class ChainedReferencesCheck : SimpleCheck { - public TooManyChainedReferencesCheck(IContextBoundSettingsStore settingsStore) + public ChainedReferencesCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } @@ -50,15 +48,14 @@ private void HighlightMethodChainsThatAreTooLong(ITreeNode statement, IHighlight private void HightlightReferenceExpressionIfNeeded(IReferenceExpression referenceExpression, IHighlightingConsumer consumer) { - var equalityComparer = new TypeEqualityComparer(); - var types = new HashSet(equalityComparer); + var types = new HashSet(); var nextReferenceExpression = referenceExpression; var chainLength = 0; while (nextReferenceExpression != null) { - var childReturnType = this.GetReturnTypeFrom(nextReferenceExpression); + var childReturnType = ExtensionMethods.TryGetClosedReturnTypeFrom(nextReferenceExpression); if (childReturnType != null) { @@ -66,7 +63,7 @@ private void HightlightReferenceExpressionIfNeeded(IReferenceExpression referenc chainLength++; } - nextReferenceExpression = TryGetFirstReferenceExpression(nextReferenceExpression); + nextReferenceExpression = ExtensionMethods.TryGetFirstReferenceExpression(nextReferenceExpression); } var isFluentChain = types.Count == 1; @@ -80,76 +77,21 @@ private void HightlightReferenceExpressionIfNeeded(IReferenceExpression referenc } } - private IType GetReturnTypeFrom(ITreeNode treeNode) + protected override int Threshold { - IType type = null; - var reference = treeNode as IReferenceExpression; - if (reference != null) - { - type = GetReturnTypeFromReference(reference.Reference); - } - - var invocationExpression = treeNode as IInvocationExpression; - if (invocationExpression != null) - { - type = GetReturnTypeFromReference(invocationExpression.Reference); - } - - return type; + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); } } - private static IReferenceExpression TryGetFirstReferenceExpression(ITreeNode currentNode) + protected override bool IsEnabled { - var childNodes = currentNode.Children(); - var firstChildNode = childNodes.FirstOrDefault(); - - if (firstChildNode == null) - { - return null; - } - else - { - var referenceExpression = firstChildNode as IReferenceExpression; - - if (referenceExpression == null) - { - referenceExpression = TryGetFirstReferenceExpression(firstChildNode); - } - - return referenceExpression; - } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesEnabled); } } - private static void AddHighlightning(IReferenceExpression reference, IHighlightingConsumer consumer) + public static void AddHighlightning(IReferenceExpression reference, IHighlightingConsumer consumer) { var highlighting = new Highlighting(Warnings.ChainedReferences); var nameIdentifier = reference.NameIdentifier; consumer.AddHighlighting(highlighting, nameIdentifier.GetDocumentRange()); } - - private static IType GetReturnTypeFromReference(IReference reference) - { - if (reference.CurrentResolveResult == null) - { - reference.Resolve(); - } - - Debug.Assert(reference.CurrentResolveResult != null, "reference.CurrentResolveResult != null"); - - var declaredElement = reference.CurrentResolveResult.DeclaredElement; - var parameternsOwner = declaredElement as IParametersOwner; - - return parameternsOwner != null ? parameternsOwner.ReturnType : null; - } - - protected override int Threshold - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesEnabled); } - } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/Highlighting.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs similarity index 95% rename from CleanCode/src/CleanCode/Features/TooManyChainedReferences/Highlighting.cs rename to CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs index bbcd38c..2f27065 100644 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs @@ -25,7 +25,7 @@ // OR OTHER DEALINGS IN THE SOFTWARE. #endregion -using CleanCode.Features.TooManyChainedReferences; +using CleanCode.Features.ChainedReferences; using JetBrains.ReSharper.Daemon; using JetBrains.ReSharper.Psi.CSharp; @@ -33,7 +33,7 @@ HighlightingGroupIds.CodeSmell, "Chained References", "There are too many chained references.", Severity.WARNING, false)] -namespace CleanCode.Features.TooManyChainedReferences +namespace CleanCode.Features.ChainedReferences { [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] public class Highlighting : IHighlighting diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/InvalidateOnMaximumChainedCalls.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs similarity index 97% rename from CleanCode/src/CleanCode/Features/TooManyChainedReferences/InvalidateOnMaximumChainedCalls.cs rename to CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs index d79ca32..12d7de8 100644 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/InvalidateOnMaximumChainedCalls.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs @@ -31,7 +31,7 @@ using JetBrains.ProjectModel; using JetBrains.ReSharper.Daemon; -namespace CleanCode.Features.TooManyChainedReferences +namespace CleanCode.Features.ChainedReferences { [SolutionComponent] public class InvalidateOnMaximumChainedCalls diff --git a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TypeEqualityComparer.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/TypeEqualityComparer.cs similarity index 87% rename from CleanCode/src/CleanCode/Features/TooManyChainedReferences/TypeEqualityComparer.cs rename to CleanCode/src/CleanCode/Features/ChainedReferences/TypeEqualityComparer.cs index 7537ad9..54a0093 100644 --- a/CleanCode/src/CleanCode/Features/TooManyChainedReferences/TypeEqualityComparer.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/TypeEqualityComparer.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using JetBrains.ReSharper.Psi; -namespace CleanCode.Features.TooManyChainedReferences +namespace CleanCode.Features.ChainedReferences { internal class TypeEqualityComparer : IEqualityComparer { diff --git a/CleanCode/src/CleanCode/Features/ExtensionMethods.cs b/CleanCode/src/CleanCode/Features/ExtensionMethods.cs index a55b2e2..b9fe754 100644 --- a/CleanCode/src/CleanCode/Features/ExtensionMethods.cs +++ b/CleanCode/src/CleanCode/Features/ExtensionMethods.cs @@ -1,12 +1,13 @@ using System; using System.Linq; +using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.ExtensionsAPI.Resolve; +using JetBrains.ReSharper.Psi.Resolve; using JetBrains.ReSharper.Psi.Tree; namespace CleanCode.Features { - using System.Collections.Generic; - public static class ExtensionMethods { public static int CountChildren(this ITreeNode node) where T : ITreeNode @@ -24,26 +25,6 @@ public static int CountChildren(this ITreeNode node) where T : ITreeNode } - - public static IEnumerable GetChildrenRecursive(this ITreeNode node) where T : ITreeNode - { - var nodeChildren = node.Children().ToList(); - - var list = new List(); - - var childOfType = nodeChildren.OfType(); - list.AddRange(childOfType); - - foreach (var childNode in nodeChildren) - { - var childrenOfType = GetChildrenRecursive(childNode); - list.AddRange(childrenOfType); - } - - return list; - } - - public static int GetChildrenDepth(this ITreeNode node) { var childrenDepth = 0; @@ -82,5 +63,87 @@ private static bool IsNodeThatIncreasesDepth(ITreeNode node) return false; } + + public static IType TryGetClosedReturnTypeFrom(ITreeNode treeNode) + { + IType type = null; + var reference = treeNode as IReferenceExpression; + if (reference != null) + { + type = TryGetClosedReturnTypeFromReference(reference.Reference); + } + + var invocationExpression = treeNode as IInvocationExpression; + if (invocationExpression != null) + { + type = TryGetClosedReturnTypeFromReference(invocationExpression.Reference); + } + + return type; + } + + public static IReferenceExpression TryGetFirstReferenceExpression(ITreeNode currentNode) + { + var childNodes = currentNode.Children(); + var firstChildNode = childNodes.FirstOrDefault(); + + if (firstChildNode == null) + { + return null; + } + else + { + var referenceExpression = firstChildNode as IReferenceExpression; + + if (referenceExpression == null) + { + referenceExpression = TryGetFirstReferenceExpression(firstChildNode); + } + + return referenceExpression; + } + } + + private static IType TryGetClosedReturnTypeFromReference(IReference reference) + { + var resolveResultWithInfo = GetResolveResult(reference); + + if (reference.CurrentResolveResult == null) + { + reference.Resolve(); + } + + var declaredElement = resolveResultWithInfo.DeclaredElement; + var parametersOwner = declaredElement as IParametersOwner; + + if (parametersOwner != null) + { + var returnType = parametersOwner.ReturnType; + if (returnType.IsOpenType) + { + return GetClosedType(resolveResultWithInfo, returnType); + } + + return returnType; + } + + return null; + } + + private static IType GetClosedType(ResolveResultWithInfo resolveResultWithInfo, IType returnType) + { + var closedType = resolveResultWithInfo.Result.Substitution.Apply(returnType); + return closedType; + } + + private static ResolveResultWithInfo GetResolveResult(IReference reference) + { + if (reference.CurrentResolveResult != null) + { + return reference.CurrentResolveResult; + } + + return reference.Resolve(); + } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/SimpleCheck.cs b/CleanCode/src/CleanCode/Features/SimpleCheck.cs index f09e8f8..db2a5b4 100644 --- a/CleanCode/src/CleanCode/Features/SimpleCheck.cs +++ b/CleanCode/src/CleanCode/Features/SimpleCheck.cs @@ -19,6 +19,7 @@ public void ExecuteIfEnabled(TElement methodDeclaration, IHighlightingConsumer c { return; } + ExecuteCore(methodDeclaration, context); } diff --git a/CleanCode/src/NuGet.Packager/Package.nuspec b/CleanCode/src/NuGet.Packager/Package.nuspec index b233c63..83fabdc 100644 --- a/CleanCode/src/NuGet.Packager/Package.nuspec +++ b/CleanCode/src/NuGet.Packager/Package.nuspec @@ -2,7 +2,7 @@ CleanCode - 4.0.0.0 + 4.0.0.2 CleanCode Hadi Hariri, Matt Ellis, SuperJMN Hadi Hariri, Matt Ellis From a5f4c6962577b7b1ea86e38f5668168838102d76 Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Fri, 20 Jun 2014 14:46:07 +0200 Subject: [PATCH 10/50] New feature: Flag arguments. --- CleanCode/src/CleanCode/CleanCode.8.2.csproj | 4 +++ .../CleanCode/CleanCodeDaemonStageProcess.cs | 5 ++- .../CleanCode/Features/ExtensionMethods.cs | 36 ++++++++++++++++++- .../CleanCode/Resources/Warnings.Designer.cs | 9 +++++ .../src/CleanCode/Resources/Warnings.resx | 3 ++ .../src/NuGet.Packager/NuGet.Packager.csproj | 3 +- CleanCode/src/NuGet.Packager/Package.nuspec | 2 +- 7 files changed, 57 insertions(+), 5 deletions(-) diff --git a/CleanCode/src/CleanCode/CleanCode.8.2.csproj b/CleanCode/src/CleanCode/CleanCode.8.2.csproj index 92a060f..bb9fb63 100644 --- a/CleanCode/src/CleanCode/CleanCode.8.2.csproj +++ b/CleanCode/src/CleanCode/CleanCode.8.2.csproj @@ -66,6 +66,9 @@ Code + + + @@ -141,6 +144,7 @@ + diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 95db43f..08bba07 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -29,6 +29,7 @@ using CleanCode.Features.ChainedReferences; using CleanCode.Features.ClassTooBig; using CleanCode.Features.ExcessiveIndentation; +using CleanCode.Features.FlagArguments; using CleanCode.Features.MethodNameNotMeaningful; using CleanCode.Features.MethodTooLong; using CleanCode.Features.TooManyDependencies; @@ -55,6 +56,7 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase private readonly TooManyDependenciesCheck tooManyDependenciesCheck; private readonly MethodNamesNotMeaningfulCheck methodNamesNotMeaningfulCheck; private readonly ChainedReferencesCheck chainedReferencesCheck; + private readonly FlagArgumentsCheck flagArgumentsCheck; public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile file, IContextBoundSettingsStore settingsStore) : base(daemonProcess, file) @@ -70,6 +72,7 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); methodNamesNotMeaningfulCheck = new MethodNamesNotMeaningfulCheck(settingsStore); chainedReferencesCheck = new ChainedReferencesCheck(settingsStore); + flagArgumentsCheck = new FlagArgumentsCheck(settingsStore); } public override void Execute(Action commiter) @@ -79,7 +82,6 @@ public override void Execute(Action commiter) { throw new ProcessCancelledException(); } - } public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration, IHighlightingConsumer context) @@ -88,6 +90,7 @@ public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration tooManyArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); excessiveIndentationCheck.ExecuteIfEnabled(methodDeclaration, context); methodNamesNotMeaningfulCheck.ExecuteIfEnabled(methodDeclaration, context); + flagArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); } public override void VisitCSharpStatement(ICSharpStatement cSharpStatementParam, IHighlightingConsumer context) diff --git a/CleanCode/src/CleanCode/Features/ExtensionMethods.cs b/CleanCode/src/CleanCode/Features/ExtensionMethods.cs index b9fe754..353d886 100644 --- a/CleanCode/src/CleanCode/Features/ExtensionMethods.cs +++ b/CleanCode/src/CleanCode/Features/ExtensionMethods.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.CSharp.Tree; @@ -42,6 +43,39 @@ public static int GetChildrenDepth(this ITreeNode node) return childrenDepth; } + public static IEnumerable GetFlattenedHierarchyOfType(this ITreeNode root) where T : class, ITreeNode + { + var list = new List(); + + var rootAsType = root as T; + if (rootAsType != null) + { + list.Add(rootAsType); + } + + list.AddRange(root.GetChildrenRecursive()); + + return list; + } + + public static IEnumerable GetChildrenRecursive(this ITreeNode node) where T : ITreeNode + { + var nodeChildren = node.Children().ToList(); + + var list = new List(); + + var childOfType = nodeChildren.OfType(); + list.AddRange(childOfType); + + foreach (var childNode in nodeChildren) + { + var childrenOfType = GetChildrenRecursive(childNode); + list.AddRange(childrenOfType); + } + + return list; + } + private static bool IsNodeThatIncreasesDepth(ITreeNode node) { if (node is IIfStatement) @@ -136,7 +170,7 @@ private static IType GetClosedType(ResolveResultWithInfo resolveResultWithInfo, return closedType; } - private static ResolveResultWithInfo GetResolveResult(IReference reference) + public static ResolveResultWithInfo GetResolveResult(this IReference reference) { if (reference.CurrentResolveResult != null) { diff --git a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs index 040065e..d71a7e4 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs @@ -87,6 +87,15 @@ public static string ExcessiveDepth { } } + /// + /// Looks up a localized string similar to This argument is used as a flag in the method. It usually means that the method has more than one responsibility.. + /// + public static string FlagArgument { + get { + return ResourceManager.GetString("FlagArgument", resourceCulture); + } + } + /// /// Looks up a localized string similar to The name of this method is too short to be meaningful.. /// diff --git a/CleanCode/src/CleanCode/Resources/Warnings.resx b/CleanCode/src/CleanCode/Resources/Warnings.resx index f51cc2a..7a89fab 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.resx +++ b/CleanCode/src/CleanCode/Resources/Warnings.resx @@ -138,4 +138,7 @@ The name of this method is too short to be meaningful. + + This argument is used as a flag in the method. It usually means that the method has more than one responsibility. + \ No newline at end of file diff --git a/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj b/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj index 68dabb3..e433496 100644 --- a/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj +++ b/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj @@ -11,8 +11,7 @@ NuGet.Packager NuGet.Packager v4.0 - - + 512 diff --git a/CleanCode/src/NuGet.Packager/Package.nuspec b/CleanCode/src/NuGet.Packager/Package.nuspec index 83fabdc..e5131de 100644 --- a/CleanCode/src/NuGet.Packager/Package.nuspec +++ b/CleanCode/src/NuGet.Packager/Package.nuspec @@ -2,7 +2,7 @@ CleanCode - 4.0.0.2 + 4.0.0.3 CleanCode Hadi Hariri, Matt Ellis, SuperJMN Hadi Hariri, Matt Ellis From c3cd39b20b163b0e8d2abb7b995207bfdd2abb72 Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Mon, 23 Jun 2014 09:08:11 +0200 Subject: [PATCH 11/50] Untracked files :S --- .../FlagArguments/FlagArgumentsCheck.cs | 98 +++++++++++++++++++ .../Features/FlagArguments/Highlighting.cs | 69 +++++++++++++ ...nvalidateOnMaximumMethodArgumentsChange.cs | 46 +++++++++ 3 files changed, 213 insertions(+) create mode 100644 CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs create mode 100644 CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs create mode 100644 CleanCode/src/CleanCode/Features/FlagArguments/InvalidateOnMaximumMethodArgumentsChange.cs diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs new file mode 100644 index 0000000..8a4e6bf --- /dev/null +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs @@ -0,0 +1,98 @@ +using System.Linq; +using CleanCode.Resources; +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Psi; +using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Daemon.CSharp.Stages; +using JetBrains.ReSharper.Psi.Tree; +using System.Collections.Generic; +using System.Diagnostics; +using JetBrains.ReSharper.Psi.Util; +using IType = JetBrains.ReSharper.Psi.IType; + + +namespace CleanCode.Features.FlagArguments +{ + public class FlagArgumentsCheck : SimpleCheck + { + public FlagArgumentsCheck(IContextBoundSettingsStore settingsStore) + : base(settingsStore) + { + } + + protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingConsumer consumer) + { + var parameterDeclarations = statement.ParameterDeclarations; + + foreach (var parameterDeclaration in parameterDeclarations) + { + if (IsFlagArgument(parameterDeclaration, statement.Body)) + { + AddHighlighting(consumer, parameterDeclaration); + } + } + } + + private static void AddHighlighting(IHighlightingConsumer consumer, ICSharpParameterDeclaration parameterDeclaration) + { + var highlighting = new Highlighting(Warnings.FlagArgument); + consumer.AddHighlighting(highlighting, parameterDeclaration.GetDocumentRange()); + } + + private static bool IsFlagArgument(ITypeOwnerDeclaration typeOwnerDeclaration, ITreeNode node) + { + if (IsOfTypeThatCanBeUsedAsFlag(typeOwnerDeclaration)) + { + var references = GetReferencesTo(typeOwnerDeclaration.DeclaredElement, node); + return references.Any(); + } + + return false; + } + + private static bool IsOfTypeThatCanBeUsedAsFlag(ITypeOwnerDeclaration arg) + { + var type = arg.Type; + return type.IsBool() || type.IsEnumType(); + } + + private static IEnumerable GetReferencesTo(IDeclaredElement declaredElement, ITreeNode body) + { + var ifStatements = body.GetChildrenRecursive(); + + var allConditions = ifStatements.Select(statement => statement.Condition); + + var allReferencesInConditions = + allConditions.SelectMany(expression => expression.GetFlattenedHierarchyOfType()); + + return GetReferencesToArgument(allReferencesInConditions, declaredElement); + } + + private static IEnumerable GetReferencesToArgument(IEnumerable allReferencesInConditions, IDeclaredElement declaredElementInArgument) + { + return allReferencesInConditions.Where(reference => IsReferenceToArgument(reference, declaredElementInArgument)); + } + + private static bool IsReferenceToArgument(IReferenceExpression r, IDeclaredElement toFind) + { + var resolveResultWithInfo = r.Reference.GetResolveResult(); + var declaredElement = resolveResultWithInfo.DeclaredElement; + + Debug.Assert(declaredElement != null, "declaredElement != null"); + + return declaredElement.ShortName == toFind.ShortName; + } + + protected override int Threshold + { + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); } + } + + protected override bool IsEnabled + { + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsEnabled); } + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs b/CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs new file mode 100644 index 0000000..788f939 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs @@ -0,0 +1,69 @@ +#region License +// Copyright (C) 2012 Hadi Hariri and Contributors +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall +// be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT +// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using CleanCode.Features.FlagArguments; +using JetBrains.ReSharper.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, + HighlightingGroupIds.CodeSmell, "Flag Argument", "An argument that is used as a flag.", + Severity.WARNING, false)] + +namespace CleanCode.Features.FlagArguments +{ + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class Highlighting : IHighlighting + { + internal const string SeverityID = "FlagArguments"; + private readonly string tooltip; + + public Highlighting(string toolTip) + { + tooltip = toolTip; + } + + public string ToolTip + { + get { return tooltip; } + } + + public string ErrorStripeToolTip + { + get { return tooltip; } + } + + public int NavigationOffsetPatch + { + get { return 0; } + } + + public bool IsValid() + { + return true; + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/InvalidateOnMaximumMethodArgumentsChange.cs b/CleanCode/src/CleanCode/Features/FlagArguments/InvalidateOnMaximumMethodArgumentsChange.cs new file mode 100644 index 0000000..9434d2f --- /dev/null +++ b/CleanCode/src/CleanCode/Features/FlagArguments/InvalidateOnMaximumMethodArgumentsChange.cs @@ -0,0 +1,46 @@ +#region License +// Copyright (C) 2012 Hadi Hariri and Contributors +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall +// be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT +// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.DataFlow; +using JetBrains.ProjectModel; +using JetBrains.ReSharper.Daemon; + +namespace CleanCode.Features.FlagArguments +{ + [SolutionComponent] + public class InvalidateOnMaximumMethodArgumentsChange + { + public InvalidateOnMaximumMethodArgumentsChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + { + var maxArguments = + settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); + settingsStore.AdviseChange(lifetime, maxArguments, daemon.Invalidate); + } + } +} \ No newline at end of file From 2cbb68fa86bb4c5f7aea9ece6da0131483c02ae1 Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Mon, 23 Jun 2014 15:58:33 +0200 Subject: [PATCH 12/50] New features: Complex Expression check. Fixes: naming and settings that were mistakenly associated to features that didn't match. --- CleanCode/src/CleanCode/CleanCode.8.2.csproj | 6 +- .../CleanCode/CleanCodeDaemonStageProcess.cs | 28 +++++++- .../ChainedReferencesCheck.cs | 4 +- .../Features/ClassTooBig/ClassTooBigCheck.cs | 4 +- .../ExpressionTooComplexCheck.cs | 43 ++++++++++++ .../ComplexExpression/Highlighting.cs | 70 +++++++++++++++++++ .../InvalidateOnComplexExpressionChange.cs} | 24 +++---- .../ExcessiveIndentationCheck.cs | 4 +- .../FlagArguments/FlagArgumentsCheck.cs | 20 +++--- ...eck.cs => MethodNameNotMeaningfulCheck.cs} | 8 +-- .../MethodTooLong/MethodTooLongCheck.cs | 4 +- .../src/CleanCode/Features/SimpleCheck.cs | 30 +++++--- .../TooManyDependenciesCheck.cs | 4 +- .../TooManyMethodArgumentsCheck.cs | 4 +- .../CleanCode/Resources/Settings.Designer.cs | 22 +++++- .../src/CleanCode/Resources/Settings.resx | 8 ++- .../CleanCode/Resources/Warnings.Designer.cs | 9 +++ .../src/CleanCode/Resources/Warnings.resx | 3 + .../CleanCode/Settings/CleanCodeSettings.cs | 8 +++ .../CleanCode/Settings/OptionsViewModel.cs | 27 ++++--- 20 files changed, 266 insertions(+), 64 deletions(-) create mode 100644 CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs create mode 100644 CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs rename CleanCode/src/CleanCode/Features/{FlagArguments/InvalidateOnMaximumMethodArgumentsChange.cs => ComplexExpression/InvalidateOnComplexExpressionChange.cs} (67%) rename CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/{MethodNamesNotMeaningfulCheck.cs => MethodNameNotMeaningfulCheck.cs} (74%) diff --git a/CleanCode/src/CleanCode/CleanCode.8.2.csproj b/CleanCode/src/CleanCode/CleanCode.8.2.csproj index bb9fb63..7437b2a 100644 --- a/CleanCode/src/CleanCode/CleanCode.8.2.csproj +++ b/CleanCode/src/CleanCode/CleanCode.8.2.csproj @@ -57,6 +57,9 @@ + + + @@ -67,11 +70,10 @@ Code - - + Code diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 08bba07..162c404 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -44,6 +44,8 @@ namespace CleanCode { + using CleanCode.Features.ComplexExpression; + public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase { private readonly IDaemonProcess daemonProcess; @@ -54,9 +56,10 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase private readonly TooManyMethodArgumentsCheck tooManyArgumentsCheck; private readonly ExcessiveIndentationCheck excessiveIndentationCheck; private readonly TooManyDependenciesCheck tooManyDependenciesCheck; - private readonly MethodNamesNotMeaningfulCheck methodNamesNotMeaningfulCheck; + private readonly MethodNameNotMeaningfulCheck methodNamesNotMeaningfulCheck; private readonly ChainedReferencesCheck chainedReferencesCheck; private readonly FlagArgumentsCheck flagArgumentsCheck; + private readonly ComplexExpressionCheck complexExpressionCheck; public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile file, IContextBoundSettingsStore settingsStore) : base(daemonProcess, file) @@ -70,9 +73,10 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil tooManyArgumentsCheck = new TooManyMethodArgumentsCheck(settingsStore); excessiveIndentationCheck = new ExcessiveIndentationCheck(settingsStore); tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); - methodNamesNotMeaningfulCheck = new MethodNamesNotMeaningfulCheck(settingsStore); + methodNamesNotMeaningfulCheck = new MethodNameNotMeaningfulCheck(settingsStore); chainedReferencesCheck = new ChainedReferencesCheck(settingsStore); flagArgumentsCheck = new FlagArgumentsCheck(settingsStore); + complexExpressionCheck = new ComplexExpressionCheck(settingsStore); } public override void Execute(Action commiter) @@ -107,5 +111,25 @@ public override void VisitClassDeclaration(IClassDeclaration classDeclaration, I { classTooBigCheck.ExecuteIfEnabled(classDeclaration, context); } + + public override void VisitIfStatement(IIfStatement ifStatementParam, IHighlightingConsumer context) + { + this.complexExpressionCheck.ExecuteIfEnabled(ifStatementParam.Condition, context); + } + + public override void VisitWhileStatement(IWhileStatement whileStatementParam, IHighlightingConsumer context) + { + this.complexExpressionCheck.ExecuteIfEnabled(whileStatementParam.Condition, context); + } + + public override void VisitForStatement(IForStatement forStatementParam, IHighlightingConsumer context) + { + this.complexExpressionCheck.ExecuteIfEnabled(forStatementParam.Condition, context); + } + + public override void VisitDoStatement(IDoStatement doStatementParam, IHighlightingConsumer context) + { + this.complexExpressionCheck.ExecuteIfEnabled(doStatementParam.Condition, context); + } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs index d8cd175..7717813 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs @@ -79,12 +79,12 @@ private void HightlightReferenceExpressionIfNeeded(IReferenceExpression referenc protected override int Threshold { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); } } protected override bool IsEnabled { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesEnabled); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesEnabled); } } public static void AddHighlightning(IReferenceExpression reference, IHighlightingConsumer consumer) diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs index 1334687..904c043 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs @@ -31,12 +31,12 @@ protected override void ExecuteCore(IClassDeclaration statement, IHighlightingCo protected override int Threshold { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigMaximum); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigMaximum); } } protected override bool IsEnabled { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigEnabled); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs new file mode 100644 index 0000000..aed03e3 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs @@ -0,0 +1,43 @@ +namespace CleanCode.Features.ComplexExpression +{ + using System.Linq; + + using CleanCode.Resources; + using CleanCode.Settings; + + using JetBrains.Application.Settings; + using JetBrains.ReSharper.Daemon.CSharp.Stages; + using JetBrains.ReSharper.Daemon.Stages; + using JetBrains.ReSharper.Psi.CSharp.Tree; + using JetBrains.ReSharper.Psi.Tree; + + public class ComplexExpressionCheck : SimpleCheck + { + public ComplexExpressionCheck(IContextBoundSettingsStore settingsStore) + : base(settingsStore) + { + } + + protected override void ExecuteCore(IExpression statement, IHighlightingConsumer consumer) + { + var maxExpressions = this.Threshold; + var depth = statement.GetChildrenRecursive().Count(); + + if (depth > maxExpressions) + { + var highlighting = new ExcessiveIndentation.Highlighting(Warnings.ExpressionTooComplex); + consumer.AddHighlighting(highlighting, statement.GetDocumentRange()); + } + } + + protected override int Threshold + { + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ComplexExpressionMaximum); } + } + + protected override bool IsEnabled + { + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ComplexExpressionEnabled); } + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs new file mode 100644 index 0000000..8e95e6b --- /dev/null +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs @@ -0,0 +1,70 @@ +#region License +// Copyright (C) 2012 Hadi Hariri and Contributors +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall +// be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT +// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using CleanCode.Features.ComplexExpression; +using JetBrains.ReSharper.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly:RegisterConfigurableSeverity(Highlighting.SeverityID, null, + HighlightingGroupIds.CodeSmell, "Expression Too Complex", "The expression contains too complex.", + Severity.WARNING, false)] + +namespace CleanCode.Features.ComplexExpression +{ + + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class Highlighting : IHighlighting + { + internal const string SeverityID = "ComplexExpression"; + private readonly string tooltip; + + public Highlighting(string toolTip) + { + this.tooltip = toolTip; + } + + public string ToolTip + { + get { return this.tooltip; } + } + + public string ErrorStripeToolTip + { + get { return this.tooltip; } + } + + public int NavigationOffsetPatch + { + get { return 0; } + } + + public bool IsValid() + { + return true; + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/InvalidateOnMaximumMethodArgumentsChange.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs similarity index 67% rename from CleanCode/src/CleanCode/Features/FlagArguments/InvalidateOnMaximumMethodArgumentsChange.cs rename to CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs index 9434d2f..e842cd9 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/InvalidateOnMaximumMethodArgumentsChange.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs @@ -25,22 +25,22 @@ // OR OTHER DEALINGS IN THE SOFTWARE. #endregion -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; - -namespace CleanCode.Features.FlagArguments +namespace CleanCode.Features.ComplexExpression { + using CleanCode.Settings; + + using JetBrains.Application.Settings; + using JetBrains.DataFlow; + using JetBrains.ProjectModel; + using JetBrains.ReSharper.Daemon; + [SolutionComponent] - public class InvalidateOnMaximumMethodArgumentsChange + public class InvalidateOnComplexExpressionChange { - public InvalidateOnMaximumMethodArgumentsChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + public InvalidateOnComplexExpressionChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) { - var maxArguments = - settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); - settingsStore.AdviseChange(lifetime, maxArguments, daemon.Invalidate); + var maxDepth = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.ComplexExpressionMaximum); + settingsStore.AdviseChange(lifetime, maxDepth, daemon.Invalidate); } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs index 88d19a0..a854141 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs @@ -29,12 +29,12 @@ protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingC protected override int Threshold { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationMaximum); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationMaximum); } } protected override bool IsEnabled { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationEnabled); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs index 8a4e6bf..0f5cc06 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs @@ -10,12 +10,10 @@ using System.Collections.Generic; using System.Diagnostics; using JetBrains.ReSharper.Psi.Util; -using IType = JetBrains.ReSharper.Psi.IType; - namespace CleanCode.Features.FlagArguments { - public class FlagArgumentsCheck : SimpleCheck + public class FlagArgumentsCheck : SimpleCheckBase { public FlagArgumentsCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) @@ -75,9 +73,14 @@ private static IEnumerable GetReferencesToArgument(IEnumer return allReferencesInConditions.Where(reference => IsReferenceToArgument(reference, declaredElementInArgument)); } - private static bool IsReferenceToArgument(IReferenceExpression r, IDeclaredElement toFind) + private static bool IsReferenceToArgument(IReferenceExpression referenceExpression, IDeclaredElement toFind) { - var resolveResultWithInfo = r.Reference.GetResolveResult(); + if (referenceExpression == null) + { + return false; + } + + var resolveResultWithInfo = referenceExpression.Reference.GetResolveResult(); var declaredElement = resolveResultWithInfo.DeclaredElement; Debug.Assert(declaredElement != null, "declaredElement != null"); @@ -85,14 +88,9 @@ private static bool IsReferenceToArgument(IReferenceExpression r, IDeclaredEleme return declaredElement.ShortName == toFind.ShortName; } - protected override int Threshold - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); } - } - protected override bool IsEnabled { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsEnabled); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.FlagArgumentsEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNamesNotMeaningfulCheck.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs similarity index 74% rename from CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNamesNotMeaningfulCheck.cs rename to CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs index e04e8be..3023287 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNamesNotMeaningfulCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs @@ -8,9 +8,9 @@ namespace CleanCode.Features.MethodNameNotMeaningful { - public class MethodNamesNotMeaningfulCheck : SimpleCheck + public class MethodNameNotMeaningfulCheck : SimpleCheck { - public MethodNamesNotMeaningfulCheck(IContextBoundSettingsStore settingsStore) + public MethodNameNotMeaningfulCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } @@ -35,12 +35,12 @@ protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingC protected override int Threshold { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimum); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimum); } } protected override bool IsEnabled { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimumEnabled); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimumEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs index 30f4d81..dea32f6 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs @@ -29,12 +29,12 @@ protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingC protected override int Threshold { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongMaximum); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongMaximum); } } protected override bool IsEnabled { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongEnabled); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/SimpleCheck.cs b/CleanCode/src/CleanCode/Features/SimpleCheck.cs index db2a5b4..80eb206 100644 --- a/CleanCode/src/CleanCode/Features/SimpleCheck.cs +++ b/CleanCode/src/CleanCode/Features/SimpleCheck.cs @@ -4,34 +4,44 @@ namespace CleanCode.Features { - public abstract class SimpleCheck where TElement : ITreeNode + public abstract class SimpleCheckBase + where TElement : ITreeNode { private readonly IContextBoundSettingsStore settingsStore; - protected SimpleCheck(IContextBoundSettingsStore settingsStore) + protected SimpleCheckBase(IContextBoundSettingsStore settingsStore) { this.settingsStore = settingsStore; } + protected abstract bool IsEnabled { get; } + + protected IContextBoundSettingsStore SettingsStore + { + get { return this.settingsStore; } + } + public void ExecuteIfEnabled(TElement methodDeclaration, IHighlightingConsumer context) { - if (!IsEnabled) + if (!this.IsEnabled) { return; } - ExecuteCore(methodDeclaration, context); + this.ExecuteCore(methodDeclaration, context); } protected abstract void ExecuteCore(TElement statement, IHighlightingConsumer consumer); + } - protected abstract TThreshold Threshold { get; } - - protected abstract bool IsEnabled { get; } - - protected IContextBoundSettingsStore SettingsStore + public abstract class SimpleCheck : SimpleCheckBase + where TElement : ITreeNode + { + protected SimpleCheck(IContextBoundSettingsStore settingsStore) + : base(settingsStore) { - get { return settingsStore; } } + + protected abstract TThreshold Threshold { get; } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs index 344fef7..36fc6aa 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs @@ -36,12 +36,12 @@ protected override void ExecuteCore(IConstructorDeclaration statement, IHighligh protected override int Threshold { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximum); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximum); } } protected override bool IsEnabled { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximumEnabled); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximumEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs index f2242c0..afe6f2e 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs @@ -29,12 +29,12 @@ protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingC protected override int Threshold { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); } } protected override bool IsEnabled { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsEnabled); } + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs index 1a4dba5..89efe1f 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs @@ -78,6 +78,24 @@ public static string ClassTooBigCheck { } } + /// + /// Looks up a localized string similar to Complex expression check (conditions). + /// + public static string ComplexExpressionCheck { + get { + return ResourceManager.GetString("ComplexExpressionCheck", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Set the maximum of expressions that can be part of a condition. + /// + public static string ComplexExpressionMaximum { + get { + return ResourceManager.GetString("ComplexExpressionMaximum", resourceCulture); + } + } + /// /// Looks up a localized string similar to Maximum level of nesting. /// @@ -142,7 +160,7 @@ public static string MethodTooLongCheck { } /// - /// Looks up a localized string similar to Minimum lenght for the name of methods. + /// Looks up a localized string similar to Minimum length for the name of methods. /// public static string MinimumMethodNameLength { get { @@ -151,7 +169,7 @@ public static string MinimumMethodNameLength { } /// - /// Looks up a localized string similar to Minimum Method Name Lenght. + /// Looks up a localized string similar to Minimum Method Name Length. /// public static string MinimumMethodNameLengthCheck { get { diff --git a/CleanCode/src/CleanCode/Resources/Settings.resx b/CleanCode/src/CleanCode/Resources/Settings.resx index 64db111..5847b93 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.resx +++ b/CleanCode/src/CleanCode/Resources/Settings.resx @@ -165,4 +165,10 @@ Minimum Method Name Length - + + Complex expression check (conditions) + + + Set the maximum of expressions that can be part of a condition + + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs index d71a7e4..289dc02 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs @@ -87,6 +87,15 @@ public static string ExcessiveDepth { } } + /// + /// Looks up a localized string similar to This expression is too complex to be legible. Please, simplify it.. + /// + public static string ExpressionTooComplex { + get { + return ResourceManager.GetString("ExpressionTooComplex", resourceCulture); + } + } + /// /// Looks up a localized string similar to This argument is used as a flag in the method. It usually means that the method has more than one responsibility.. /// diff --git a/CleanCode/src/CleanCode/Resources/Warnings.resx b/CleanCode/src/CleanCode/Resources/Warnings.resx index 7a89fab..6a14782 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.resx +++ b/CleanCode/src/CleanCode/Resources/Warnings.resx @@ -141,4 +141,7 @@ This argument is used as a flag in the method. It usually means that the method has more than one responsibility. + + This expression is too complex to be legible. Please, simplify it. + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs index 7cad180..f6b4cdc 100644 --- a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs +++ b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs @@ -69,5 +69,13 @@ public class CleanCodeSettings public bool MethodNameNotMeaningfulMinimumEnabled { get; set; } [SettingsEntry(4, "MethodNameNotMeaningfulMinimum")] public int MethodNameNotMeaningfulMinimum { get; set; } + + [SettingsEntry(true, "FlagArgumentsEnabled")] + public bool FlagArgumentsEnabled { get; set; } + + [SettingsEntry(true, "ComplexExpressionEnabled")] + public bool ComplexExpressionEnabled { get; set; } + [SettingsEntry(1, "ComplexExpressionMaximum")] + public int ComplexExpressionMaximum { get; set; } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs index 02047af..efbb82d 100644 --- a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs +++ b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs @@ -64,7 +64,7 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) viewModels.Add(tooManyMethodArguments); - var enabledMaxDepth = new SingleCheckSettingViewModel( + var excessiveDepth = new SingleCheckSettingViewModel( settings, e => e.TooManyDependenciesMaximumEnabled, e => e.ExcessiveIndentationMaximum) @@ -73,9 +73,9 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) ValueDescription = Resources.Settings.ExcessiveDepth, }; - viewModels.Add(enabledMaxDepth); + viewModels.Add(excessiveDepth); - var enableClassTooBig = new SingleCheckSettingViewModel( + var classTooBig = new SingleCheckSettingViewModel( settings, e => e.ClassTooBigEnabled, e => e.ClassTooBigMaximum) @@ -84,9 +84,9 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) ValueDescription = Resources.Settings.ClassTooBig, }; - viewModels.Add(enableClassTooBig); + viewModels.Add(classTooBig); - var enableChainedReferences = new SingleCheckSettingViewModel( + var chainedReferences = new SingleCheckSettingViewModel( settings, e => e.TooManyChainedReferencesEnabled, e => e.TooManyChainedReferencesMaximum) @@ -95,9 +95,9 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) ValueDescription = Resources.Settings.MaxChainedReferences, }; - viewModels.Add(enableChainedReferences); + viewModels.Add(chainedReferences); - var enableMinimumMethodNameLength = new SingleCheckSettingViewModel( + var methodNameLength = new SingleCheckSettingViewModel( settings, e => e.MethodNameNotMeaningfulMinimumEnabled, e => e.MethodNameNotMeaningfulMinimum) @@ -106,7 +106,18 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) ValueDescription = Resources.Settings.MinimumMethodNameLength, }; - viewModels.Add(enableMinimumMethodNameLength); + viewModels.Add(methodNameLength); + + var complexCondition = new SingleCheckSettingViewModel( + settings, + e => e.ComplexExpressionEnabled, + e => e.ComplexExpressionMaximum) + { + IsEnabledDescription = Resources.Settings.ComplexExpressionCheck, + ValueDescription = Resources.Settings.ComplexExpressionMaximum, + }; + + viewModels.Add(complexCondition); return viewModels; } From 00a1413d4965ec9ce8f8f8b84c076b50a0cab137 Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Tue, 24 Jun 2014 00:31:47 +0200 Subject: [PATCH 13/50] Settings for new features. --- CleanCode/src/CleanCode/CleanCode.8.2.csproj | 4 +- .../CleanCode/Resources/Settings.Designer.cs | 9 ++ .../src/CleanCode/Resources/Settings.resx | 3 + .../Settings/CheckSettingViewModel.cs | 32 +++++++ .../Settings/CheckTemplateSelector.cs | 31 +++++++ .../src/CleanCode/Settings/OptionsPage.xaml | 86 ++++++++++++------- .../CleanCode/Settings/OptionsViewModel.cs | 27 ++++-- .../Settings/SingleCheckSettingViewModel.cs | 43 ---------- .../ThresholdCheckSettingViewModel.cs | 28 ++++++ 9 files changed, 177 insertions(+), 86 deletions(-) create mode 100644 CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs create mode 100644 CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs delete mode 100644 CleanCode/src/CleanCode/Settings/SingleCheckSettingViewModel.cs create mode 100644 CleanCode/src/CleanCode/Settings/ThresholdCheckSettingViewModel.cs diff --git a/CleanCode/src/CleanCode/CleanCode.8.2.csproj b/CleanCode/src/CleanCode/CleanCode.8.2.csproj index 7437b2a..87a962e 100644 --- a/CleanCode/src/CleanCode/CleanCode.8.2.csproj +++ b/CleanCode/src/CleanCode/CleanCode.8.2.csproj @@ -111,12 +111,14 @@ True Settings.resx + OptionsPage.xaml - + + diff --git a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs index 89efe1f..94ae2e1 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs @@ -114,6 +114,15 @@ public static string ExcessiveDepthCheck { } } + /// + /// Looks up a localized string similar to Flag Arguments Check. + /// + public static string FlagArgumentsCheck { + get { + return ResourceManager.GetString("FlagArgumentsCheck", resourceCulture); + } + } + /// /// Looks up a localized string similar to Maximum Chained References. /// diff --git a/CleanCode/src/CleanCode/Resources/Settings.resx b/CleanCode/src/CleanCode/Resources/Settings.resx index 5847b93..b5b06df 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.resx +++ b/CleanCode/src/CleanCode/Resources/Settings.resx @@ -171,4 +171,7 @@ Set the maximum of expressions that can be part of a condition + + Flag Arguments Check + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs b/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs new file mode 100644 index 0000000..8012bef --- /dev/null +++ b/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs @@ -0,0 +1,32 @@ +using System; +using System.Linq.Expressions; +using JetBrains.Application.Settings; + +namespace CleanCode.Settings +{ + public class CheckSettingViewModel : ViewModel + { + private readonly Expression> isEnabledSelector; + + protected readonly IContextBoundSettingsStore Settings; + + public CheckSettingViewModel(IContextBoundSettingsStore settings, Expression> isEnabledSelector) + { + this.Settings = settings; + this.isEnabledSelector = isEnabledSelector; + + } + + public bool IsEnabled + { + get { return Settings.GetValue(isEnabledSelector); } + set + { + Settings.SetValue(isEnabledSelector, value); + OnPropertyChanged(); + } + } + + public string IsEnabledDescription { get; set; } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs b/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs new file mode 100644 index 0000000..53e83a1 --- /dev/null +++ b/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs @@ -0,0 +1,31 @@ +using System.Windows; +using System.Windows.Controls; + +namespace CleanCode.Settings +{ + public class CheckTemplateSelector : DataTemplateSelector + { + public DataTemplate ThresholdCheckTemplate { get; set; } + public DataTemplate BasicCheckTemplate { get; set; } + + public override DataTemplate SelectTemplate(object item, DependencyObject container) + { + var type = item.GetType(); + + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ThresholdCheckSettingViewModel<>)) + { + return ThresholdCheckTemplate; + } + if (item is CheckSettingViewModel) + { + return BasicCheckTemplate; + } + return base.SelectTemplate(item, container); + } + + bool IsTypeof(object t) + { + return (t is T); + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml index c37f2d4..9b79b7e 100644 --- a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml +++ b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml @@ -7,45 +7,65 @@ mc:Ignorable="d" d:DataContext="{d:DesignInstance settings:OptionsViewModel}" d:DesignWidth="529" d:DesignHeight="126"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs index efbb82d..b92e930 100644 --- a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs +++ b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs @@ -33,7 +33,7 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) { var viewModels = new ArrayList(); - var methodTooLong = new SingleCheckSettingViewModel( + var methodTooLong = new ThresholdCheckSettingViewModel( settings, codeSettings => codeSettings.MethodTooLongEnabled, codeSettings => codeSettings.MethodTooLongMaximum) @@ -43,7 +43,7 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) }; viewModels.Add(methodTooLong); - var tooManyDependencies = new SingleCheckSettingViewModel( + var tooManyDependencies = new ThresholdCheckSettingViewModel( settings, e => e.TooManyDependenciesMaximumEnabled, e => e.TooManyDependenciesMaximum) @@ -53,7 +53,7 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) }; viewModels.Add(tooManyDependencies); - var tooManyMethodArguments = new SingleCheckSettingViewModel( + var tooManyMethodArguments = new ThresholdCheckSettingViewModel( settings, e => e.TooManyMethodArgumentsEnabled, e => e.TooManyMethodArgumentsMaximum) @@ -64,7 +64,7 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) viewModels.Add(tooManyMethodArguments); - var excessiveDepth = new SingleCheckSettingViewModel( + var excessiveDepth = new ThresholdCheckSettingViewModel( settings, e => e.TooManyDependenciesMaximumEnabled, e => e.ExcessiveIndentationMaximum) @@ -75,7 +75,7 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) viewModels.Add(excessiveDepth); - var classTooBig = new SingleCheckSettingViewModel( + var classTooBig = new ThresholdCheckSettingViewModel( settings, e => e.ClassTooBigEnabled, e => e.ClassTooBigMaximum) @@ -86,7 +86,7 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) viewModels.Add(classTooBig); - var chainedReferences = new SingleCheckSettingViewModel( + var chainedReferences = new ThresholdCheckSettingViewModel( settings, e => e.TooManyChainedReferencesEnabled, e => e.TooManyChainedReferencesMaximum) @@ -97,7 +97,7 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) viewModels.Add(chainedReferences); - var methodNameLength = new SingleCheckSettingViewModel( + var methodNameLength = new ThresholdCheckSettingViewModel( settings, e => e.MethodNameNotMeaningfulMinimumEnabled, e => e.MethodNameNotMeaningfulMinimum) @@ -108,17 +108,26 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) viewModels.Add(methodNameLength); - var complexCondition = new SingleCheckSettingViewModel( + var complexCondition = new ThresholdCheckSettingViewModel( settings, e => e.ComplexExpressionEnabled, e => e.ComplexExpressionMaximum) { - IsEnabledDescription = Resources.Settings.ComplexExpressionCheck, + IsEnabledDescription = Resources.Settings.ComplexExpressionCheck, ValueDescription = Resources.Settings.ComplexExpressionMaximum, }; viewModels.Add(complexCondition); + var flagArguments = new CheckSettingViewModel( + settings, + e => e.FlagArgumentsEnabled) + { + IsEnabledDescription = Resources.Settings.FlagArgumentsCheck, + }; + + viewModels.Add(flagArguments); + return viewModels; } } diff --git a/CleanCode/src/CleanCode/Settings/SingleCheckSettingViewModel.cs b/CleanCode/src/CleanCode/Settings/SingleCheckSettingViewModel.cs deleted file mode 100644 index ca28c92..0000000 --- a/CleanCode/src/CleanCode/Settings/SingleCheckSettingViewModel.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Linq.Expressions; -using JetBrains.Application.Settings; - -namespace CleanCode.Settings -{ - public class SingleCheckSettingViewModel : ViewModel - { - private readonly Expression> isEnabledSelector; - private readonly Expression> valueSelector; - private readonly IContextBoundSettingsStore settings; - - public SingleCheckSettingViewModel(IContextBoundSettingsStore settings, Expression> isEnabledSelector, Expression> valueSelector) - { - this.settings = settings; - this.isEnabledSelector = isEnabledSelector; - this.valueSelector = valueSelector; - } - - public bool IsEnabled - { - get { return settings.GetValue(isEnabledSelector); } - set - { - settings.SetValue(isEnabledSelector, value); - OnPropertyChanged(); - } - } - - public TType Value - { - get { return settings.GetValue(valueSelector); } - set - { - settings.SetValue(valueSelector, value); - OnPropertyChanged(); - } - } - - public string IsEnabledDescription { get; set; } - public string ValueDescription { get; set; } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/ThresholdCheckSettingViewModel.cs b/CleanCode/src/CleanCode/Settings/ThresholdCheckSettingViewModel.cs new file mode 100644 index 0000000..6fc9d80 --- /dev/null +++ b/CleanCode/src/CleanCode/Settings/ThresholdCheckSettingViewModel.cs @@ -0,0 +1,28 @@ +using System; +using System.Linq.Expressions; +using JetBrains.Application.Settings; + +namespace CleanCode.Settings +{ + public class ThresholdCheckSettingViewModel : CheckSettingViewModel + { + protected Expression> valueSelector; + + public ThresholdCheckSettingViewModel(IContextBoundSettingsStore settings, Expression> isEnabledSelector, Expression> valueSelector) : base(settings, isEnabledSelector) + { + this.valueSelector = valueSelector; + } + + public TType Value + { + get { return Settings.GetValue(valueSelector); } + set + { + Settings.SetValue(valueSelector, value); + OnPropertyChanged(); + } + } + + public string ValueDescription { get; set; } + } +} \ No newline at end of file From c52eba54448d8bcd1791269d65cc8c357b132e31 Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Tue, 24 Jun 2014 15:08:20 +0200 Subject: [PATCH 14/50] New feature: Hollow Type Names. --- CleanCode/src/CleanCode/CleanCode.8.2.csproj | 3 + .../CleanCode/CleanCodeDaemonStageProcess.cs | 8 ++- .../ChainedReferencesCheck.cs | 6 +- .../Features/ClassTooBig/ClassTooBigCheck.cs | 6 +- .../ExpressionTooComplexCheck.cs | 6 +- .../ExcessiveIndentationCheck.cs | 6 +- .../FlagArguments/FlagArgumentsCheck.cs | 6 +- .../Features/HollowNames/Highlighting.cs | 72 +++++++++++++++++++ .../InvalidateOnMaximumLinesChange.cs | 46 ++++++++++++ .../HollowNames/MethodTooLongCheck.cs | 49 +++++++++++++ .../MethodNameNotMeaningfulCheck.cs | 8 +-- .../MethodTooLong/MethodTooLongCheck.cs | 6 +- .../src/CleanCode/Features/SimpleCheck.cs | 2 +- .../TooManyDependenciesCheck.cs | 6 +- .../TooManyMethodArgumentsCheck.cs | 6 +- .../CleanCode/Resources/Warnings.Designer.cs | 9 +++ .../src/CleanCode/Resources/Warnings.resx | 3 + .../CleanCode/Settings/CleanCodeSettings.cs | 5 +- CleanCode/src/NuGet.Packager/Package.nuspec | 2 +- 19 files changed, 222 insertions(+), 33 deletions(-) create mode 100644 CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs create mode 100644 CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnMaximumLinesChange.cs create mode 100644 CleanCode/src/CleanCode/Features/HollowNames/MethodTooLongCheck.cs diff --git a/CleanCode/src/CleanCode/CleanCode.8.2.csproj b/CleanCode/src/CleanCode/CleanCode.8.2.csproj index 87a962e..ec294ad 100644 --- a/CleanCode/src/CleanCode/CleanCode.8.2.csproj +++ b/CleanCode/src/CleanCode/CleanCode.8.2.csproj @@ -71,6 +71,9 @@ + + + diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 162c404..3daf026 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -45,6 +45,7 @@ namespace CleanCode { using CleanCode.Features.ComplexExpression; + using CleanCode.Features.HollowNames; public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase { @@ -60,6 +61,7 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase private readonly ChainedReferencesCheck chainedReferencesCheck; private readonly FlagArgumentsCheck flagArgumentsCheck; private readonly ComplexExpressionCheck complexExpressionCheck; + private readonly HollowNamesCheck hollowNamesCheck; public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile file, IContextBoundSettingsStore settingsStore) : base(daemonProcess, file) @@ -67,7 +69,7 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil this.daemonProcess = daemonProcess; this.settingsStore = settingsStore; - // Simple checks. + // TODO: This is starting to feel like a beach of Benidorm in July. Refactoring needed. methodTooLongCheck = new MethodTooLongCheck(settingsStore); classTooBigCheck = new ClassTooBigCheck(settingsStore); tooManyArgumentsCheck = new TooManyMethodArgumentsCheck(settingsStore); @@ -77,6 +79,7 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil chainedReferencesCheck = new ChainedReferencesCheck(settingsStore); flagArgumentsCheck = new FlagArgumentsCheck(settingsStore); complexExpressionCheck = new ComplexExpressionCheck(settingsStore); + hollowNamesCheck = new HollowNamesCheck(settingsStore); } public override void Execute(Action commiter) @@ -94,7 +97,7 @@ public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration tooManyArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); excessiveIndentationCheck.ExecuteIfEnabled(methodDeclaration, context); methodNamesNotMeaningfulCheck.ExecuteIfEnabled(methodDeclaration, context); - flagArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); + flagArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); } public override void VisitCSharpStatement(ICSharpStatement cSharpStatementParam, IHighlightingConsumer context) @@ -110,6 +113,7 @@ public override void VisitConstructorDeclaration(IConstructorDeclaration constru public override void VisitClassDeclaration(IClassDeclaration classDeclaration, IHighlightingConsumer context) { classTooBigCheck.ExecuteIfEnabled(classDeclaration, context); + hollowNamesCheck.ExecuteIfEnabled(classDeclaration, context); } public override void VisitIfStatement(IIfStatement ifStatementParam, IHighlightingConsumer context) diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs index 7717813..a6d8c61 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs @@ -20,11 +20,11 @@ public ChainedReferencesCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(ICSharpStatement statement, IHighlightingConsumer consumer) + protected override void ExecuteCore(ICSharpStatement typeExpression, IHighlightingConsumer consumer) { - if (statement != null && !statement.IsEmbeddedStatement) + if (typeExpression != null && !typeExpression.IsEmbeddedStatement) { - this.HighlightMethodChainsThatAreTooLong(statement, consumer); + this.HighlightMethodChainsThatAreTooLong(typeExpression, consumer); } } diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs index 904c043..eaf251a 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs @@ -15,14 +15,14 @@ public ClassTooBigCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IClassDeclaration statement, IHighlightingConsumer consumer) + protected override void ExecuteCore(IClassDeclaration typeExpression, IHighlightingConsumer consumer) { var maxLength = Threshold; - var statementCount = statement.CountChildren(); + var statementCount = typeExpression.CountChildren(); if (statementCount > maxLength) { - var declarationIdentifier = statement.NameIdentifier; + var declarationIdentifier = typeExpression.NameIdentifier; var documentRange = declarationIdentifier.GetDocumentRange(); var highlighting = new Highlighting(Warnings.ClassTooBig); consumer.AddHighlighting(highlighting, documentRange); diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs index aed03e3..d17ef78 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs @@ -18,15 +18,15 @@ public ComplexExpressionCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IExpression statement, IHighlightingConsumer consumer) + protected override void ExecuteCore(IExpression typeExpression, IHighlightingConsumer consumer) { var maxExpressions = this.Threshold; - var depth = statement.GetChildrenRecursive().Count(); + var depth = typeExpression.GetChildrenRecursive().Count(); if (depth > maxExpressions) { var highlighting = new ExcessiveIndentation.Highlighting(Warnings.ExpressionTooComplex); - consumer.AddHighlighting(highlighting, statement.GetDocumentRange()); + consumer.AddHighlighting(highlighting, typeExpression.GetDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs index a854141..6693d66 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs @@ -15,15 +15,15 @@ public ExcessiveIndentationCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) { var maxIndentation = Threshold; - var depth = statement.GetChildrenDepth(); + var depth = typeExpression.GetChildrenDepth(); if (depth > maxIndentation) { var highlighting = new Highlighting(Warnings.ExcessiveDepth); - consumer.AddHighlighting(highlighting, statement.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs index 0f5cc06..50b1241 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs @@ -20,13 +20,13 @@ public FlagArgumentsCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) { - var parameterDeclarations = statement.ParameterDeclarations; + var parameterDeclarations = typeExpression.ParameterDeclarations; foreach (var parameterDeclaration in parameterDeclarations) { - if (IsFlagArgument(parameterDeclaration, statement.Body)) + if (IsFlagArgument(parameterDeclaration, typeExpression.Body)) { AddHighlighting(consumer, parameterDeclaration); } diff --git a/CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs b/CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs new file mode 100644 index 0000000..3ee8a65 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs @@ -0,0 +1,72 @@ +#region License +// Copyright (C) 2012 Hadi Hariri and Contributors +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall +// be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT +// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using CleanCode.Features.HollowNames; + +using JetBrains.ReSharper.Daemon; + +[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, + HighlightingGroupIds.CodeSmell, "Hollow Type Name", "This type has a name that doesn't express its intent.", + Severity.SUGGESTION, false)] + +namespace CleanCode.Features.HollowNames +{ + using JetBrains.ReSharper.Daemon; + using JetBrains.ReSharper.Psi.CSharp; + + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class Highlighting : IHighlighting + { + internal const string SeverityID = "HollowTypeName"; + private readonly string tooltip; + + public Highlighting(string toolTip) + { + this.tooltip = toolTip; + } + + public string ToolTip + { + get { return this.tooltip; } + } + + public string ErrorStripeToolTip + { + get { return this.tooltip; } + } + + public int NavigationOffsetPatch + { + get { return 0; } + } + + public bool IsValid() + { + return true; + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnMaximumLinesChange.cs b/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnMaximumLinesChange.cs new file mode 100644 index 0000000..ec3bef9 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnMaximumLinesChange.cs @@ -0,0 +1,46 @@ +#region License +// Copyright (C) 2012 Hadi Hariri and Contributors +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall +// be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT +// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. +#endregion + +namespace CleanCode.Features.HollowNames +{ + using CleanCode.Settings; + + using JetBrains.Application.Settings; + using JetBrains.DataFlow; + using JetBrains.ProjectModel; + using JetBrains.ReSharper.Daemon; + + [SolutionComponent] + public class InvalidateOnMaximumLinesChange + { + public InvalidateOnMaximumLinesChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + { + var maxLines = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.MethodTooLongMaximum); + settingsStore.AdviseChange(lifetime, maxLines, daemon.Invalidate); + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/HollowNames/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/HollowNames/MethodTooLongCheck.cs new file mode 100644 index 0000000..3af3c5f --- /dev/null +++ b/CleanCode/src/CleanCode/Features/HollowNames/MethodTooLongCheck.cs @@ -0,0 +1,49 @@ +namespace CleanCode.Features.HollowNames +{ + using System.Collections.Generic; + using System.Linq; + + using CleanCode.Resources; + using CleanCode.Settings; + using JetBrains.Application.Settings; + using JetBrains.ReSharper.Daemon.CSharp.Stages; + using JetBrains.ReSharper.Daemon.Stages; + using JetBrains.ReSharper.Psi.Tree; + + public class HollowNamesCheck : SimpleCheckBase + { + public HollowNamesCheck(IContextBoundSettingsStore settingsStore) + : base(settingsStore) + { + } + + protected override void ExecuteCore(ITypeDeclaration typeExpression, IHighlightingConsumer consumer) + { + + var suffixes = new[] { "Manager", "Controller", "Processor", "Helper", "Handler" }; + + var match = GetFirstMatchOrDefault(typeExpression.DeclaredName, suffixes); + + if (match != null) + { + AddHightlightning(match, consumer, typeExpression); + } + } + + private static string GetFirstMatchOrDefault(string declaredName, IEnumerable suffixes) + { + return suffixes.FirstOrDefault(declaredName.EndsWith); + } + + private void AddHightlightning(string bannedSuffix, IHighlightingConsumer consumer, ITypeDeclaration typeExpression) + { + var highlighting = new Highlighting(string.Format(Warnings.HollowTypeName, bannedSuffix)); + consumer.AddHighlighting(highlighting, typeExpression.GetDocumentRange()); + } + + protected override bool IsEnabled + { + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.HollowTypeNameEnabled); } + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs index 3023287..6bfff4d 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs @@ -15,21 +15,21 @@ public MethodNameNotMeaningfulCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) { var minimumMethodNameLenght = Threshold; - if (statement.NameIdentifier == null) + if (typeExpression.NameIdentifier == null) { return; } - var name = statement.NameIdentifier.GetText(); + var name = typeExpression.NameIdentifier.GetText(); var methodNameLenght = name.Length; if (methodNameLenght < minimumMethodNameLenght) { var highlighting = new Highlighting(Warnings.MethodNameNotMeaningful); - consumer.AddHighlighting(highlighting, statement.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs index dea32f6..1feb1b2 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs @@ -15,15 +15,15 @@ public MethodTooLongCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) { var maxLength = Threshold; - var statementCount = statement.CountChildren(); + var statementCount = typeExpression.CountChildren(); if (statementCount > maxLength) { var highlighting = new Highlighting(Warnings.Warning_MethodTooLong); - consumer.AddHighlighting(highlighting, statement.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/SimpleCheck.cs b/CleanCode/src/CleanCode/Features/SimpleCheck.cs index 80eb206..3035628 100644 --- a/CleanCode/src/CleanCode/Features/SimpleCheck.cs +++ b/CleanCode/src/CleanCode/Features/SimpleCheck.cs @@ -31,7 +31,7 @@ public void ExecuteIfEnabled(TElement methodDeclaration, IHighlightingConsumer c this.ExecuteCore(methodDeclaration, context); } - protected abstract void ExecuteCore(TElement statement, IHighlightingConsumer consumer); + protected abstract void ExecuteCore(TElement typeExpression, IHighlightingConsumer consumer); } public abstract class SimpleCheck : SimpleCheckBase diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs index 36fc6aa..6505691 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs @@ -17,11 +17,11 @@ public TooManyDependenciesCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IConstructorDeclaration statement, IHighlightingConsumer consumer) + protected override void ExecuteCore(IConstructorDeclaration typeExpression, IHighlightingConsumer consumer) { var maxDependencies = Threshold; - var depedencies = statement.ParameterDeclarations.Select( + var depedencies = typeExpression.ParameterDeclarations.Select( declaration => declaration.DeclaredElement != null && declaration.DeclaredElement.Type.IsInterfaceType()); @@ -30,7 +30,7 @@ protected override void ExecuteCore(IConstructorDeclaration statement, IHighligh if (dependenciesCount > maxDependencies) { var highlighting = new Highlighting(Warnings.TooManyDependencies); - consumer.AddHighlighting(highlighting, statement.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs index afe6f2e..c80ebbf 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs @@ -15,15 +15,15 @@ public TooManyMethodArgumentsCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration statement, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) { - var parameterDeclarations = statement.ParameterDeclarations; + var parameterDeclarations = typeExpression.ParameterDeclarations; var maxParameters = Threshold; if (parameterDeclarations.Count > maxParameters) { var highlighting = new Highlighting(Warnings.TooManyMethodArguments); - consumer.AddHighlighting(highlighting, statement.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs index 289dc02..2fa4694 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs @@ -105,6 +105,15 @@ public static string FlagArgument { } } + /// + /// Looks up a localized string similar to The usage of the suffix '{0}' is discouraged. It doesn't express the responsiblity of the type accurately. Chose a meaningful name.. + /// + public static string HollowTypeName { + get { + return ResourceManager.GetString("HollowTypeName", resourceCulture); + } + } + /// /// Looks up a localized string similar to The name of this method is too short to be meaningful.. /// diff --git a/CleanCode/src/CleanCode/Resources/Warnings.resx b/CleanCode/src/CleanCode/Resources/Warnings.resx index 6a14782..bbc6f21 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.resx +++ b/CleanCode/src/CleanCode/Resources/Warnings.resx @@ -144,4 +144,7 @@ This expression is too complex to be legible. Please, simplify it. + + The usage of the suffix '{0}' is discouraged. It doesn't express the responsiblity of the type accurately. Chose a meaningful name. + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs index f6b4cdc..361c6af 100644 --- a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs +++ b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs @@ -71,7 +71,10 @@ public class CleanCodeSettings public int MethodNameNotMeaningfulMinimum { get; set; } [SettingsEntry(true, "FlagArgumentsEnabled")] - public bool FlagArgumentsEnabled { get; set; } + public bool FlagArgumentsEnabled { get; set; } + + [SettingsEntry(true, "HollowTypeNameEnabled")] + public bool HollowTypeNameEnabled { get; set; } [SettingsEntry(true, "ComplexExpressionEnabled")] public bool ComplexExpressionEnabled { get; set; } diff --git a/CleanCode/src/NuGet.Packager/Package.nuspec b/CleanCode/src/NuGet.Packager/Package.nuspec index e5131de..8dcc68d 100644 --- a/CleanCode/src/NuGet.Packager/Package.nuspec +++ b/CleanCode/src/NuGet.Packager/Package.nuspec @@ -2,7 +2,7 @@ CleanCode - 4.0.0.3 + 4.0.0.6 CleanCode Hadi Hariri, Matt Ellis, SuperJMN Hadi Hariri, Matt Ellis From c5b49ef3827feab2eb21cbb47aa78bbc47c48916 Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Wed, 25 Jun 2014 00:03:06 +0200 Subject: [PATCH 15/50] Improved settings page Renamed bases for checks Introduced configurable work list for theHollow Type Names check --- CleanCode/src/CleanCode/CleanCode.8.2.csproj | 12 +- .../ChainedReferencesCheck.cs | 12 +- .../Features/{SimpleCheck.cs => Check.cs} | 17 +- .../Features/ClassTooBig/ClassTooBigCheck.cs | 12 +- ...plexCheck.cs => ComplexExpressionCheck.cs} | 12 +- .../ExcessiveIndentationCheck.cs | 12 +- .../FlagArguments/FlagArgumentsCheck.cs | 8 +- ...hodTooLongCheck.cs => HollowNamesCheck.cs} | 32 +++- ...InvalidateOnHollowTypeNameStringChange.cs} | 20 +-- .../MethodNameNotMeaningfulCheck.cs | 14 +- .../MethodTooLong/MethodTooLongCheck.cs | 12 +- .../src/CleanCode/Features/MonoValueCheck.cs | 16 ++ .../TooManyDependenciesCheck.cs | 12 +- .../TooManyMethodArgumentsCheck.cs | 12 +- .../CleanCode/Resources/Settings.Designer.cs | 18 ++ .../src/CleanCode/Resources/Settings.resx | 6 + .../CleanCode/Resources/Warnings.Designer.cs | 2 +- .../src/CleanCode/Resources/Warnings.resx | 2 +- .../Settings/CheckSettingViewModel.cs | 19 +- .../Settings/CheckTemplateSelector.cs | 25 ++- .../CleanCode/Settings/CleanCodeSettings.cs | 6 +- ...l.cs => MonoValueCheckSettingViewModel.cs} | 6 +- .../src/CleanCode/Settings/OptionsPage.xaml | 166 +++++++++++++----- .../CleanCode/Settings/OptionsViewModel.cs | 159 ++++++++--------- CleanCode/src/CleanCode/Settings/ViewModel.cs | 18 ++ CleanCode/src/NuGet.Packager/Package.nuspec | 2 +- 26 files changed, 408 insertions(+), 224 deletions(-) rename CleanCode/src/CleanCode/Features/{SimpleCheck.cs => Check.cs} (58%) rename CleanCode/src/CleanCode/Features/ComplexExpression/{ExpressionTooComplexCheck.cs => ComplexExpressionCheck.cs} (69%) rename CleanCode/src/CleanCode/Features/HollowNames/{MethodTooLongCheck.cs => HollowNamesCheck.cs} (50%) rename CleanCode/src/CleanCode/Features/HollowNames/{InvalidateOnMaximumLinesChange.cs => InvalidateOnHollowTypeNameStringChange.cs} (78%) create mode 100644 CleanCode/src/CleanCode/Features/MonoValueCheck.cs rename CleanCode/src/CleanCode/Settings/{ThresholdCheckSettingViewModel.cs => MonoValueCheckSettingViewModel.cs} (76%) create mode 100644 CleanCode/src/CleanCode/Settings/ViewModel.cs diff --git a/CleanCode/src/CleanCode/CleanCode.8.2.csproj b/CleanCode/src/CleanCode/CleanCode.8.2.csproj index ec294ad..b203bc7 100644 --- a/CleanCode/src/CleanCode/CleanCode.8.2.csproj +++ b/CleanCode/src/CleanCode/CleanCode.8.2.csproj @@ -54,12 +54,13 @@ + - + @@ -72,8 +73,8 @@ - - + + @@ -84,7 +85,7 @@ Code - + Code @@ -121,7 +122,8 @@ - + + diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs index a6d8c61..aa7b982 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs @@ -13,18 +13,18 @@ namespace CleanCode.Features.ChainedReferences { - public class ChainedReferencesCheck : SimpleCheck + public class ChainedReferencesCheck : MonoValueCheck { public ChainedReferencesCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(ICSharpStatement typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(ICSharpStatement classDeclaration, IHighlightingConsumer consumer) { - if (typeExpression != null && !typeExpression.IsEmbeddedStatement) + if (classDeclaration != null && !classDeclaration.IsEmbeddedStatement) { - this.HighlightMethodChainsThatAreTooLong(typeExpression, consumer); + this.HighlightMethodChainsThatAreTooLong(classDeclaration, consumer); } } @@ -70,14 +70,14 @@ private void HightlightReferenceExpressionIfNeeded(IReferenceExpression referenc if (!isFluentChain) { - if (chainLength > Threshold) + if (chainLength > Value) { AddHighlightning(referenceExpression, consumer); } } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); } } diff --git a/CleanCode/src/CleanCode/Features/SimpleCheck.cs b/CleanCode/src/CleanCode/Features/Check.cs similarity index 58% rename from CleanCode/src/CleanCode/Features/SimpleCheck.cs rename to CleanCode/src/CleanCode/Features/Check.cs index 3035628..404aaf2 100644 --- a/CleanCode/src/CleanCode/Features/SimpleCheck.cs +++ b/CleanCode/src/CleanCode/Features/Check.cs @@ -4,12 +4,12 @@ namespace CleanCode.Features { - public abstract class SimpleCheckBase + public abstract class Check where TElement : ITreeNode { private readonly IContextBoundSettingsStore settingsStore; - protected SimpleCheckBase(IContextBoundSettingsStore settingsStore) + protected Check(IContextBoundSettingsStore settingsStore) { this.settingsStore = settingsStore; } @@ -31,17 +31,6 @@ public void ExecuteIfEnabled(TElement methodDeclaration, IHighlightingConsumer c this.ExecuteCore(methodDeclaration, context); } - protected abstract void ExecuteCore(TElement typeExpression, IHighlightingConsumer consumer); - } - - public abstract class SimpleCheck : SimpleCheckBase - where TElement : ITreeNode - { - protected SimpleCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected abstract TThreshold Threshold { get; } + protected abstract void ExecuteCore(TElement classDeclaration, IHighlightingConsumer consumer); } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs index eaf251a..dd308f1 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs @@ -8,28 +8,28 @@ namespace CleanCode.Features.ClassTooBig { - public class ClassTooBigCheck : SimpleCheck + public class ClassTooBigCheck : MonoValueCheck { public ClassTooBigCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IClassDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IClassDeclaration classDeclaration, IHighlightingConsumer consumer) { - var maxLength = Threshold; + var maxLength = Value; - var statementCount = typeExpression.CountChildren(); + var statementCount = classDeclaration.CountChildren(); if (statementCount > maxLength) { - var declarationIdentifier = typeExpression.NameIdentifier; + var declarationIdentifier = classDeclaration.NameIdentifier; var documentRange = declarationIdentifier.GetDocumentRange(); var highlighting = new Highlighting(Warnings.ClassTooBig); consumer.AddHighlighting(highlighting, documentRange); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigMaximum); } } diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs similarity index 69% rename from CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs rename to CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs index d17ef78..dfb8d10 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs @@ -11,26 +11,26 @@ namespace CleanCode.Features.ComplexExpression using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; - public class ComplexExpressionCheck : SimpleCheck + public class ComplexExpressionCheck : MonoValueCheck { public ComplexExpressionCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IExpression typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IExpression classDeclaration, IHighlightingConsumer consumer) { - var maxExpressions = this.Threshold; - var depth = typeExpression.GetChildrenRecursive().Count(); + var maxExpressions = this.Value; + var depth = classDeclaration.GetChildrenRecursive().Count(); if (depth > maxExpressions) { var highlighting = new ExcessiveIndentation.Highlighting(Warnings.ExpressionTooComplex); - consumer.AddHighlighting(highlighting, typeExpression.GetDocumentRange()); + consumer.AddHighlighting(highlighting, classDeclaration.GetDocumentRange()); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ComplexExpressionMaximum); } } diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs index 6693d66..59c4bbf 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs @@ -8,26 +8,26 @@ namespace CleanCode.Features.ExcessiveIndentation { - public class ExcessiveIndentationCheck : SimpleCheck + public class ExcessiveIndentationCheck : MonoValueCheck { public ExcessiveIndentationCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) { - var maxIndentation = Threshold; - var depth = typeExpression.GetChildrenDepth(); + var maxIndentation = Value; + var depth = classDeclaration.GetChildrenDepth(); if (depth > maxIndentation) { var highlighting = new Highlighting(Warnings.ExcessiveDepth); - consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationMaximum); } } diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs index 50b1241..9030380 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs @@ -13,20 +13,20 @@ namespace CleanCode.Features.FlagArguments { - public class FlagArgumentsCheck : SimpleCheckBase + public class FlagArgumentsCheck : Check { public FlagArgumentsCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) { - var parameterDeclarations = typeExpression.ParameterDeclarations; + var parameterDeclarations = classDeclaration.ParameterDeclarations; foreach (var parameterDeclaration in parameterDeclarations) { - if (IsFlagArgument(parameterDeclaration, typeExpression.Body)) + if (IsFlagArgument(parameterDeclaration, classDeclaration.Body)) { AddHighlighting(consumer, parameterDeclaration); } diff --git a/CleanCode/src/CleanCode/Features/HollowNames/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs similarity index 50% rename from CleanCode/src/CleanCode/Features/HollowNames/MethodTooLongCheck.cs rename to CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs index 3af3c5f..415ecbb 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs @@ -1,3 +1,7 @@ +using System; +using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.Xaml.Tree.MarkupExtensions; + namespace CleanCode.Features.HollowNames { using System.Collections.Generic; @@ -10,40 +14,52 @@ namespace CleanCode.Features.HollowNames using JetBrains.ReSharper.Daemon.Stages; using JetBrains.ReSharper.Psi.Tree; - public class HollowNamesCheck : SimpleCheckBase + public class HollowNamesCheck : MonoValueCheck { + private const string Separator = ","; + public HollowNamesCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(ITypeDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IClassDeclaration classDeclaration, IHighlightingConsumer consumer) { + var suffixes = GetSuffixes(); - var suffixes = new[] { "Manager", "Controller", "Processor", "Helper", "Handler" }; - - var match = GetFirstMatchOrDefault(typeExpression.DeclaredName, suffixes); + var match = GetFirstMatchOrDefault(classDeclaration.DeclaredName, suffixes); if (match != null) { - AddHightlightning(match, consumer, typeExpression); + AddHightlightning(match, consumer, classDeclaration); } } + private IEnumerable GetSuffixes() + { + return Value.Split(new[] { Separator }, StringSplitOptions.RemoveEmptyEntries); + } + private static string GetFirstMatchOrDefault(string declaredName, IEnumerable suffixes) { return suffixes.FirstOrDefault(declaredName.EndsWith); } - private void AddHightlightning(string bannedSuffix, IHighlightingConsumer consumer, ITypeDeclaration typeExpression) + private void AddHightlightning(string bannedSuffix, IHighlightingConsumer consumer, IClassDeclaration typeExpression) { var highlighting = new Highlighting(string.Format(Warnings.HollowTypeName, bannedSuffix)); - consumer.AddHighlighting(highlighting, typeExpression.GetDocumentRange()); + var identifier = typeExpression.NameIdentifier; + consumer.AddHighlighting(highlighting, identifier.GetDocumentRange()); } protected override bool IsEnabled { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.HollowTypeNameEnabled); } } + + protected override string Value + { + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.HollowTypeNameString); } + } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnMaximumLinesChange.cs b/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs similarity index 78% rename from CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnMaximumLinesChange.cs rename to CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs index ec3bef9..f9795af 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnMaximumLinesChange.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs @@ -25,21 +25,21 @@ // OR OTHER DEALINGS IN THE SOFTWARE. #endregion -namespace CleanCode.Features.HollowNames -{ - using CleanCode.Settings; +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.DataFlow; +using JetBrains.ProjectModel; +using JetBrains.ReSharper.Daemon; - using JetBrains.Application.Settings; - using JetBrains.DataFlow; - using JetBrains.ProjectModel; - using JetBrains.ReSharper.Daemon; +namespace CleanCode.Features.HollowNames +{ [SolutionComponent] - public class InvalidateOnMaximumLinesChange + public class InvalidateOnHollowTypeNameStringChange { - public InvalidateOnMaximumLinesChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + public InvalidateOnHollowTypeNameStringChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) { - var maxLines = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.MethodTooLongMaximum); + var maxLines = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.HollowTypeNameString); settingsStore.AdviseChange(lifetime, maxLines, daemon.Invalidate); } } diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs index 6bfff4d..33d7bd0 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs @@ -8,32 +8,32 @@ namespace CleanCode.Features.MethodNameNotMeaningful { - public class MethodNameNotMeaningfulCheck : SimpleCheck + public class MethodNameNotMeaningfulCheck : MonoValueCheck { public MethodNameNotMeaningfulCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) { - var minimumMethodNameLenght = Threshold; + var minimumMethodNameLenght = Value; - if (typeExpression.NameIdentifier == null) + if (classDeclaration.NameIdentifier == null) { return; } - var name = typeExpression.NameIdentifier.GetText(); + var name = classDeclaration.NameIdentifier.GetText(); var methodNameLenght = name.Length; if (methodNameLenght < minimumMethodNameLenght) { var highlighting = new Highlighting(Warnings.MethodNameNotMeaningful); - consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimum); } } diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs index 1feb1b2..0a8384e 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs @@ -8,26 +8,26 @@ namespace CleanCode.Features.MethodTooLong { - public class MethodTooLongCheck : SimpleCheck + public class MethodTooLongCheck : MonoValueCheck { public MethodTooLongCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) { - var maxLength = Threshold; + var maxLength = Value; - var statementCount = typeExpression.CountChildren(); + var statementCount = classDeclaration.CountChildren(); if (statementCount > maxLength) { var highlighting = new Highlighting(Warnings.Warning_MethodTooLong); - consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongMaximum); } } diff --git a/CleanCode/src/CleanCode/Features/MonoValueCheck.cs b/CleanCode/src/CleanCode/Features/MonoValueCheck.cs new file mode 100644 index 0000000..0c87c88 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/MonoValueCheck.cs @@ -0,0 +1,16 @@ +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Psi.Tree; + +namespace CleanCode.Features +{ + public abstract class MonoValueCheck : Check + where TElement : ITreeNode + { + protected MonoValueCheck(IContextBoundSettingsStore settingsStore) + : base(settingsStore) + { + } + + protected abstract TValue Value { get; } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs index 6505691..7c8f0d4 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs @@ -10,18 +10,18 @@ namespace CleanCode.Features.TooManyDependencies { - public class TooManyDependenciesCheck : SimpleCheck + public class TooManyDependenciesCheck : MonoValueCheck { public TooManyDependenciesCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IConstructorDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IConstructorDeclaration classDeclaration, IHighlightingConsumer consumer) { - var maxDependencies = Threshold; + var maxDependencies = Value; - var depedencies = typeExpression.ParameterDeclarations.Select( + var depedencies = classDeclaration.ParameterDeclarations.Select( declaration => declaration.DeclaredElement != null && declaration.DeclaredElement.Type.IsInterfaceType()); @@ -30,11 +30,11 @@ protected override void ExecuteCore(IConstructorDeclaration typeExpression, IHig if (dependenciesCount > maxDependencies) { var highlighting = new Highlighting(Warnings.TooManyDependencies); - consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximum); } } diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs index c80ebbf..eecadb2 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs @@ -8,26 +8,26 @@ namespace CleanCode.Features.TooManyMethodArguments { - public class TooManyMethodArgumentsCheck : SimpleCheck + public class TooManyMethodArgumentsCheck : MonoValueCheck { public TooManyMethodArgumentsCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) { - var parameterDeclarations = typeExpression.ParameterDeclarations; - var maxParameters = Threshold; + var parameterDeclarations = classDeclaration.ParameterDeclarations; + var maxParameters = Value; if (parameterDeclarations.Count > maxParameters) { var highlighting = new Highlighting(Warnings.TooManyMethodArguments); - consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); } } diff --git a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs index 94ae2e1..22aab15 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs @@ -123,6 +123,24 @@ public static string FlagArgumentsCheck { } } + /// + /// Looks up a localized string similar to Hollow Type Name Check. + /// + public static string HollowTypeNameCheck { + get { + return ResourceManager.GetString("HollowTypeNameCheck", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to List of meaningless suffixes. + /// + public static string HollowTypeNameWords { + get { + return ResourceManager.GetString("HollowTypeNameWords", resourceCulture); + } + } + /// /// Looks up a localized string similar to Maximum Chained References. /// diff --git a/CleanCode/src/CleanCode/Resources/Settings.resx b/CleanCode/src/CleanCode/Resources/Settings.resx index b5b06df..f9ad440 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.resx +++ b/CleanCode/src/CleanCode/Resources/Settings.resx @@ -174,4 +174,10 @@ Flag Arguments Check + + Hollow Type Name Check + + + List of meaningless suffixes + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs index 2fa4694..71ec71c 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs @@ -106,7 +106,7 @@ public static string FlagArgument { } /// - /// Looks up a localized string similar to The usage of the suffix '{0}' is discouraged. It doesn't express the responsiblity of the type accurately. Chose a meaningful name.. + /// Looks up a localized string similar to The usage of the suffix '{0}' is discouraged because it's too generic. Please, choose a meaningful name instead to clarify its intent and responsibilities.. /// public static string HollowTypeName { get { diff --git a/CleanCode/src/CleanCode/Resources/Warnings.resx b/CleanCode/src/CleanCode/Resources/Warnings.resx index bbc6f21..28095cc 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.resx +++ b/CleanCode/src/CleanCode/Resources/Warnings.resx @@ -145,6 +145,6 @@ This expression is too complex to be legible. Please, simplify it. - The usage of the suffix '{0}' is discouraged. It doesn't express the responsiblity of the type accurately. Chose a meaningful name. + The usage of the suffix '{0}' is discouraged because it's too generic. Please, choose a meaningful name instead to clarify its intent and responsibilities. \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs b/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs index 8012bef..f2a1c1c 100644 --- a/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs +++ b/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using JetBrains.Application.Settings; namespace CleanCode.Settings @@ -10,13 +11,25 @@ public class CheckSettingViewModel : ViewModel protected readonly IContextBoundSettingsStore Settings; - public CheckSettingViewModel(IContextBoundSettingsStore settings, Expression> isEnabledSelector) + public CheckSettingViewModel([NotNull] IContextBoundSettingsStore settings, + [NotNull] Expression> isEnabledSelector) { + if (settings == null) + { + throw new ArgumentNullException("settings"); + } + + if (isEnabledSelector == null) + { + throw new ArgumentNullException("isEnabledSelector"); + } + this.Settings = settings; - this.isEnabledSelector = isEnabledSelector; - + this.isEnabledSelector = isEnabledSelector; } + public string Category { get; set; } + public bool IsEnabled { get { return Settings.GetValue(isEnabledSelector); } diff --git a/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs b/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs index 53e83a1..02da0c9 100644 --- a/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs +++ b/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs @@ -1,4 +1,6 @@ -using System.Windows; +using System; +using System.Linq; +using System.Windows; using System.Windows.Controls; namespace CleanCode.Settings @@ -7,14 +9,20 @@ public class CheckTemplateSelector : DataTemplateSelector { public DataTemplate ThresholdCheckTemplate { get; set; } public DataTemplate BasicCheckTemplate { get; set; } + public DataTemplate StringCheckTemplate { get; set; } public override DataTemplate SelectTemplate(object item, DependencyObject container) { + if (item == null) + { + return base.SelectTemplate(item, container); + } + var type = item.GetType(); - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ThresholdCheckSettingViewModel<>)) + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(MonoValueCheckSettingViewModel<>)) { - return ThresholdCheckTemplate; + return GetTemplateFromGenericType(type); } if (item is CheckSettingViewModel) { @@ -23,6 +31,17 @@ public override DataTemplate SelectTemplate(object item, DependencyObject contai return base.SelectTemplate(item, container); } + private DataTemplate GetTemplateFromGenericType(Type type) + { + var firstType = type.GetGenericArguments().First(); + if (firstType == typeof (string)) + { + return StringCheckTemplate; + } + return ThresholdCheckTemplate; + } + + bool IsTypeof(object t) { return (t is T); diff --git a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs index 361c6af..6a7d78c 100644 --- a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs +++ b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs @@ -74,9 +74,13 @@ public class CleanCodeSettings public bool FlagArgumentsEnabled { get; set; } [SettingsEntry(true, "HollowTypeNameEnabled")] - public bool HollowTypeNameEnabled { get; set; } + public bool HollowTypeNameEnabled { get; set; } + + [SettingsEntry("Handler,Manager,Processor,Controller,Helper", "HollowTypeNameString")] + public string HollowTypeNameString { get; set; } [SettingsEntry(true, "ComplexExpressionEnabled")] + public bool ComplexExpressionEnabled { get; set; } [SettingsEntry(1, "ComplexExpressionMaximum")] public int ComplexExpressionMaximum { get; set; } diff --git a/CleanCode/src/CleanCode/Settings/ThresholdCheckSettingViewModel.cs b/CleanCode/src/CleanCode/Settings/MonoValueCheckSettingViewModel.cs similarity index 76% rename from CleanCode/src/CleanCode/Settings/ThresholdCheckSettingViewModel.cs rename to CleanCode/src/CleanCode/Settings/MonoValueCheckSettingViewModel.cs index 6fc9d80..ab0767d 100644 --- a/CleanCode/src/CleanCode/Settings/ThresholdCheckSettingViewModel.cs +++ b/CleanCode/src/CleanCode/Settings/MonoValueCheckSettingViewModel.cs @@ -4,11 +4,11 @@ namespace CleanCode.Settings { - public class ThresholdCheckSettingViewModel : CheckSettingViewModel + public class MonoValueCheckSettingViewModel : CheckSettingViewModel { - protected Expression> valueSelector; + private readonly Expression> valueSelector; - public ThresholdCheckSettingViewModel(IContextBoundSettingsStore settings, Expression> isEnabledSelector, Expression> valueSelector) : base(settings, isEnabledSelector) + public MonoValueCheckSettingViewModel(IContextBoundSettingsStore settings, Expression> isEnabledSelector, Expression> valueSelector) : base(settings, isEnabledSelector) { this.valueSelector = valueSelector; } diff --git a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml index 9b79b7e..3b5f561 100644 --- a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml +++ b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml @@ -5,68 +5,154 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:settings="clr-namespace:CleanCode.Settings" mc:Ignorable="d" - d:DataContext="{d:DesignInstance settings:OptionsViewModel}" d:DesignWidth="529" d:DesignHeight="126"> + d:DataContext="{d:DesignInstance settings:OptionsViewModel}" d:DesignWidth="842" d:DesignHeight="414"> + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + - - + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + - - - diff --git a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs index b92e930..e6e0169 100644 --- a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs +++ b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs @@ -1,23 +1,8 @@ using System.Collections; -using System.ComponentModel; -using System.Runtime.CompilerServices; -using JetBrains.Annotations; using JetBrains.Application.Settings; namespace CleanCode.Settings { - public abstract class ViewModel : INotifyPropertyChanged - { - public virtual event PropertyChangedEventHandler PropertyChanged; - - [NotifyPropertyChangedInvocator] - protected void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - var handler = PropertyChanged; - if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); - } - } - public sealed class OptionsViewModel : ViewModel { public OptionsViewModel(IContextBoundSettingsStore settings) @@ -33,102 +18,114 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) { var viewModels = new ArrayList(); - var methodTooLong = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, codeSettings => codeSettings.MethodTooLongEnabled, codeSettings => codeSettings.MethodTooLongMaximum) - { - IsEnabledDescription = Resources.Settings.MethodTooLongCheck, - ValueDescription = Resources.Settings.TooLongLinesPerMethod, - }; - viewModels.Add(methodTooLong); + { + IsEnabledDescription = Resources.Settings.MethodTooLongCheck, + ValueDescription = Resources.Settings.TooLongLinesPerMethod, + Category = Categories.Size, + }); - var tooManyDependencies = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, e => e.TooManyDependenciesMaximumEnabled, e => e.TooManyDependenciesMaximum) - { - IsEnabledDescription = Resources.Settings.MaximumDependenciesCheck, - ValueDescription = Resources.Settings.TooManyDependencies, - }; - viewModels.Add(tooManyDependencies); + { + IsEnabledDescription = Resources.Settings.MaximumDependenciesCheck, + ValueDescription = Resources.Settings.TooManyDependencies, + Category = Categories.Coupling, + }); - var tooManyMethodArguments = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, e => e.TooManyMethodArgumentsEnabled, e => e.TooManyMethodArgumentsMaximum) - { - IsEnabledDescription = Resources.Settings.MaximumMethodArgumentsCheck, - ValueDescription = Resources.Settings.TooManyMethodArguments, - }; - - viewModels.Add(tooManyMethodArguments); + { + IsEnabledDescription = Resources.Settings.MaximumMethodArgumentsCheck, + ValueDescription = Resources.Settings.TooManyMethodArguments, + Category = Categories.Responsibility, + }); - var excessiveDepth = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, - e => e.TooManyDependenciesMaximumEnabled, + e => e.ExcessiveIndentationEnabled, e => e.ExcessiveIndentationMaximum) - { - IsEnabledDescription = Resources.Settings.ExcessiveDepthCheck, - ValueDescription = Resources.Settings.ExcessiveDepth, - }; + { + IsEnabledDescription = Resources.Settings.ExcessiveDepthCheck, + ValueDescription = Resources.Settings.ExcessiveDepth, + Category = Categories.Coupling, + }); - viewModels.Add(excessiveDepth); - - var classTooBig = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, e => e.ClassTooBigEnabled, e => e.ClassTooBigMaximum) - { - IsEnabledDescription = Resources.Settings.ClassTooBigCheck, - ValueDescription = Resources.Settings.ClassTooBig, - }; - - viewModels.Add(classTooBig); + { + IsEnabledDescription = Resources.Settings.ClassTooBigCheck, + ValueDescription = Resources.Settings.ClassTooBig, + Category = Categories.Size, + }); - var chainedReferences = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, e => e.TooManyChainedReferencesEnabled, e => e.TooManyChainedReferencesMaximum) - { - IsEnabledDescription = Resources.Settings.MaxChainedReferencesCheck, - ValueDescription = Resources.Settings.MaxChainedReferences, - }; + { + IsEnabledDescription = Resources.Settings.MaxChainedReferencesCheck, + ValueDescription = Resources.Settings.MaxChainedReferences, + Category = Categories.Responsibility, + }); - viewModels.Add(chainedReferences); - - var methodNameLength = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, e => e.MethodNameNotMeaningfulMinimumEnabled, e => e.MethodNameNotMeaningfulMinimum) - { - IsEnabledDescription = Resources.Settings.MinimumMethodNameLengthCheck, - ValueDescription = Resources.Settings.MinimumMethodNameLength, - }; - - viewModels.Add(methodNameLength); - - var complexCondition = new ThresholdCheckSettingViewModel( - settings, - e => e.ComplexExpressionEnabled, - e => e.ComplexExpressionMaximum) - { - IsEnabledDescription = Resources.Settings.ComplexExpressionCheck, - ValueDescription = Resources.Settings.ComplexExpressionMaximum, - }; + { + IsEnabledDescription = Resources.Settings.MinimumMethodNameLengthCheck, + ValueDescription = Resources.Settings.MinimumMethodNameLength, + Category = Categories.Legibility, + }); - viewModels.Add(complexCondition); - - var flagArguments = new CheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, - e => e.FlagArgumentsEnabled) - { - IsEnabledDescription = Resources.Settings.FlagArgumentsCheck, - }; - - viewModels.Add(flagArguments); + e => e.ComplexExpressionEnabled, + e => e.ComplexExpressionMaximum) + { + IsEnabledDescription = Resources.Settings.ComplexExpressionCheck, + ValueDescription = Resources.Settings.ComplexExpressionMaximum, + Category = Categories.Complexity, + }); + + viewModels.Add(new CheckSettingViewModel( + settings, + e => e.FlagArgumentsEnabled) + { + IsEnabledDescription = Resources.Settings.FlagArgumentsCheck, + Category = Categories.Responsibility, + }); + + viewModels.Add(new MonoValueCheckSettingViewModel( + settings, + codeSettings => codeSettings.HollowTypeNameEnabled, + codeSettings => codeSettings.HollowTypeNameString) + { + IsEnabledDescription = Resources.Settings.HollowTypeNameCheck, + ValueDescription = Resources.Settings.HollowTypeNameWords, + Category = Categories.Legibility, + }); return viewModels; } } + + public class Categories + { + public const string Size = "Size"; + public const string Complexity = "Complexity"; + public const string Coupling = "Coupling"; + public const string Responsibility = "Responsibility"; + public const string Legibility = "Legibility"; + } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/ViewModel.cs b/CleanCode/src/CleanCode/Settings/ViewModel.cs new file mode 100644 index 0000000..2513048 --- /dev/null +++ b/CleanCode/src/CleanCode/Settings/ViewModel.cs @@ -0,0 +1,18 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; + +namespace CleanCode.Settings +{ + public abstract class ViewModel : INotifyPropertyChanged + { + public virtual event PropertyChangedEventHandler PropertyChanged; + + [NotifyPropertyChangedInvocator] + protected void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); + } + } +} \ No newline at end of file diff --git a/CleanCode/src/NuGet.Packager/Package.nuspec b/CleanCode/src/NuGet.Packager/Package.nuspec index 8dcc68d..a930265 100644 --- a/CleanCode/src/NuGet.Packager/Package.nuspec +++ b/CleanCode/src/NuGet.Packager/Package.nuspec @@ -2,7 +2,7 @@ CleanCode - 4.0.0.6 + 4.0.0.7 CleanCode Hadi Hariri, Matt Ellis, SuperJMN Hadi Hariri, Matt Ellis From 0c18c60a0418b40d81a87788e03d93033ae2d82b Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Wed, 25 Jun 2014 00:17:44 +0200 Subject: [PATCH 16/50] Improved settings page Renamed bases for checks Introduced configurable word list for the Hollow Type Names check --- CleanCode/src/CleanCode/CleanCode.8.2.csproj | 12 +- .../ChainedReferencesCheck.cs | 12 +- .../Features/{SimpleCheck.cs => Check.cs} | 17 +- .../Features/ClassTooBig/ClassTooBigCheck.cs | 12 +- ...plexCheck.cs => ComplexExpressionCheck.cs} | 12 +- .../ExcessiveIndentationCheck.cs | 12 +- .../FlagArguments/FlagArgumentsCheck.cs | 8 +- ...hodTooLongCheck.cs => HollowNamesCheck.cs} | 32 +++- ...InvalidateOnHollowTypeNameStringChange.cs} | 20 +-- .../MethodNameNotMeaningfulCheck.cs | 14 +- .../MethodTooLong/MethodTooLongCheck.cs | 12 +- .../src/CleanCode/Features/MonoValueCheck.cs | 16 ++ .../TooManyDependenciesCheck.cs | 12 +- .../TooManyMethodArgumentsCheck.cs | 12 +- .../CleanCode/Resources/Settings.Designer.cs | 18 ++ .../src/CleanCode/Resources/Settings.resx | 6 + .../CleanCode/Resources/Warnings.Designer.cs | 2 +- .../src/CleanCode/Resources/Warnings.resx | 2 +- .../Settings/CheckSettingViewModel.cs | 19 +- .../Settings/CheckTemplateSelector.cs | 25 ++- .../CleanCode/Settings/CleanCodeSettings.cs | 6 +- ...l.cs => MonoValueCheckSettingViewModel.cs} | 6 +- .../src/CleanCode/Settings/OptionsPage.xaml | 166 +++++++++++++----- .../CleanCode/Settings/OptionsViewModel.cs | 159 ++++++++--------- CleanCode/src/CleanCode/Settings/ViewModel.cs | 18 ++ CleanCode/src/NuGet.Packager/Package.nuspec | 2 +- 26 files changed, 408 insertions(+), 224 deletions(-) rename CleanCode/src/CleanCode/Features/{SimpleCheck.cs => Check.cs} (58%) rename CleanCode/src/CleanCode/Features/ComplexExpression/{ExpressionTooComplexCheck.cs => ComplexExpressionCheck.cs} (69%) rename CleanCode/src/CleanCode/Features/HollowNames/{MethodTooLongCheck.cs => HollowNamesCheck.cs} (50%) rename CleanCode/src/CleanCode/Features/HollowNames/{InvalidateOnMaximumLinesChange.cs => InvalidateOnHollowTypeNameStringChange.cs} (78%) create mode 100644 CleanCode/src/CleanCode/Features/MonoValueCheck.cs rename CleanCode/src/CleanCode/Settings/{ThresholdCheckSettingViewModel.cs => MonoValueCheckSettingViewModel.cs} (76%) create mode 100644 CleanCode/src/CleanCode/Settings/ViewModel.cs diff --git a/CleanCode/src/CleanCode/CleanCode.8.2.csproj b/CleanCode/src/CleanCode/CleanCode.8.2.csproj index ec294ad..b203bc7 100644 --- a/CleanCode/src/CleanCode/CleanCode.8.2.csproj +++ b/CleanCode/src/CleanCode/CleanCode.8.2.csproj @@ -54,12 +54,13 @@ + - + @@ -72,8 +73,8 @@ - - + + @@ -84,7 +85,7 @@ Code - + Code @@ -121,7 +122,8 @@ - + + diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs index a6d8c61..aa7b982 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs @@ -13,18 +13,18 @@ namespace CleanCode.Features.ChainedReferences { - public class ChainedReferencesCheck : SimpleCheck + public class ChainedReferencesCheck : MonoValueCheck { public ChainedReferencesCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(ICSharpStatement typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(ICSharpStatement classDeclaration, IHighlightingConsumer consumer) { - if (typeExpression != null && !typeExpression.IsEmbeddedStatement) + if (classDeclaration != null && !classDeclaration.IsEmbeddedStatement) { - this.HighlightMethodChainsThatAreTooLong(typeExpression, consumer); + this.HighlightMethodChainsThatAreTooLong(classDeclaration, consumer); } } @@ -70,14 +70,14 @@ private void HightlightReferenceExpressionIfNeeded(IReferenceExpression referenc if (!isFluentChain) { - if (chainLength > Threshold) + if (chainLength > Value) { AddHighlightning(referenceExpression, consumer); } } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); } } diff --git a/CleanCode/src/CleanCode/Features/SimpleCheck.cs b/CleanCode/src/CleanCode/Features/Check.cs similarity index 58% rename from CleanCode/src/CleanCode/Features/SimpleCheck.cs rename to CleanCode/src/CleanCode/Features/Check.cs index 3035628..404aaf2 100644 --- a/CleanCode/src/CleanCode/Features/SimpleCheck.cs +++ b/CleanCode/src/CleanCode/Features/Check.cs @@ -4,12 +4,12 @@ namespace CleanCode.Features { - public abstract class SimpleCheckBase + public abstract class Check where TElement : ITreeNode { private readonly IContextBoundSettingsStore settingsStore; - protected SimpleCheckBase(IContextBoundSettingsStore settingsStore) + protected Check(IContextBoundSettingsStore settingsStore) { this.settingsStore = settingsStore; } @@ -31,17 +31,6 @@ public void ExecuteIfEnabled(TElement methodDeclaration, IHighlightingConsumer c this.ExecuteCore(methodDeclaration, context); } - protected abstract void ExecuteCore(TElement typeExpression, IHighlightingConsumer consumer); - } - - public abstract class SimpleCheck : SimpleCheckBase - where TElement : ITreeNode - { - protected SimpleCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected abstract TThreshold Threshold { get; } + protected abstract void ExecuteCore(TElement classDeclaration, IHighlightingConsumer consumer); } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs index eaf251a..dd308f1 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs @@ -8,28 +8,28 @@ namespace CleanCode.Features.ClassTooBig { - public class ClassTooBigCheck : SimpleCheck + public class ClassTooBigCheck : MonoValueCheck { public ClassTooBigCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IClassDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IClassDeclaration classDeclaration, IHighlightingConsumer consumer) { - var maxLength = Threshold; + var maxLength = Value; - var statementCount = typeExpression.CountChildren(); + var statementCount = classDeclaration.CountChildren(); if (statementCount > maxLength) { - var declarationIdentifier = typeExpression.NameIdentifier; + var declarationIdentifier = classDeclaration.NameIdentifier; var documentRange = declarationIdentifier.GetDocumentRange(); var highlighting = new Highlighting(Warnings.ClassTooBig); consumer.AddHighlighting(highlighting, documentRange); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigMaximum); } } diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs similarity index 69% rename from CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs rename to CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs index d17ef78..dfb8d10 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/ExpressionTooComplexCheck.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs @@ -11,26 +11,26 @@ namespace CleanCode.Features.ComplexExpression using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; - public class ComplexExpressionCheck : SimpleCheck + public class ComplexExpressionCheck : MonoValueCheck { public ComplexExpressionCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IExpression typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IExpression classDeclaration, IHighlightingConsumer consumer) { - var maxExpressions = this.Threshold; - var depth = typeExpression.GetChildrenRecursive().Count(); + var maxExpressions = this.Value; + var depth = classDeclaration.GetChildrenRecursive().Count(); if (depth > maxExpressions) { var highlighting = new ExcessiveIndentation.Highlighting(Warnings.ExpressionTooComplex); - consumer.AddHighlighting(highlighting, typeExpression.GetDocumentRange()); + consumer.AddHighlighting(highlighting, classDeclaration.GetDocumentRange()); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ComplexExpressionMaximum); } } diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs index 6693d66..59c4bbf 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs @@ -8,26 +8,26 @@ namespace CleanCode.Features.ExcessiveIndentation { - public class ExcessiveIndentationCheck : SimpleCheck + public class ExcessiveIndentationCheck : MonoValueCheck { public ExcessiveIndentationCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) { - var maxIndentation = Threshold; - var depth = typeExpression.GetChildrenDepth(); + var maxIndentation = Value; + var depth = classDeclaration.GetChildrenDepth(); if (depth > maxIndentation) { var highlighting = new Highlighting(Warnings.ExcessiveDepth); - consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationMaximum); } } diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs index 50b1241..9030380 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs @@ -13,20 +13,20 @@ namespace CleanCode.Features.FlagArguments { - public class FlagArgumentsCheck : SimpleCheckBase + public class FlagArgumentsCheck : Check { public FlagArgumentsCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) { - var parameterDeclarations = typeExpression.ParameterDeclarations; + var parameterDeclarations = classDeclaration.ParameterDeclarations; foreach (var parameterDeclaration in parameterDeclarations) { - if (IsFlagArgument(parameterDeclaration, typeExpression.Body)) + if (IsFlagArgument(parameterDeclaration, classDeclaration.Body)) { AddHighlighting(consumer, parameterDeclaration); } diff --git a/CleanCode/src/CleanCode/Features/HollowNames/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs similarity index 50% rename from CleanCode/src/CleanCode/Features/HollowNames/MethodTooLongCheck.cs rename to CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs index 3af3c5f..415ecbb 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs @@ -1,3 +1,7 @@ +using System; +using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.Xaml.Tree.MarkupExtensions; + namespace CleanCode.Features.HollowNames { using System.Collections.Generic; @@ -10,40 +14,52 @@ namespace CleanCode.Features.HollowNames using JetBrains.ReSharper.Daemon.Stages; using JetBrains.ReSharper.Psi.Tree; - public class HollowNamesCheck : SimpleCheckBase + public class HollowNamesCheck : MonoValueCheck { + private const string Separator = ","; + public HollowNamesCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(ITypeDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IClassDeclaration classDeclaration, IHighlightingConsumer consumer) { + var suffixes = GetSuffixes(); - var suffixes = new[] { "Manager", "Controller", "Processor", "Helper", "Handler" }; - - var match = GetFirstMatchOrDefault(typeExpression.DeclaredName, suffixes); + var match = GetFirstMatchOrDefault(classDeclaration.DeclaredName, suffixes); if (match != null) { - AddHightlightning(match, consumer, typeExpression); + AddHightlightning(match, consumer, classDeclaration); } } + private IEnumerable GetSuffixes() + { + return Value.Split(new[] { Separator }, StringSplitOptions.RemoveEmptyEntries); + } + private static string GetFirstMatchOrDefault(string declaredName, IEnumerable suffixes) { return suffixes.FirstOrDefault(declaredName.EndsWith); } - private void AddHightlightning(string bannedSuffix, IHighlightingConsumer consumer, ITypeDeclaration typeExpression) + private void AddHightlightning(string bannedSuffix, IHighlightingConsumer consumer, IClassDeclaration typeExpression) { var highlighting = new Highlighting(string.Format(Warnings.HollowTypeName, bannedSuffix)); - consumer.AddHighlighting(highlighting, typeExpression.GetDocumentRange()); + var identifier = typeExpression.NameIdentifier; + consumer.AddHighlighting(highlighting, identifier.GetDocumentRange()); } protected override bool IsEnabled { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.HollowTypeNameEnabled); } } + + protected override string Value + { + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.HollowTypeNameString); } + } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnMaximumLinesChange.cs b/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs similarity index 78% rename from CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnMaximumLinesChange.cs rename to CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs index ec3bef9..f9795af 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnMaximumLinesChange.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs @@ -25,21 +25,21 @@ // OR OTHER DEALINGS IN THE SOFTWARE. #endregion -namespace CleanCode.Features.HollowNames -{ - using CleanCode.Settings; +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.DataFlow; +using JetBrains.ProjectModel; +using JetBrains.ReSharper.Daemon; - using JetBrains.Application.Settings; - using JetBrains.DataFlow; - using JetBrains.ProjectModel; - using JetBrains.ReSharper.Daemon; +namespace CleanCode.Features.HollowNames +{ [SolutionComponent] - public class InvalidateOnMaximumLinesChange + public class InvalidateOnHollowTypeNameStringChange { - public InvalidateOnMaximumLinesChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + public InvalidateOnHollowTypeNameStringChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) { - var maxLines = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.MethodTooLongMaximum); + var maxLines = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.HollowTypeNameString); settingsStore.AdviseChange(lifetime, maxLines, daemon.Invalidate); } } diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs index 6bfff4d..33d7bd0 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs @@ -8,32 +8,32 @@ namespace CleanCode.Features.MethodNameNotMeaningful { - public class MethodNameNotMeaningfulCheck : SimpleCheck + public class MethodNameNotMeaningfulCheck : MonoValueCheck { public MethodNameNotMeaningfulCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) { - var minimumMethodNameLenght = Threshold; + var minimumMethodNameLenght = Value; - if (typeExpression.NameIdentifier == null) + if (classDeclaration.NameIdentifier == null) { return; } - var name = typeExpression.NameIdentifier.GetText(); + var name = classDeclaration.NameIdentifier.GetText(); var methodNameLenght = name.Length; if (methodNameLenght < minimumMethodNameLenght) { var highlighting = new Highlighting(Warnings.MethodNameNotMeaningful); - consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimum); } } diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs index 1feb1b2..0a8384e 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs @@ -8,26 +8,26 @@ namespace CleanCode.Features.MethodTooLong { - public class MethodTooLongCheck : SimpleCheck + public class MethodTooLongCheck : MonoValueCheck { public MethodTooLongCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) { - var maxLength = Threshold; + var maxLength = Value; - var statementCount = typeExpression.CountChildren(); + var statementCount = classDeclaration.CountChildren(); if (statementCount > maxLength) { var highlighting = new Highlighting(Warnings.Warning_MethodTooLong); - consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongMaximum); } } diff --git a/CleanCode/src/CleanCode/Features/MonoValueCheck.cs b/CleanCode/src/CleanCode/Features/MonoValueCheck.cs new file mode 100644 index 0000000..0c87c88 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/MonoValueCheck.cs @@ -0,0 +1,16 @@ +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Psi.Tree; + +namespace CleanCode.Features +{ + public abstract class MonoValueCheck : Check + where TElement : ITreeNode + { + protected MonoValueCheck(IContextBoundSettingsStore settingsStore) + : base(settingsStore) + { + } + + protected abstract TValue Value { get; } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs index 6505691..7c8f0d4 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs @@ -10,18 +10,18 @@ namespace CleanCode.Features.TooManyDependencies { - public class TooManyDependenciesCheck : SimpleCheck + public class TooManyDependenciesCheck : MonoValueCheck { public TooManyDependenciesCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IConstructorDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IConstructorDeclaration classDeclaration, IHighlightingConsumer consumer) { - var maxDependencies = Threshold; + var maxDependencies = Value; - var depedencies = typeExpression.ParameterDeclarations.Select( + var depedencies = classDeclaration.ParameterDeclarations.Select( declaration => declaration.DeclaredElement != null && declaration.DeclaredElement.Type.IsInterfaceType()); @@ -30,11 +30,11 @@ protected override void ExecuteCore(IConstructorDeclaration typeExpression, IHig if (dependenciesCount > maxDependencies) { var highlighting = new Highlighting(Warnings.TooManyDependencies); - consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximum); } } diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs index c80ebbf..eecadb2 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs @@ -8,26 +8,26 @@ namespace CleanCode.Features.TooManyMethodArguments { - public class TooManyMethodArgumentsCheck : SimpleCheck + public class TooManyMethodArgumentsCheck : MonoValueCheck { public TooManyMethodArgumentsCheck(IContextBoundSettingsStore settingsStore) : base(settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration typeExpression, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) { - var parameterDeclarations = typeExpression.ParameterDeclarations; - var maxParameters = Threshold; + var parameterDeclarations = classDeclaration.ParameterDeclarations; + var maxParameters = Value; if (parameterDeclarations.Count > maxParameters) { var highlighting = new Highlighting(Warnings.TooManyMethodArguments); - consumer.AddHighlighting(highlighting, typeExpression.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); } } - protected override int Threshold + protected override int Value { get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); } } diff --git a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs index 94ae2e1..22aab15 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs @@ -123,6 +123,24 @@ public static string FlagArgumentsCheck { } } + /// + /// Looks up a localized string similar to Hollow Type Name Check. + /// + public static string HollowTypeNameCheck { + get { + return ResourceManager.GetString("HollowTypeNameCheck", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to List of meaningless suffixes. + /// + public static string HollowTypeNameWords { + get { + return ResourceManager.GetString("HollowTypeNameWords", resourceCulture); + } + } + /// /// Looks up a localized string similar to Maximum Chained References. /// diff --git a/CleanCode/src/CleanCode/Resources/Settings.resx b/CleanCode/src/CleanCode/Resources/Settings.resx index b5b06df..f9ad440 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.resx +++ b/CleanCode/src/CleanCode/Resources/Settings.resx @@ -174,4 +174,10 @@ Flag Arguments Check + + Hollow Type Name Check + + + List of meaningless suffixes + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs index 2fa4694..71ec71c 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs @@ -106,7 +106,7 @@ public static string FlagArgument { } /// - /// Looks up a localized string similar to The usage of the suffix '{0}' is discouraged. It doesn't express the responsiblity of the type accurately. Chose a meaningful name.. + /// Looks up a localized string similar to The usage of the suffix '{0}' is discouraged because it's too generic. Please, choose a meaningful name instead to clarify its intent and responsibilities.. /// public static string HollowTypeName { get { diff --git a/CleanCode/src/CleanCode/Resources/Warnings.resx b/CleanCode/src/CleanCode/Resources/Warnings.resx index bbc6f21..28095cc 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.resx +++ b/CleanCode/src/CleanCode/Resources/Warnings.resx @@ -145,6 +145,6 @@ This expression is too complex to be legible. Please, simplify it. - The usage of the suffix '{0}' is discouraged. It doesn't express the responsiblity of the type accurately. Chose a meaningful name. + The usage of the suffix '{0}' is discouraged because it's too generic. Please, choose a meaningful name instead to clarify its intent and responsibilities. \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs b/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs index 8012bef..f2a1c1c 100644 --- a/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs +++ b/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Linq.Expressions; +using JetBrains.Annotations; using JetBrains.Application.Settings; namespace CleanCode.Settings @@ -10,13 +11,25 @@ public class CheckSettingViewModel : ViewModel protected readonly IContextBoundSettingsStore Settings; - public CheckSettingViewModel(IContextBoundSettingsStore settings, Expression> isEnabledSelector) + public CheckSettingViewModel([NotNull] IContextBoundSettingsStore settings, + [NotNull] Expression> isEnabledSelector) { + if (settings == null) + { + throw new ArgumentNullException("settings"); + } + + if (isEnabledSelector == null) + { + throw new ArgumentNullException("isEnabledSelector"); + } + this.Settings = settings; - this.isEnabledSelector = isEnabledSelector; - + this.isEnabledSelector = isEnabledSelector; } + public string Category { get; set; } + public bool IsEnabled { get { return Settings.GetValue(isEnabledSelector); } diff --git a/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs b/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs index 53e83a1..02da0c9 100644 --- a/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs +++ b/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs @@ -1,4 +1,6 @@ -using System.Windows; +using System; +using System.Linq; +using System.Windows; using System.Windows.Controls; namespace CleanCode.Settings @@ -7,14 +9,20 @@ public class CheckTemplateSelector : DataTemplateSelector { public DataTemplate ThresholdCheckTemplate { get; set; } public DataTemplate BasicCheckTemplate { get; set; } + public DataTemplate StringCheckTemplate { get; set; } public override DataTemplate SelectTemplate(object item, DependencyObject container) { + if (item == null) + { + return base.SelectTemplate(item, container); + } + var type = item.GetType(); - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ThresholdCheckSettingViewModel<>)) + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(MonoValueCheckSettingViewModel<>)) { - return ThresholdCheckTemplate; + return GetTemplateFromGenericType(type); } if (item is CheckSettingViewModel) { @@ -23,6 +31,17 @@ public override DataTemplate SelectTemplate(object item, DependencyObject contai return base.SelectTemplate(item, container); } + private DataTemplate GetTemplateFromGenericType(Type type) + { + var firstType = type.GetGenericArguments().First(); + if (firstType == typeof (string)) + { + return StringCheckTemplate; + } + return ThresholdCheckTemplate; + } + + bool IsTypeof(object t) { return (t is T); diff --git a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs index 361c6af..6a7d78c 100644 --- a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs +++ b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs @@ -74,9 +74,13 @@ public class CleanCodeSettings public bool FlagArgumentsEnabled { get; set; } [SettingsEntry(true, "HollowTypeNameEnabled")] - public bool HollowTypeNameEnabled { get; set; } + public bool HollowTypeNameEnabled { get; set; } + + [SettingsEntry("Handler,Manager,Processor,Controller,Helper", "HollowTypeNameString")] + public string HollowTypeNameString { get; set; } [SettingsEntry(true, "ComplexExpressionEnabled")] + public bool ComplexExpressionEnabled { get; set; } [SettingsEntry(1, "ComplexExpressionMaximum")] public int ComplexExpressionMaximum { get; set; } diff --git a/CleanCode/src/CleanCode/Settings/ThresholdCheckSettingViewModel.cs b/CleanCode/src/CleanCode/Settings/MonoValueCheckSettingViewModel.cs similarity index 76% rename from CleanCode/src/CleanCode/Settings/ThresholdCheckSettingViewModel.cs rename to CleanCode/src/CleanCode/Settings/MonoValueCheckSettingViewModel.cs index 6fc9d80..ab0767d 100644 --- a/CleanCode/src/CleanCode/Settings/ThresholdCheckSettingViewModel.cs +++ b/CleanCode/src/CleanCode/Settings/MonoValueCheckSettingViewModel.cs @@ -4,11 +4,11 @@ namespace CleanCode.Settings { - public class ThresholdCheckSettingViewModel : CheckSettingViewModel + public class MonoValueCheckSettingViewModel : CheckSettingViewModel { - protected Expression> valueSelector; + private readonly Expression> valueSelector; - public ThresholdCheckSettingViewModel(IContextBoundSettingsStore settings, Expression> isEnabledSelector, Expression> valueSelector) : base(settings, isEnabledSelector) + public MonoValueCheckSettingViewModel(IContextBoundSettingsStore settings, Expression> isEnabledSelector, Expression> valueSelector) : base(settings, isEnabledSelector) { this.valueSelector = valueSelector; } diff --git a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml index 9b79b7e..3b5f561 100644 --- a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml +++ b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml @@ -5,68 +5,154 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:settings="clr-namespace:CleanCode.Settings" mc:Ignorable="d" - d:DataContext="{d:DesignInstance settings:OptionsViewModel}" d:DesignWidth="529" d:DesignHeight="126"> + d:DataContext="{d:DesignInstance settings:OptionsViewModel}" d:DesignWidth="842" d:DesignHeight="414"> + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + - - + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + - - - diff --git a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs index b92e930..e6e0169 100644 --- a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs +++ b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs @@ -1,23 +1,8 @@ using System.Collections; -using System.ComponentModel; -using System.Runtime.CompilerServices; -using JetBrains.Annotations; using JetBrains.Application.Settings; namespace CleanCode.Settings { - public abstract class ViewModel : INotifyPropertyChanged - { - public virtual event PropertyChangedEventHandler PropertyChanged; - - [NotifyPropertyChangedInvocator] - protected void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - var handler = PropertyChanged; - if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); - } - } - public sealed class OptionsViewModel : ViewModel { public OptionsViewModel(IContextBoundSettingsStore settings) @@ -33,102 +18,114 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) { var viewModels = new ArrayList(); - var methodTooLong = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, codeSettings => codeSettings.MethodTooLongEnabled, codeSettings => codeSettings.MethodTooLongMaximum) - { - IsEnabledDescription = Resources.Settings.MethodTooLongCheck, - ValueDescription = Resources.Settings.TooLongLinesPerMethod, - }; - viewModels.Add(methodTooLong); + { + IsEnabledDescription = Resources.Settings.MethodTooLongCheck, + ValueDescription = Resources.Settings.TooLongLinesPerMethod, + Category = Categories.Size, + }); - var tooManyDependencies = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, e => e.TooManyDependenciesMaximumEnabled, e => e.TooManyDependenciesMaximum) - { - IsEnabledDescription = Resources.Settings.MaximumDependenciesCheck, - ValueDescription = Resources.Settings.TooManyDependencies, - }; - viewModels.Add(tooManyDependencies); + { + IsEnabledDescription = Resources.Settings.MaximumDependenciesCheck, + ValueDescription = Resources.Settings.TooManyDependencies, + Category = Categories.Coupling, + }); - var tooManyMethodArguments = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, e => e.TooManyMethodArgumentsEnabled, e => e.TooManyMethodArgumentsMaximum) - { - IsEnabledDescription = Resources.Settings.MaximumMethodArgumentsCheck, - ValueDescription = Resources.Settings.TooManyMethodArguments, - }; - - viewModels.Add(tooManyMethodArguments); + { + IsEnabledDescription = Resources.Settings.MaximumMethodArgumentsCheck, + ValueDescription = Resources.Settings.TooManyMethodArguments, + Category = Categories.Responsibility, + }); - var excessiveDepth = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, - e => e.TooManyDependenciesMaximumEnabled, + e => e.ExcessiveIndentationEnabled, e => e.ExcessiveIndentationMaximum) - { - IsEnabledDescription = Resources.Settings.ExcessiveDepthCheck, - ValueDescription = Resources.Settings.ExcessiveDepth, - }; + { + IsEnabledDescription = Resources.Settings.ExcessiveDepthCheck, + ValueDescription = Resources.Settings.ExcessiveDepth, + Category = Categories.Coupling, + }); - viewModels.Add(excessiveDepth); - - var classTooBig = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, e => e.ClassTooBigEnabled, e => e.ClassTooBigMaximum) - { - IsEnabledDescription = Resources.Settings.ClassTooBigCheck, - ValueDescription = Resources.Settings.ClassTooBig, - }; - - viewModels.Add(classTooBig); + { + IsEnabledDescription = Resources.Settings.ClassTooBigCheck, + ValueDescription = Resources.Settings.ClassTooBig, + Category = Categories.Size, + }); - var chainedReferences = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, e => e.TooManyChainedReferencesEnabled, e => e.TooManyChainedReferencesMaximum) - { - IsEnabledDescription = Resources.Settings.MaxChainedReferencesCheck, - ValueDescription = Resources.Settings.MaxChainedReferences, - }; + { + IsEnabledDescription = Resources.Settings.MaxChainedReferencesCheck, + ValueDescription = Resources.Settings.MaxChainedReferences, + Category = Categories.Responsibility, + }); - viewModels.Add(chainedReferences); - - var methodNameLength = new ThresholdCheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, e => e.MethodNameNotMeaningfulMinimumEnabled, e => e.MethodNameNotMeaningfulMinimum) - { - IsEnabledDescription = Resources.Settings.MinimumMethodNameLengthCheck, - ValueDescription = Resources.Settings.MinimumMethodNameLength, - }; - - viewModels.Add(methodNameLength); - - var complexCondition = new ThresholdCheckSettingViewModel( - settings, - e => e.ComplexExpressionEnabled, - e => e.ComplexExpressionMaximum) - { - IsEnabledDescription = Resources.Settings.ComplexExpressionCheck, - ValueDescription = Resources.Settings.ComplexExpressionMaximum, - }; + { + IsEnabledDescription = Resources.Settings.MinimumMethodNameLengthCheck, + ValueDescription = Resources.Settings.MinimumMethodNameLength, + Category = Categories.Legibility, + }); - viewModels.Add(complexCondition); - - var flagArguments = new CheckSettingViewModel( + viewModels.Add(new MonoValueCheckSettingViewModel( settings, - e => e.FlagArgumentsEnabled) - { - IsEnabledDescription = Resources.Settings.FlagArgumentsCheck, - }; - - viewModels.Add(flagArguments); + e => e.ComplexExpressionEnabled, + e => e.ComplexExpressionMaximum) + { + IsEnabledDescription = Resources.Settings.ComplexExpressionCheck, + ValueDescription = Resources.Settings.ComplexExpressionMaximum, + Category = Categories.Complexity, + }); + + viewModels.Add(new CheckSettingViewModel( + settings, + e => e.FlagArgumentsEnabled) + { + IsEnabledDescription = Resources.Settings.FlagArgumentsCheck, + Category = Categories.Responsibility, + }); + + viewModels.Add(new MonoValueCheckSettingViewModel( + settings, + codeSettings => codeSettings.HollowTypeNameEnabled, + codeSettings => codeSettings.HollowTypeNameString) + { + IsEnabledDescription = Resources.Settings.HollowTypeNameCheck, + ValueDescription = Resources.Settings.HollowTypeNameWords, + Category = Categories.Legibility, + }); return viewModels; } } + + public class Categories + { + public const string Size = "Size"; + public const string Complexity = "Complexity"; + public const string Coupling = "Coupling"; + public const string Responsibility = "Responsibility"; + public const string Legibility = "Legibility"; + } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/ViewModel.cs b/CleanCode/src/CleanCode/Settings/ViewModel.cs new file mode 100644 index 0000000..2513048 --- /dev/null +++ b/CleanCode/src/CleanCode/Settings/ViewModel.cs @@ -0,0 +1,18 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; + +namespace CleanCode.Settings +{ + public abstract class ViewModel : INotifyPropertyChanged + { + public virtual event PropertyChangedEventHandler PropertyChanged; + + [NotifyPropertyChangedInvocator] + protected void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + var handler = PropertyChanged; + if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); + } + } +} \ No newline at end of file diff --git a/CleanCode/src/NuGet.Packager/Package.nuspec b/CleanCode/src/NuGet.Packager/Package.nuspec index 8dcc68d..a930265 100644 --- a/CleanCode/src/NuGet.Packager/Package.nuspec +++ b/CleanCode/src/NuGet.Packager/Package.nuspec @@ -2,7 +2,7 @@ CleanCode - 4.0.0.6 + 4.0.0.7 CleanCode Hadi Hariri, Matt Ellis, SuperJMN Hadi Hariri, Matt Ellis From 116032e3fa5fd8f72c75a264a2a828c40ffeb4ae Mon Sep 17 00:00:00 2001 From: SuperJMN Date: Sun, 6 Jul 2014 22:41:57 +0200 Subject: [PATCH 17/50] Too many declarations check. Naming fixes. --- CleanCode/src/CleanCode/CleanCode.8.2.csproj | 3 + .../CleanCode/CleanCodeDaemonStageProcess.cs | 6 +- .../ChainedReferencesCheck.cs | 6 +- CleanCode/src/CleanCode/Features/Check.cs | 2 +- .../Features/ClassTooBig/ClassTooBigCheck.cs | 6 +- .../ComplexExpressionCheck.cs | 6 +- .../ExcessiveIndentationCheck.cs | 6 +- .../FlagArguments/FlagArgumentsCheck.cs | 6 +- .../Features/HollowNames/HollowNamesCheck.cs | 6 +- .../MethodNameNotMeaningfulCheck.cs | 8 +-- .../MethodTooLong/MethodTooLongCheck.cs | 6 +- .../TooManyDeclarations/Highlighting.cs | 69 +++++++++++++++++++ .../InvalidateOnMaximumDeclarationsChange.cs | 45 ++++++++++++ .../TooManyDeclarationsCheck.cs | 40 +++++++++++ .../TooManyDependenciesCheck.cs | 8 +-- .../TooManyMethodArgumentsCheck.cs | 6 +- .../CleanCode/Resources/Settings.Designer.cs | 18 +++++ .../src/CleanCode/Resources/Settings.resx | 6 ++ .../CleanCode/Resources/Warnings.Designer.cs | 9 +++ .../src/CleanCode/Resources/Warnings.resx | 3 + .../CleanCode/Settings/CleanCodeSettings.cs | 8 +++ .../CleanCode/Settings/OptionsViewModel.cs | 10 +++ CleanCode/src/NuGet.Packager/Package.nuspec | 2 +- 23 files changed, 250 insertions(+), 35 deletions(-) create mode 100644 CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs create mode 100644 CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs create mode 100644 CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs diff --git a/CleanCode/src/CleanCode/CleanCode.8.2.csproj b/CleanCode/src/CleanCode/CleanCode.8.2.csproj index b203bc7..7b266f2 100644 --- a/CleanCode/src/CleanCode/CleanCode.8.2.csproj +++ b/CleanCode/src/CleanCode/CleanCode.8.2.csproj @@ -87,6 +87,9 @@ + + + Code diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 3daf026..8a291ce 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -32,6 +32,7 @@ using CleanCode.Features.FlagArguments; using CleanCode.Features.MethodNameNotMeaningful; using CleanCode.Features.MethodTooLong; +using CleanCode.Features.TooManyDeclarations; using CleanCode.Features.TooManyDependencies; using CleanCode.Features.TooManyMethodArguments; using JetBrains.Application.Progress; @@ -62,6 +63,7 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase private readonly FlagArgumentsCheck flagArgumentsCheck; private readonly ComplexExpressionCheck complexExpressionCheck; private readonly HollowNamesCheck hollowNamesCheck; + private readonly TooManyDeclarationsCheck tooManyDeclarationsCheck; public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile file, IContextBoundSettingsStore settingsStore) : base(daemonProcess, file) @@ -80,6 +82,7 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil flagArgumentsCheck = new FlagArgumentsCheck(settingsStore); complexExpressionCheck = new ComplexExpressionCheck(settingsStore); hollowNamesCheck = new HollowNamesCheck(settingsStore); + tooManyDeclarationsCheck = new TooManyDeclarationsCheck(settingsStore); } public override void Execute(Action commiter) @@ -97,7 +100,8 @@ public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration tooManyArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); excessiveIndentationCheck.ExecuteIfEnabled(methodDeclaration, context); methodNamesNotMeaningfulCheck.ExecuteIfEnabled(methodDeclaration, context); - flagArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); + flagArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); + tooManyDeclarationsCheck.ExecuteIfEnabled(methodDeclaration, context); } public override void VisitCSharpStatement(ICSharpStatement cSharpStatementParam, IHighlightingConsumer context) diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs index aa7b982..cb64e86 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs @@ -20,11 +20,11 @@ public ChainedReferencesCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(ICSharpStatement classDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(ICSharpStatement constructorDeclaration, IHighlightingConsumer consumer) { - if (classDeclaration != null && !classDeclaration.IsEmbeddedStatement) + if (constructorDeclaration != null && !constructorDeclaration.IsEmbeddedStatement) { - this.HighlightMethodChainsThatAreTooLong(classDeclaration, consumer); + this.HighlightMethodChainsThatAreTooLong(constructorDeclaration, consumer); } } diff --git a/CleanCode/src/CleanCode/Features/Check.cs b/CleanCode/src/CleanCode/Features/Check.cs index 404aaf2..c0ff9ab 100644 --- a/CleanCode/src/CleanCode/Features/Check.cs +++ b/CleanCode/src/CleanCode/Features/Check.cs @@ -31,6 +31,6 @@ public void ExecuteIfEnabled(TElement methodDeclaration, IHighlightingConsumer c this.ExecuteCore(methodDeclaration, context); } - protected abstract void ExecuteCore(TElement classDeclaration, IHighlightingConsumer consumer); + protected abstract void ExecuteCore(TElement constructorDeclaration, IHighlightingConsumer consumer); } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs index dd308f1..1aac280 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs @@ -15,14 +15,14 @@ public ClassTooBigCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IClassDeclaration classDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IClassDeclaration constructorDeclaration, IHighlightingConsumer consumer) { var maxLength = Value; - var statementCount = classDeclaration.CountChildren(); + var statementCount = constructorDeclaration.CountChildren(); if (statementCount > maxLength) { - var declarationIdentifier = classDeclaration.NameIdentifier; + var declarationIdentifier = constructorDeclaration.NameIdentifier; var documentRange = declarationIdentifier.GetDocumentRange(); var highlighting = new Highlighting(Warnings.ClassTooBig); consumer.AddHighlighting(highlighting, documentRange); diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs index dfb8d10..281b7ba 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs @@ -18,15 +18,15 @@ public ComplexExpressionCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IExpression classDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IExpression constructorDeclaration, IHighlightingConsumer consumer) { var maxExpressions = this.Value; - var depth = classDeclaration.GetChildrenRecursive().Count(); + var depth = constructorDeclaration.GetChildrenRecursive().Count(); if (depth > maxExpressions) { var highlighting = new ExcessiveIndentation.Highlighting(Warnings.ExpressionTooComplex); - consumer.AddHighlighting(highlighting, classDeclaration.GetDocumentRange()); + consumer.AddHighlighting(highlighting, constructorDeclaration.GetDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs index 59c4bbf..d25dc97 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs @@ -15,15 +15,15 @@ public ExcessiveIndentationCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, IHighlightingConsumer consumer) { var maxIndentation = Value; - var depth = classDeclaration.GetChildrenDepth(); + var depth = constructorDeclaration.GetChildrenDepth(); if (depth > maxIndentation) { var highlighting = new Highlighting(Warnings.ExcessiveDepth); - consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs index 9030380..c3d2fb7 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs @@ -20,13 +20,13 @@ public FlagArgumentsCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, IHighlightingConsumer consumer) { - var parameterDeclarations = classDeclaration.ParameterDeclarations; + var parameterDeclarations = constructorDeclaration.ParameterDeclarations; foreach (var parameterDeclaration in parameterDeclarations) { - if (IsFlagArgument(parameterDeclaration, classDeclaration.Body)) + if (IsFlagArgument(parameterDeclaration, constructorDeclaration.Body)) { AddHighlighting(consumer, parameterDeclaration); } diff --git a/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs index 415ecbb..65e7b53 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs @@ -23,15 +23,15 @@ public HollowNamesCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IClassDeclaration classDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IClassDeclaration constructorDeclaration, IHighlightingConsumer consumer) { var suffixes = GetSuffixes(); - var match = GetFirstMatchOrDefault(classDeclaration.DeclaredName, suffixes); + var match = GetFirstMatchOrDefault(constructorDeclaration.DeclaredName, suffixes); if (match != null) { - AddHightlightning(match, consumer, classDeclaration); + AddHightlightning(match, consumer, constructorDeclaration); } } diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs index 33d7bd0..7716b57 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs @@ -15,21 +15,21 @@ public MethodNameNotMeaningfulCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, IHighlightingConsumer consumer) { var minimumMethodNameLenght = Value; - if (classDeclaration.NameIdentifier == null) + if (constructorDeclaration.NameIdentifier == null) { return; } - var name = classDeclaration.NameIdentifier.GetText(); + var name = constructorDeclaration.NameIdentifier.GetText(); var methodNameLenght = name.Length; if (methodNameLenght < minimumMethodNameLenght) { var highlighting = new Highlighting(Warnings.MethodNameNotMeaningful); - consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs index 0a8384e..8d3e796 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs @@ -15,15 +15,15 @@ public MethodTooLongCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, IHighlightingConsumer consumer) { var maxLength = Value; - var statementCount = classDeclaration.CountChildren(); + var statementCount = constructorDeclaration.CountChildren(); if (statementCount > maxLength) { var highlighting = new Highlighting(Warnings.Warning_MethodTooLong); - consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs b/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs new file mode 100644 index 0000000..3001f59 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs @@ -0,0 +1,69 @@ +#region License +// Copyright (C) 2012 Hadi Hariri and Contributors +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall +// be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT +// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using CleanCode.Features.TooManyDeclarations; +using JetBrains.ReSharper.Daemon; +using JetBrains.ReSharper.Psi.CSharp; + +[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, + HighlightingGroupIds.CodeSmell, "Method Too Long", "The method is bigger than it should be.", + Severity.SUGGESTION, false)] + +namespace CleanCode.Features.TooManyDeclarations +{ + [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] + public class Highlighting : IHighlighting + { + internal const string SeverityID = "MethodTooLong"; + private readonly string tooltip; + + public Highlighting(string toolTip) + { + tooltip = toolTip; + } + + public string ToolTip + { + get { return tooltip; } + } + + public string ErrorStripeToolTip + { + get { return tooltip; } + } + + public int NavigationOffsetPatch + { + get { return 0; } + } + + public bool IsValid() + { + return true; + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs b/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs new file mode 100644 index 0000000..949d663 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs @@ -0,0 +1,45 @@ +#region License +// Copyright (C) 2012 Hadi Hariri and Contributors +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall +// be included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT +// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.DataFlow; +using JetBrains.ProjectModel; +using JetBrains.ReSharper.Daemon; + +namespace CleanCode.Features.TooManyDeclarations +{ + [SolutionComponent] + public class InvalidateOnMaximumDeclarationsChange + { + public InvalidateOnMaximumDeclarationsChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + { + var maxLines = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyDeclarationsMaximum); + settingsStore.AdviseChange(lifetime, maxLines, daemon.Invalidate); + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs new file mode 100644 index 0000000..0b53dee --- /dev/null +++ b/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs @@ -0,0 +1,40 @@ +using CleanCode.Resources; +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.CSharp.Stages; +using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.Tree; + +namespace CleanCode.Features.TooManyDeclarations +{ + public class TooManyDeclarationsCheck : MonoValueCheck + { + public TooManyDeclarationsCheck(IContextBoundSettingsStore settingsStore) + : base(settingsStore) + { + } + + protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, IHighlightingConsumer consumer) + { + var maxLength = Value; + + var statementCount = constructorDeclaration.CountChildren(); + if (statementCount > maxLength) + { + var highlighting = new MethodTooLong.Highlighting(Warnings.Warning_TooManyDeclarations); + consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); + } + } + + protected override int Value + { + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDeclarationsMaximum); } + } + + protected override bool IsEnabled + { + get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDeclarationsEnabled); } + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs index 7c8f0d4..f4584d3 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs @@ -17,20 +17,20 @@ public TooManyDependenciesCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IConstructorDeclaration classDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IConstructorDeclaration constructorDeclaration, IHighlightingConsumer consumer) { var maxDependencies = Value; - var depedencies = classDeclaration.ParameterDeclarations.Select( + var dependencies = constructorDeclaration.ParameterDeclarations.Select( declaration => declaration.DeclaredElement != null && declaration.DeclaredElement.Type.IsInterfaceType()); - var dependenciesCount = depedencies.Count(); + var dependenciesCount = dependencies.Count(); if (dependenciesCount > maxDependencies) { var highlighting = new Highlighting(Warnings.TooManyDependencies); - consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs index eecadb2..76d6047 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs @@ -15,15 +15,15 @@ public TooManyMethodArgumentsCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IMethodDeclaration classDeclaration, IHighlightingConsumer consumer) + protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, IHighlightingConsumer consumer) { - var parameterDeclarations = classDeclaration.ParameterDeclarations; + var parameterDeclarations = constructorDeclaration.ParameterDeclarations; var maxParameters = Value; if (parameterDeclarations.Count > maxParameters) { var highlighting = new Highlighting(Warnings.TooManyMethodArguments); - consumer.AddHighlighting(highlighting, classDeclaration.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); } } diff --git a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs index 22aab15..bac8222 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs @@ -96,6 +96,15 @@ public static string ComplexExpressionMaximum { } } + /// + /// Looks up a localized string similar to Maximum number of declarations per method. + /// + public static string DeclarationsMaximum { + get { + return ResourceManager.GetString("DeclarationsMaximum", resourceCulture); + } + } + /// /// Looks up a localized string similar to Maximum level of nesting. /// @@ -231,6 +240,15 @@ public static string TooLongLinesPerMethod { } } + /// + /// Looks up a localized string similar to Too Many Declarations Check. + /// + public static string TooManyDeclarationsCheck { + get { + return ResourceManager.GetString("TooManyDeclarationsCheck", resourceCulture); + } + } + /// /// Looks up a localized string similar to Set maximum dependencies to. /// diff --git a/CleanCode/src/CleanCode/Resources/Settings.resx b/CleanCode/src/CleanCode/Resources/Settings.resx index f9ad440..c346985 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.resx +++ b/CleanCode/src/CleanCode/Resources/Settings.resx @@ -180,4 +180,10 @@ List of meaningless suffixes + + Maximum number of declarations per method + + + Too Many Declarations Check + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs index 71ec71c..6b878be 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs @@ -149,5 +149,14 @@ public static string Warning_MethodTooLong { return ResourceManager.GetString("Warning_MethodTooLong", resourceCulture); } } + + /// + /// Looks up a localized string similar to Too many declarations. This method is likely doing more than one thing.. + /// + public static string Warning_TooManyDeclarations { + get { + return ResourceManager.GetString("Warning_TooManyDeclarations", resourceCulture); + } + } } } diff --git a/CleanCode/src/CleanCode/Resources/Warnings.resx b/CleanCode/src/CleanCode/Resources/Warnings.resx index 28095cc..20e5f09 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.resx +++ b/CleanCode/src/CleanCode/Resources/Warnings.resx @@ -147,4 +147,7 @@ The usage of the suffix '{0}' is discouraged because it's too generic. Please, choose a meaningful name instead to clarify its intent and responsibilities. + + Too many declarations. This method is likely doing more than one thing. + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs index 6a7d78c..b732c6d 100644 --- a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs +++ b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs @@ -84,5 +84,13 @@ public class CleanCodeSettings public bool ComplexExpressionEnabled { get; set; } [SettingsEntry(1, "ComplexExpressionMaximum")] public int ComplexExpressionMaximum { get; set; } + + [SettingsEntry(true, "TooManyDeclarationsEnabled")] + public readonly bool TooManyDeclarationsEnabled; + [SettingsEntry(6, "TooManyDeclarationsMaximum")] + public readonly int TooManyDeclarationsMaximum; + + [SettingsEntry(true, "InterfacesWithNoPrefixEnabled")] + public readonly bool InterfacesWithNoPrefixEnabled; } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs index e6e0169..5958f30 100644 --- a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs +++ b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs @@ -116,6 +116,16 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) Category = Categories.Legibility, }); + viewModels.Add(new MonoValueCheckSettingViewModel( + settings, + codeSettings => codeSettings.TooManyDeclarationsEnabled, + codeSettings => codeSettings.TooManyDeclarationsMaximum) + { + IsEnabledDescription = Resources.Settings.TooManyDeclarationsCheck, + ValueDescription = Resources.Settings.DeclarationsMaximum, + Category = Categories.Responsibility, + }); + return viewModels; } } diff --git a/CleanCode/src/NuGet.Packager/Package.nuspec b/CleanCode/src/NuGet.Packager/Package.nuspec index a930265..e115afd 100644 --- a/CleanCode/src/NuGet.Packager/Package.nuspec +++ b/CleanCode/src/NuGet.Packager/Package.nuspec @@ -2,7 +2,7 @@ CleanCode - 4.0.0.7 + 4.0.0.8 CleanCode Hadi Hariri, Matt Ellis, SuperJMN Hadi Hariri, Matt Ellis From 4e1dd7d69664ef23c186b866ecaa9100ce38a3e7 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Fri, 2 Sep 2016 16:05:37 +0100 Subject: [PATCH 18/50] Updated readme --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 38dfb17..1fb6a89 100644 --- a/README.md +++ b/README.md @@ -4,21 +4,30 @@ An experiment in trying to automate some of concepts described in [Uncle Bob's books on Clean Code](http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882). -Currently includes: +Each check is intended to highlight a symptom that your code is becoming too complex, is not "clean" enough. Increased complexity can make your code harder to read, understand and maintain. The plugin currently checks: -* TooManyDependencies - Detects when a constructor has more than X interfaces passed in. X is configurable via options dialog +* **Too many dependencies** - warns when a constructor has too many interfaces passed in. +* **Excessive indentation** - warns if a class contains members with too much indentation. +* **Too many chained references** - warns if an expression has too many chained statements, is potentially violating the [Law of Demeter](https://en.wikipedia.org/wiki/Law_of_Demeter). +* **Method too long** - warns when a method contains too many statements. +* **Class too big** - warns if a class has too many method declarations. +* **Too many method parameters** - warns if a method has too many parameters. +* **Method name not meaningful** - simple check that a method name is longer than a certain threshold. + +The limits used by each analysis are configurable in the options page. ### Upcoming features All features are [logged here](http://youtrack.codebetter.com/issues/cc) Please use the previous issue tracker for logging bugs, feature requests, etc. + ## Installing Copy the DLL for each Plugin to the ReSharper\bin\Plugins folder ## License -Licensed under MIT (c) 2012 Hadi Hariri and Contributors +Licensed under MIT (c) 2012 - 2016 Hadi Hariri and Contributors Note: All references to [Clean Code](http://www.cleancoders.com/), including but not limited to the Clean Code icon are used with permission of Robert C. Martin (a.k.a. UncleBob) From 112d1ddd90644794a50728292e76a7084823b30a Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Fri, 2 Sep 2016 16:24:24 +0100 Subject: [PATCH 19/50] Added configuration and readme for flag args --- .../FlagsMethodArgumentsCheck.cs | 2 +- .../CleanCode/Resources/Settings.Designer.cs | 24 ++++++++++++++++--- .../src/CleanCode/Resources/Settings.resx | 6 +++++ .../CleanCode/Settings/OptionsViewModel.cs | 11 +++++++++ README.md | 1 + 5 files changed, 40 insertions(+), 4 deletions(-) diff --git a/CleanCode/src/CleanCode/Features/FlagsMethodArguments/FlagsMethodArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/FlagsMethodArguments/FlagsMethodArgumentsCheck.cs index eb217d0..7c4b17a 100644 --- a/CleanCode/src/CleanCode/Features/FlagsMethodArguments/FlagsMethodArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/FlagsMethodArguments/FlagsMethodArgumentsCheck.cs @@ -21,7 +21,7 @@ protected override void ExecuteCore(IMethodDeclaration methodDeclaration, IHighl var threshold = Threshold; var numberOfFlagsArgument = methodDeclaration.ParameterDeclarations.Count( - declaration => declaration.Type.ToString() == typeof(System.Boolean).FullName); + declaration => declaration.Type.ToString() == typeof(bool).FullName); if (numberOfFlagsArgument > threshold) { diff --git a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs index 1a4dba5..3009b7c 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34014 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -132,6 +132,24 @@ public static string MaximumMethodArgumentsCheck { } } + /// + /// Looks up a localized string similar to Method Flag Arguments. + /// + public static string MethodFlagArgumentsCheck { + get { + return ResourceManager.GetString("MethodFlagArgumentsCheck", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Maximum Boolean (Flag) Arguments in Method. + /// + public static string MethodFlagArgumentsThreshold { + get { + return ResourceManager.GetString("MethodFlagArgumentsThreshold", resourceCulture); + } + } + /// /// Looks up a localized string similar to Maximum Statements Per Method Check. /// @@ -142,7 +160,7 @@ public static string MethodTooLongCheck { } /// - /// Looks up a localized string similar to Minimum lenght for the name of methods. + /// Looks up a localized string similar to Minimum length for the name of methods. /// public static string MinimumMethodNameLength { get { @@ -151,7 +169,7 @@ public static string MinimumMethodNameLength { } /// - /// Looks up a localized string similar to Minimum Method Name Lenght. + /// Looks up a localized string similar to Minimum Method Name Length. /// public static string MinimumMethodNameLengthCheck { get { diff --git a/CleanCode/src/CleanCode/Resources/Settings.resx b/CleanCode/src/CleanCode/Resources/Settings.resx index 64db111..b8216fd 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.resx +++ b/CleanCode/src/CleanCode/Resources/Settings.resx @@ -165,4 +165,10 @@ Minimum Method Name Length + + Method Flag Arguments + + + Maximum Boolean (Flag) Arguments in Method + diff --git a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs index 02047af..4dc44d6 100644 --- a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs +++ b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs @@ -108,6 +108,17 @@ private static ArrayList GetViewModels(IContextBoundSettingsStore settings) viewModels.Add(enableMinimumMethodNameLength); + var flagMethodArguments = new SingleCheckSettingViewModel( + settings, + e => e.FlagMethodArgumentsEnabled, + e => e.FlagMethodArgumentsMinimum) + { + IsEnabledDescription = Resources.Settings.MethodFlagArgumentsCheck, + ValueDescription = Resources.Settings.MethodFlagArgumentsThreshold, + }; + + viewModels.Add(flagMethodArguments); + return viewModels; } } diff --git a/README.md b/README.md index 1fb6a89..4e39f5e 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Each check is intended to highlight a symptom that your code is becoming too com * **Class too big** - warns if a class has too many method declarations. * **Too many method parameters** - warns if a method has too many parameters. * **Method name not meaningful** - simple check that a method name is longer than a certain threshold. +* **Too many flag parameters in method** - warns if too many boolean parameters are used in a method declaration. Multiple boolean values can be easily mixed up. The limits used by each analysis are configurable in the options page. From 47292a32e83078a893cdeaa6828abdf7cc0645f9 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Fri, 2 Sep 2016 16:44:38 +0100 Subject: [PATCH 20/50] Updated readme --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4e39f5e..8ffc49a 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,14 @@ Each check is intended to highlight a symptom that your code is becoming too com * **Too many dependencies** - warns when a constructor has too many interfaces passed in. * **Excessive indentation** - warns if a class contains members with too much indentation. -* **Too many chained references** - warns if an expression has too many chained statements, is potentially violating the [Law of Demeter](https://en.wikipedia.org/wiki/Law_of_Demeter). +* **Too many chained references** - warns if an expression has too many chained statements, is potentially violating the [Law of Demeter](https://en.wikipedia.org/wiki/Law_of_Demeter). The check will try to ignore fluent APIs - if the type returned is the same as the type invoked, it doesn't count. * **Method too long** - warns when a method contains too many statements. * **Class too big** - warns if a class has too many method declarations. * **Too many method parameters** - warns if a method has too many parameters. * **Method name not meaningful** - simple check that a method name is longer than a certain threshold. -* **Too many flag parameters in method** - warns if too many boolean parameters are used in a method declaration. Multiple boolean values can be easily mixed up. +* **Method flag parameters** - warns if a boolean or enum method parameter is used in an `if` statement with the method. This is an indication that the method has more than one responsibility. +* **Condition complexity** - warns if the condition in an `if` statement contains too many expressions. +* **Hollow type names** - warns if a class has a name with a suffix that is too general, e.g. `Handler`, `Manager`, `Controller`. The list of names is configurable. The limits used by each analysis are configurable in the options page. From 05f0153e8f8c7fb8a6eddabc25f0a4a8d99bac5a Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Fri, 2 Sep 2016 16:45:31 +0100 Subject: [PATCH 21/50] Rename project --- CleanCode/src/CleanCode.sln | 4 ++-- .../CleanCode/{CleanCode.8.2.csproj => CleanCode.csproj} | 0 CleanCode/src/NuGet.Packager/NuGet.Packager.csproj | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) rename CleanCode/src/CleanCode/{CleanCode.8.2.csproj => CleanCode.csproj} (100%) diff --git a/CleanCode/src/CleanCode.sln b/CleanCode/src/CleanCode.sln index 9321c79..42e9606 100644 --- a/CleanCode/src/CleanCode.sln +++ b/CleanCode/src/CleanCode.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.30501.0 +VisualStudioVersion = 12.0.40629.0 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanCode.8.2", "CleanCode\CleanCode.8.2.csproj", "{5F96119C-2646-4298-AD40-30209E7E7BB2}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanCode", "CleanCode\CleanCode.csproj", "{5F96119C-2646-4298-AD40-30209E7E7BB2}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NuGet.Packager", "NuGet.Packager\NuGet.Packager.csproj", "{0451BAEF-DF2E-4B98-8644-94EE9415E389}" EndProject diff --git a/CleanCode/src/CleanCode/CleanCode.8.2.csproj b/CleanCode/src/CleanCode/CleanCode.csproj similarity index 100% rename from CleanCode/src/CleanCode/CleanCode.8.2.csproj rename to CleanCode/src/CleanCode/CleanCode.csproj diff --git a/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj b/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj index e433496..9351f37 100644 --- a/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj +++ b/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj @@ -11,7 +11,8 @@ NuGet.Packager NuGet.Packager v4.0 - + + 512 @@ -64,9 +65,9 @@ - + {5f96119c-2646-4298-ad40-30209e7e7bb2} - CleanCode.8.2 + CleanCode From 1cc46a70862d5b7b5dd2d44ec191708a1b47fbcc Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Fri, 2 Sep 2016 17:25:59 +0100 Subject: [PATCH 22/50] Clean compile for ReSharper 2016.2 --- CleanCode/src/CleanCode/CleanCode.csproj | 167 +++++++++- .../src/CleanCode/CleanCodeDaemonStage.cs | 4 +- .../CleanCode/CleanCodeDaemonStageProcess.cs | 3 +- .../ChainedReferencesCheck.cs | 21 +- .../ChainedReferences/Highlighting.cs | 17 +- .../InvalidateOnMaximumChainedCalls.cs | 4 +- CleanCode/src/CleanCode/Features/Check.cs | 8 +- .../Features/ClassTooBig/ClassTooBigCheck.cs | 11 +- .../Features/ClassTooBig/Highlighting.cs | 17 +- .../InvalidateOnMaximumMethodsPerClass.cs | 4 +- .../ComplexExpressionCheck.cs | 46 ++- .../ComplexExpression/Highlighting.cs | 21 +- .../InvalidateOnComplexExpressionChange.cs | 15 +- .../ExcessiveIndentationCheck.cs | 12 +- .../ExcessiveIndentation/Highlighting.cs | 17 +- .../InvalidateOnExcessiveIndentationChange.cs | 4 +- .../FlagArguments/FlagArgumentsCheck.cs | 8 +- .../Features/FlagArguments/Highlighting.cs | 17 +- .../Features/HollowNames/Highlighting.cs | 26 +- .../Features/HollowNames/HollowNamesCheck.cs | 28 +- .../InvalidateOnHollowTypeNameStringChange.cs | 4 +- .../MethodNameNotMeaningful/Highlighting.cs | 17 +- ...validateOnMinimumMethodNameLenghtChange.cs | 4 +- .../MethodNameNotMeaningfulCheck.cs | 12 +- .../Features/MethodTooLong/Highlighting.cs | 17 +- .../InvalidateOnMaximumLinesChange.cs | 4 +- .../MethodTooLong/MethodTooLongCheck.cs | 11 +- .../TooManyDeclarations/Highlighting.cs | 17 +- .../InvalidateOnMaximumDeclarationsChange.cs | 4 +- .../TooManyDeclarationsCheck.cs | 12 +- .../TooManyDependencies/Highlighting.cs | 17 +- .../InvalidateOnMaximumDependenciesChange.cs | 4 +- .../TooManyDependenciesCheck.cs | 12 +- .../TooManyMethodArguments/Highlighting.cs | 17 +- ...nvalidateOnMaximumMethodArgumentsChange.cs | 4 +- .../TooManyMethodArgumentsCheck.cs | 12 +- .../src/CleanCode/Properties/AssemblyInfo.cs | 7 +- .../{Icons82 => Icons}/Settings/CleanCode.png | Bin .../ThemedIcons.Settings.Generated.Xaml | 0 .../ThemedIcons.Settings.Generated.cs | 304 ++++++++++++++++-- .../Settings/CheckSettingViewModel.cs | 2 +- .../CleanCode/Settings/CleanCodeSettings.cs | 2 +- .../src/CleanCode/Settings/OptionsPage.xaml | 9 +- .../CleanCode/Settings/OptionsPage.xaml.cs | 4 +- CleanCode/src/CleanCode/ZoneMarker.cs | 9 + CleanCode/src/CleanCode/packages.config | 47 ++- 46 files changed, 744 insertions(+), 258 deletions(-) rename CleanCode/src/CleanCode/Resources/{Icons82 => Icons}/Settings/CleanCode.png (100%) rename CleanCode/src/CleanCode/Resources/{Icons82 => Icons}/Settings/ThemedIcons.Settings.Generated.Xaml (100%) rename CleanCode/src/CleanCode/Resources/{Icons82 => Icons}/Settings/ThemedIcons.Settings.Generated.cs (68%) create mode 100644 CleanCode/src/CleanCode/ZoneMarker.cs diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index 861328a..d941173 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -1,6 +1,5 @@  - Debug @@ -15,6 +14,7 @@ v4.0 512 + aa44b150 true @@ -40,15 +40,131 @@ $(MSBuildProjectDirectory)\$(OutputPath) + + ..\packages\Antlr2.Runtime.2.7.7.02\lib\antlr.runtime.dll + True + + + ..\packages\AsyncBridge.JetBrains.0.1.1.0\lib\net40-Client\AsyncBridge.dll + True + + + ..\packages\AsyncIO.0.1.18.0\lib\net40\AsyncIO.dll + True + + + ..\packages\xmlrpcnet.2.5.0\lib\net20\CookComputing.XmlRpcV2.dll + True + + + ..\packages\JetBrains.Platform.Lib.DevExpress.2.0.20150224.0\lib\Net\DevExpress.Data.v7.1.dll + True + + + ..\packages\JetBrains.Platform.Lib.DevExpress.2.0.20150224.0\lib\Net\DevExpress.Utils.v7.1.dll + True + + + ..\packages\JetBrains.Platform.Lib.DevExpress.2.0.20150224.0\lib\Net\DevExpress.XtraEditors.v7.1.dll + True + + + ..\packages\JetBrains.Platform.Lib.DevExpress.2.0.20150224.0\lib\Net\DevExpress.XtraTreeList.v7.1.dll + True + + + ..\packages\SharpZipLib.JetBrains.Stripped.0.86.20150204.1\lib\20\ICSharpCode.SharpZipLib.dll + True + + + ..\packages\DotNetZip.Reduced.1.9.1.8\lib\net20\Ionic.Zip.Reduced.dll + True + + + ..\packages\JetBrains.Annotations.10.1.5\lib\net\JetBrains.Annotations.dll + True + + + ..\packages\JetBrains.Platform.Lib.Microsoft.Deployment.Compression.Cab.2.0.20140304.0\lib\Microsoft.Deployment.Compression.dll + True + + + ..\packages\JetBrains.Platform.Lib.Microsoft.Deployment.Compression.Cab.2.0.20140304.0\lib\Microsoft.Deployment.Compression.Cab.dll + True + + + ..\packages\Microsoft.Web.Xdt.2.1.1\lib\net40\Microsoft.Web.XmlTransform.dll + True + + + ..\packages\Windows7APICodePack.JetBrains.Stripped.1.1.20150225.0\lib\Net\Microsoft.WindowsAPICodePack.dll + True + + + ..\packages\Windows7APICodePack.JetBrains.Stripped.1.1.20150225.0\lib\Net\Microsoft.WindowsAPICodePack.Shell.dll + True + + + ..\packages\JetBrains.Mono.Posix.0.1\lib\net40\Mono.Posix.dll + True + + + ..\packages\NetMQ.3.3.3.1\lib\net40\NetMQ.dll + True + + + ..\packages\Newtonsoft35.Json.7.0.1\lib\net35\Newtonsoft.Json.dll + True + + + ..\packages\NuGet.Core.2.12.0\lib\net40-Client\NuGet.Core.dll + True + + + ..\packages\NUnit.2.6.4\lib\nunit.framework.dll + True + + + ..\packages\NVelocity.1.0.3\lib\NVelocity.dll + True + + + ..\packages\Sprache.JetBrains.2.0.0.44\lib\portable-net4+netcore45+win8+wp8+sl5+MonoAndroid1+MonoTouch1\Sprache.dll + True + + + ..\packages\JetBrains.Platform.Lib.System.Windows.Interactivity.2.0.20140318.0\lib\System.Windows.Interactivity.dll + True + + + ..\packages\Vestris.ResourceLib.JetBrains.1.4.20150303.0\lib\Net\Vestris.ResourceLib.dll + True + + + ..\packages\JetBrains.Platform.Lib.WpfContrib.2.0.20150225.0\lib\Net\WpfContrib.dll + True + + + ..\packages\xunit.JetBrains.1.9.2\lib\net20\xunit.dll + True + + + ..\packages\xunit.abstractions.JetBrains.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\packages\xunit.runner.utility.JetBrains.2.2.0\lib\net35\xunit.runner.utility.desktop.dll + True + @@ -106,6 +222,7 @@ + True True @@ -116,7 +233,6 @@ True True - @@ -127,6 +243,7 @@ + @@ -141,10 +258,7 @@ - - - - + MSBuild:Compile Designer @@ -154,18 +268,49 @@ - + + + + - + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs index 7581ea5..0a52bdd 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs @@ -28,8 +28,8 @@ #endregion using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon; -using JetBrains.ReSharper.Daemon.CSharp.Stages; +using JetBrains.ReSharper.Feature.Services.CSharp.Daemon; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; namespace CleanCode diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 47755bf..9416ebd 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -39,9 +39,8 @@ using CleanCode.Features.TooManyMethodArguments; using JetBrains.Application.Progress; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon; using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.CSharp.Tree; diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs index cb64e86..c9c28fe 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs @@ -1,14 +1,10 @@ using System.Collections.Generic; -using System.Linq; using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.CSharp.Tree; -using JetBrains.ReSharper.Psi.ExtensionsAPI.Resolve; -using JetBrains.ReSharper.Psi.Resolve; using JetBrains.ReSharper.Psi.Tree; namespace CleanCode.Features.ChainedReferences @@ -24,7 +20,7 @@ protected override void ExecuteCore(ICSharpStatement constructorDeclaration, IHi { if (constructorDeclaration != null && !constructorDeclaration.IsEmbeddedStatement) { - this.HighlightMethodChainsThatAreTooLong(constructorDeclaration, consumer); + HighlightMethodChainsThatAreTooLong(constructorDeclaration, consumer); } } @@ -37,7 +33,7 @@ private void HighlightMethodChainsThatAreTooLong(ITreeNode statement, IHighlight var referenceExpression = treeNode as IReferenceExpression; if (referenceExpression != null) { - this.HightlightReferenceExpressionIfNeeded(referenceExpression, consumer); + HightlightReferenceExpressionIfNeeded(referenceExpression, consumer); } else { @@ -79,19 +75,20 @@ private void HightlightReferenceExpressionIfNeeded(IReferenceExpression referenc protected override int Value { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); } } protected override bool IsEnabled { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesEnabled); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesEnabled); } } - public static void AddHighlightning(IReferenceExpression reference, IHighlightingConsumer consumer) + private static void AddHighlightning(IReferenceExpression reference, IHighlightingConsumer consumer) { - var highlighting = new Highlighting(Warnings.ChainedReferences); var nameIdentifier = reference.NameIdentifier; - consumer.AddHighlighting(highlighting, nameIdentifier.GetDocumentRange()); + var documentRange = nameIdentifier.GetDocumentRange(); + var highlighting = new Highlighting(Warnings.ChainedReferences, documentRange); + consumer.AddHighlighting(highlighting); } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs index 2f27065..c39aaf1 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs @@ -26,7 +26,8 @@ #endregion using CleanCode.Features.ChainedReferences; -using JetBrains.ReSharper.Daemon; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; [assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, @@ -40,25 +41,27 @@ public class Highlighting : IHighlighting { internal const string SeverityID = "MaximumChainedReferences"; private readonly string tooltip; + private readonly DocumentRange documentRange; - public Highlighting(string toolTip) + public Highlighting(string toolTip, DocumentRange documentRange) { tooltip = toolTip; + this.documentRange = documentRange; } - public string ToolTip + public DocumentRange CalculateRange() { - get { return tooltip; } + return documentRange; } - public string ErrorStripeToolTip + public string ToolTip { get { return tooltip; } } - public int NavigationOffsetPatch + public string ErrorStripeToolTip { - get { return 0; } + get { return tooltip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs index 12d7de8..daf2c28 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs @@ -29,14 +29,14 @@ using JetBrains.Application.Settings; using JetBrains.DataFlow; using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; +using JetBrains.ReSharper.Feature.Services.Daemon; namespace CleanCode.Features.ChainedReferences { [SolutionComponent] public class InvalidateOnMaximumChainedCalls { - public InvalidateOnMaximumChainedCalls(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + public InvalidateOnMaximumChainedCalls(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) { var maxDepth = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); settingsStore.AdviseChange(lifetime, maxDepth, daemon.Invalidate); diff --git a/CleanCode/src/CleanCode/Features/Check.cs b/CleanCode/src/CleanCode/Features/Check.cs index c0ff9ab..b9136e2 100644 --- a/CleanCode/src/CleanCode/Features/Check.cs +++ b/CleanCode/src/CleanCode/Features/Check.cs @@ -1,5 +1,5 @@ using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.Tree; namespace CleanCode.Features @@ -18,17 +18,17 @@ protected Check(IContextBoundSettingsStore settingsStore) protected IContextBoundSettingsStore SettingsStore { - get { return this.settingsStore; } + get { return settingsStore; } } public void ExecuteIfEnabled(TElement methodDeclaration, IHighlightingConsumer context) { - if (!this.IsEnabled) + if (!IsEnabled) { return; } - this.ExecuteCore(methodDeclaration, context); + ExecuteCore(methodDeclaration, context); } protected abstract void ExecuteCore(TElement constructorDeclaration, IHighlightingConsumer consumer); diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs index 1aac280..9e5c860 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs @@ -1,8 +1,7 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; @@ -24,19 +23,19 @@ protected override void ExecuteCore(IClassDeclaration constructorDeclaration, IH { var declarationIdentifier = constructorDeclaration.NameIdentifier; var documentRange = declarationIdentifier.GetDocumentRange(); - var highlighting = new Highlighting(Warnings.ClassTooBig); - consumer.AddHighlighting(highlighting, documentRange); + var highlighting = new Highlighting(Warnings.ClassTooBig, documentRange); + consumer.AddHighlighting(highlighting); } } protected override int Value { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigMaximum); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigMaximum); } } protected override bool IsEnabled { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigEnabled); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs index 0954796..afbda4c 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs @@ -26,7 +26,8 @@ #endregion using CleanCode.Features.ClassTooBig; -using JetBrains.ReSharper.Daemon; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; [assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, @@ -40,25 +41,27 @@ public class Highlighting : IHighlighting { internal const string SeverityID = "ClassTooBig"; private readonly string tooltip; + private readonly DocumentRange documentRange; - public Highlighting(string toolTip) + public Highlighting(string toolTip, DocumentRange documentRange) { tooltip = toolTip; + this.documentRange = documentRange; } - public string ToolTip + public DocumentRange CalculateRange() { - get { return tooltip; } + return documentRange; } - public string ErrorStripeToolTip + public string ToolTip { get { return tooltip; } } - public int NavigationOffsetPatch + public string ErrorStripeToolTip { - get { return 0; } + get { return tooltip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs index b512039..d1d661a 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs @@ -29,14 +29,14 @@ using JetBrains.Application.Settings; using JetBrains.DataFlow; using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; +using JetBrains.ReSharper.Feature.Services.Daemon; namespace CleanCode.Features.ClassTooBig { [SolutionComponent] public class InvalidateOnMaximumMethodsPerClass { - public InvalidateOnMaximumMethodsPerClass(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + public InvalidateOnMaximumMethodsPerClass(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) { var maxDepth = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.ClassTooBigMaximum); settingsStore.AdviseChange(lifetime, maxDepth, daemon.Invalidate); diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs index 281b7ba..b0eee83 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs @@ -1,16 +1,13 @@ +using System.Linq; +using CleanCode.Resources; +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.Tree; + namespace CleanCode.Features.ComplexExpression { - using System.Linq; - - using CleanCode.Resources; - using CleanCode.Settings; - - using JetBrains.Application.Settings; - using JetBrains.ReSharper.Daemon.CSharp.Stages; - using JetBrains.ReSharper.Daemon.Stages; - using JetBrains.ReSharper.Psi.CSharp.Tree; - using JetBrains.ReSharper.Psi.Tree; - public class ComplexExpressionCheck : MonoValueCheck { public ComplexExpressionCheck(IContextBoundSettingsStore settingsStore) @@ -18,26 +15,27 @@ public ComplexExpressionCheck(IContextBoundSettingsStore settingsStore) { } - protected override void ExecuteCore(IExpression constructorDeclaration, IHighlightingConsumer consumer) + protected override int Value { - var maxExpressions = this.Value; - var depth = constructorDeclaration.GetChildrenRecursive().Count(); - - if (depth > maxExpressions) - { - var highlighting = new ExcessiveIndentation.Highlighting(Warnings.ExpressionTooComplex); - consumer.AddHighlighting(highlighting, constructorDeclaration.GetDocumentRange()); - } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ComplexExpressionMaximum); } } - protected override int Value + protected override bool IsEnabled { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ComplexExpressionMaximum); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ComplexExpressionEnabled); } } - protected override bool IsEnabled + protected override void ExecuteCore(IExpression constructorDeclaration, IHighlightingConsumer consumer) { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ComplexExpressionEnabled); } + var maxExpressions = Value; + var depth = constructorDeclaration.GetChildrenRecursive().Count(); + + if (depth > maxExpressions) + { + var documentRange = constructorDeclaration.GetDocumentRange(); + var highlighting = new ExcessiveIndentation.Highlighting(Warnings.ExpressionTooComplex, documentRange); + consumer.AddHighlighting(highlighting); + } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs index 8e95e6b..f01225e 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs @@ -26,7 +26,8 @@ #endregion using CleanCode.Features.ComplexExpression; -using JetBrains.ReSharper.Daemon; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; [assembly:RegisterConfigurableSeverity(Highlighting.SeverityID, null, @@ -41,25 +42,27 @@ public class Highlighting : IHighlighting { internal const string SeverityID = "ComplexExpression"; private readonly string tooltip; + private readonly DocumentRange documentRange; - public Highlighting(string toolTip) + public Highlighting(string toolTip, DocumentRange documentRange) { - this.tooltip = toolTip; + tooltip = toolTip; + this.documentRange = documentRange; } - public string ToolTip + public DocumentRange CalculateRange() { - get { return this.tooltip; } + return documentRange; } - public string ErrorStripeToolTip + public string ToolTip { - get { return this.tooltip; } + get { return tooltip; } } - public int NavigationOffsetPatch + public string ErrorStripeToolTip { - get { return 0; } + get { return tooltip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs index e842cd9..fcf836e 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs @@ -25,19 +25,18 @@ // OR OTHER DEALINGS IN THE SOFTWARE. #endregion +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.DataFlow; +using JetBrains.ProjectModel; +using JetBrains.ReSharper.Feature.Services.Daemon; + namespace CleanCode.Features.ComplexExpression { - using CleanCode.Settings; - - using JetBrains.Application.Settings; - using JetBrains.DataFlow; - using JetBrains.ProjectModel; - using JetBrains.ReSharper.Daemon; - [SolutionComponent] public class InvalidateOnComplexExpressionChange { - public InvalidateOnComplexExpressionChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + public InvalidateOnComplexExpressionChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) { var maxDepth = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.ComplexExpressionMaximum); settingsStore.AdviseChange(lifetime, maxDepth, daemon.Invalidate); diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs index d25dc97..450524c 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs @@ -1,8 +1,7 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; @@ -22,19 +21,20 @@ protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, I if (depth > maxIndentation) { - var highlighting = new Highlighting(Warnings.ExcessiveDepth); - consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); + var documentRange = constructorDeclaration.GetNameDocumentRange(); + var highlighting = new Highlighting(Warnings.ExcessiveDepth, documentRange); + consumer.AddHighlighting(highlighting); } } protected override int Value { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationMaximum); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationMaximum); } } protected override bool IsEnabled { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationEnabled); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs index 1086f2f..02f92cb 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs @@ -26,7 +26,8 @@ #endregion using CleanCode.Features.ExcessiveIndentation; -using JetBrains.ReSharper.Daemon; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; [assembly:RegisterConfigurableSeverity(Highlighting.SeverityID, null, @@ -43,25 +44,27 @@ public class Highlighting : IHighlighting { internal const string SeverityID = "ExcessiveIndentation"; private readonly string tooltip; + private readonly DocumentRange documentRange; - public Highlighting(string toolTip) + public Highlighting(string toolTip, DocumentRange documentRange) { tooltip = toolTip; + this.documentRange = documentRange; } - public string ToolTip + public DocumentRange CalculateRange() { - get { return tooltip; } + return documentRange; } - public string ErrorStripeToolTip + public string ToolTip { get { return tooltip; } } - public int NavigationOffsetPatch + public string ErrorStripeToolTip { - get { return 0; } + get { return tooltip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/InvalidateOnExcessiveIndentationChange.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/InvalidateOnExcessiveIndentationChange.cs index 211c5f6..57aaef3 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/InvalidateOnExcessiveIndentationChange.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/InvalidateOnExcessiveIndentationChange.cs @@ -29,14 +29,14 @@ using JetBrains.Application.Settings; using JetBrains.DataFlow; using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; +using JetBrains.ReSharper.Feature.Services.Daemon; namespace CleanCode.Features.ExcessiveIndentation { [SolutionComponent] public class InvalidateOnExcessiveIndentationChange { - public InvalidateOnExcessiveIndentationChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + public InvalidateOnExcessiveIndentationChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) { var maxDepth = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.ExcessiveIndentationMaximum); settingsStore.AdviseChange(lifetime, maxDepth, daemon.Invalidate); diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs index bd14e0a..a35bdae 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs @@ -2,13 +2,12 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.Stages; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.CSharp.Tree; -using JetBrains.ReSharper.Daemon.CSharp.Stages; using JetBrains.ReSharper.Psi.Tree; using System.Collections.Generic; using System.Diagnostics; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.Util; namespace CleanCode.Features.FlagArguments @@ -35,8 +34,9 @@ protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, I private static void AddHighlighting(IHighlightingConsumer consumer, ICSharpParameterDeclaration parameterDeclaration) { - var highlighting = new Highlighting(Warnings.FlagArgument); - consumer.AddHighlighting(highlighting, parameterDeclaration.GetDocumentRange()); + var documentRange = parameterDeclaration.GetDocumentRange(); + var highlighting = new Highlighting(Warnings.FlagArgument, documentRange); + consumer.AddHighlighting(highlighting); } private static bool IsFlagArgument(ITypeOwnerDeclaration typeOwnerDeclaration, ITreeNode node) diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs b/CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs index 788f939..d88187c 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs @@ -26,7 +26,8 @@ #endregion using CleanCode.Features.FlagArguments; -using JetBrains.ReSharper.Daemon; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; [assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, @@ -40,25 +41,27 @@ public class Highlighting : IHighlighting { internal const string SeverityID = "FlagArguments"; private readonly string tooltip; + private readonly DocumentRange documentRange; - public Highlighting(string toolTip) + public Highlighting(string toolTip, DocumentRange documentRange) { tooltip = toolTip; + this.documentRange = documentRange; } - public string ToolTip + public DocumentRange CalculateRange() { - get { return tooltip; } + return documentRange; } - public string ErrorStripeToolTip + public string ToolTip { get { return tooltip; } } - public int NavigationOffsetPatch + public string ErrorStripeToolTip { - get { return 0; } + get { return tooltip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs b/CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs index 3ee8a65..8a12aa8 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs @@ -26,8 +26,9 @@ #endregion using CleanCode.Features.HollowNames; - -using JetBrains.ReSharper.Daemon; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp; [assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, HighlightingGroupIds.CodeSmell, "Hollow Type Name", "This type has a name that doesn't express its intent.", @@ -35,33 +36,32 @@ namespace CleanCode.Features.HollowNames { - using JetBrains.ReSharper.Daemon; - using JetBrains.ReSharper.Psi.CSharp; - [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] public class Highlighting : IHighlighting { internal const string SeverityID = "HollowTypeName"; private readonly string tooltip; + private readonly DocumentRange documentRange; - public Highlighting(string toolTip) + public Highlighting(string toolTip, DocumentRange documentRange) { - this.tooltip = toolTip; + tooltip = toolTip; + this.documentRange = documentRange; } - public string ToolTip + public DocumentRange CalculateRange() { - get { return this.tooltip; } + return documentRange; } - public string ErrorStripeToolTip + public string ToolTip { - get { return this.tooltip; } + get { return tooltip; } } - public int NavigationOffsetPatch + public string ErrorStripeToolTip { - get { return 0; } + get { return tooltip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs index 65e7b53..f59a0d2 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs @@ -1,19 +1,16 @@ using System; +using System.Collections.Generic; +using System.Linq; +using CleanCode.Resources; +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; -using JetBrains.ReSharper.Psi.Xaml.Tree.MarkupExtensions; +using JetBrains.ReSharper.Psi.Tree; +using IContextBoundSettingsStore = JetBrains.Application.Settings.IContextBoundSettingsStore; namespace CleanCode.Features.HollowNames { - using System.Collections.Generic; - using System.Linq; - - using CleanCode.Resources; - using CleanCode.Settings; - using JetBrains.Application.Settings; - using JetBrains.ReSharper.Daemon.CSharp.Stages; - using JetBrains.ReSharper.Daemon.Stages; - using JetBrains.ReSharper.Psi.Tree; - public class HollowNamesCheck : MonoValueCheck { private const string Separator = ","; @@ -47,19 +44,20 @@ private static string GetFirstMatchOrDefault(string declaredName, IEnumerable s.HollowTypeNameEnabled); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.HollowTypeNameEnabled); } } protected override string Value { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.HollowTypeNameString); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.HollowTypeNameString); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs b/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs index f9795af..3778288 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs @@ -29,7 +29,7 @@ using JetBrains.Application.Settings; using JetBrains.DataFlow; using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; +using JetBrains.ReSharper.Feature.Services.Daemon; namespace CleanCode.Features.HollowNames { @@ -37,7 +37,7 @@ namespace CleanCode.Features.HollowNames [SolutionComponent] public class InvalidateOnHollowTypeNameStringChange { - public InvalidateOnHollowTypeNameStringChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + public InvalidateOnHollowTypeNameStringChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) { var maxLines = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.HollowTypeNameString); settingsStore.AdviseChange(lifetime, maxLines, daemon.Invalidate); diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs index a00aa83..f6b1793 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs @@ -26,7 +26,8 @@ #endregion using CleanCode.Features.MethodNameNotMeaningful; -using JetBrains.ReSharper.Daemon; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; [assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, @@ -44,25 +45,27 @@ public class Highlighting : IHighlighting { internal const string SeverityID = "MethodNamesNotMeaningful"; private readonly string tooltip; + private readonly DocumentRange documentRange; - public Highlighting(string toolTip) + public Highlighting(string toolTip, DocumentRange documentRange) { tooltip = toolTip; + this.documentRange = documentRange; } - public string ToolTip + public DocumentRange CalculateRange() { - get { return tooltip; } + return documentRange; } - public string ErrorStripeToolTip + public string ToolTip { get { return tooltip; } } - public int NavigationOffsetPatch + public string ErrorStripeToolTip { - get { return 0; } + get { return tooltip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs index 2ec7de2..4f4ff0e 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs @@ -29,14 +29,14 @@ using JetBrains.Application.Settings; using JetBrains.DataFlow; using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; +using JetBrains.ReSharper.Feature.Services.Daemon; namespace CleanCode.Features.MethodNameNotMeaningful { [SolutionComponent] public class InvalidateOnMinimumMethodNameLenghtChange { - public InvalidateOnMinimumMethodNameLenghtChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + public InvalidateOnMinimumMethodNameLenghtChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) { var minMethodNameLenght = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimumEnabled); settingsStore.AdviseChange(lifetime, minMethodNameLenght, daemon.Invalidate); diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs index 7716b57..8dd6f15 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs @@ -1,8 +1,7 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; @@ -28,19 +27,20 @@ protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, I var methodNameLenght = name.Length; if (methodNameLenght < minimumMethodNameLenght) { - var highlighting = new Highlighting(Warnings.MethodNameNotMeaningful); - consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); + var documentRange = constructorDeclaration.GetNameDocumentRange(); + var highlighting = new Highlighting(Warnings.MethodNameNotMeaningful, documentRange); + consumer.AddHighlighting(highlighting); } } protected override int Value { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimum); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimum); } } protected override bool IsEnabled { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimumEnabled); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimumEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs index 684ed63..96778e2 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs @@ -26,7 +26,8 @@ #endregion using CleanCode.Features.MethodTooLong; -using JetBrains.ReSharper.Daemon; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; [assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, @@ -40,25 +41,27 @@ public class Highlighting : IHighlighting { internal const string SeverityID = "MethodTooLong"; private readonly string tooltip; + private readonly DocumentRange documentRange; - public Highlighting(string toolTip) + public Highlighting(string toolTip, DocumentRange documentRange) { tooltip = toolTip; + this.documentRange = documentRange; } - public string ToolTip + public DocumentRange CalculateRange() { - get { return tooltip; } + return documentRange; } - public string ErrorStripeToolTip + public string ToolTip { get { return tooltip; } } - public int NavigationOffsetPatch + public string ErrorStripeToolTip { - get { return 0; } + get { return tooltip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs index cd48f0c..acffdb8 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs @@ -29,14 +29,14 @@ using JetBrains.Application.Settings; using JetBrains.DataFlow; using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; +using JetBrains.ReSharper.Feature.Services.Daemon; namespace CleanCode.Features.MethodTooLong { [SolutionComponent] public class InvalidateOnMaximumLinesChange { - public InvalidateOnMaximumLinesChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + public InvalidateOnMaximumLinesChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) { var maxLines = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.MethodTooLongMaximum); settingsStore.AdviseChange(lifetime, maxLines, daemon.Invalidate); diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs index 8d3e796..1e071eb 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs @@ -1,8 +1,7 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; @@ -22,19 +21,19 @@ protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, I var statementCount = constructorDeclaration.CountChildren(); if (statementCount > maxLength) { - var highlighting = new Highlighting(Warnings.Warning_MethodTooLong); - consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); + var highlighting = new Highlighting(Warnings.Warning_MethodTooLong, constructorDeclaration.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting); } } protected override int Value { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongMaximum); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongMaximum); } } protected override bool IsEnabled { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongEnabled); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs b/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs index 3001f59..d0dddfa 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs @@ -26,7 +26,8 @@ #endregion using CleanCode.Features.TooManyDeclarations; -using JetBrains.ReSharper.Daemon; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; [assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, @@ -40,25 +41,27 @@ public class Highlighting : IHighlighting { internal const string SeverityID = "MethodTooLong"; private readonly string tooltip; + private readonly DocumentRange documentRange; - public Highlighting(string toolTip) + public Highlighting(string toolTip, DocumentRange documentRange) { tooltip = toolTip; + this.documentRange = documentRange; } - public string ToolTip + public DocumentRange CalculateRange() { - get { return tooltip; } + return documentRange; } - public string ErrorStripeToolTip + public string ToolTip { get { return tooltip; } } - public int NavigationOffsetPatch + public string ErrorStripeToolTip { - get { return 0; } + get { return tooltip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs b/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs index 949d663..b5e1825 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs @@ -29,14 +29,14 @@ using JetBrains.Application.Settings; using JetBrains.DataFlow; using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; +using JetBrains.ReSharper.Feature.Services.Daemon; namespace CleanCode.Features.TooManyDeclarations { [SolutionComponent] public class InvalidateOnMaximumDeclarationsChange { - public InvalidateOnMaximumDeclarationsChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + public InvalidateOnMaximumDeclarationsChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) { var maxLines = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyDeclarationsMaximum); settingsStore.AdviseChange(lifetime, maxLines, daemon.Invalidate); diff --git a/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs index 0b53dee..5db2fa5 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs @@ -1,8 +1,7 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; @@ -22,19 +21,20 @@ protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, I var statementCount = constructorDeclaration.CountChildren(); if (statementCount > maxLength) { - var highlighting = new MethodTooLong.Highlighting(Warnings.Warning_TooManyDeclarations); - consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); + var highlighting = new MethodTooLong.Highlighting(Warnings.Warning_TooManyDeclarations, + constructorDeclaration.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting); } } protected override int Value { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDeclarationsMaximum); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDeclarationsMaximum); } } protected override bool IsEnabled { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDeclarationsEnabled); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDeclarationsEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs index e7976f0..6ac6963 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs @@ -26,7 +26,8 @@ #endregion using CleanCode.Features.TooManyDependencies; -using JetBrains.ReSharper.Daemon; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; [assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, @@ -40,25 +41,27 @@ public class Highlighting : IHighlighting { internal const string SeverityID = "TooManyDependencies"; private readonly string tooltip; + private readonly DocumentRange documentRange; - public Highlighting(string toolTip) + public Highlighting(string toolTip, DocumentRange documentRange) { tooltip = toolTip; + this.documentRange = documentRange; } - public string ToolTip + public DocumentRange CalculateRange() { - get { return tooltip; } + return documentRange; } - public string ErrorStripeToolTip + public string ToolTip { get { return tooltip; } } - public int NavigationOffsetPatch + public string ErrorStripeToolTip { - get { return 0; } + get { return tooltip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs index 1a2cde0..d1337af 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs @@ -29,14 +29,14 @@ using JetBrains.Application.Settings; using JetBrains.DataFlow; using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; +using JetBrains.ReSharper.Feature.Services.Daemon; namespace CleanCode.Features.TooManyDependencies { [SolutionComponent] public class InvalidateOnMaximumDependenciesChange { - public InvalidateOnMaximumDependenciesChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + public InvalidateOnMaximumDependenciesChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) { var maxParams = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyDependenciesMaximum); settingsStore.AdviseChange(lifetime, maxParams, daemon.Invalidate); diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs index f4584d3..406c23f 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs @@ -2,8 +2,7 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; using JetBrains.ReSharper.Psi.Util; @@ -29,19 +28,20 @@ protected override void ExecuteCore(IConstructorDeclaration constructorDeclarati if (dependenciesCount > maxDependencies) { - var highlighting = new Highlighting(Warnings.TooManyDependencies); - consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); + var highlighting = new Highlighting(Warnings.TooManyDependencies, + constructorDeclaration.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting); } } protected override int Value { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximum); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximum); } } protected override bool IsEnabled { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximumEnabled); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximumEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs index f4369d8..bc02ca8 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs @@ -26,7 +26,8 @@ #endregion using CleanCode.Features.TooManyMethodArguments; -using JetBrains.ReSharper.Daemon; +using JetBrains.DocumentModel; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; [assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, @@ -40,25 +41,27 @@ public class Highlighting : IHighlighting { internal const string SeverityID = "TooManyArguments"; private readonly string tooltip; + private readonly DocumentRange documentRange; - public Highlighting(string toolTip) + public Highlighting(string toolTip, DocumentRange documentRange) { tooltip = toolTip; + this.documentRange = documentRange; } - public string ToolTip + public DocumentRange CalculateRange() { - get { return tooltip; } + return documentRange; } - public string ErrorStripeToolTip + public string ToolTip { get { return tooltip; } } - public int NavigationOffsetPatch + public string ErrorStripeToolTip { - get { return 0; } + get { return tooltip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs index be1fa24..dbd642e 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs @@ -29,14 +29,14 @@ using JetBrains.Application.Settings; using JetBrains.DataFlow; using JetBrains.ProjectModel; -using JetBrains.ReSharper.Daemon; +using JetBrains.ReSharper.Feature.Services.Daemon; namespace CleanCode.Features.TooManyMethodArguments { [SolutionComponent] public class InvalidateOnMaximumMethodArgumentsChange { - public InvalidateOnMaximumMethodArgumentsChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore) + public InvalidateOnMaximumMethodArgumentsChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) { var maxArguments = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs index 76d6047..77a3751 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs @@ -1,8 +1,7 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Daemon.Stages; +using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; @@ -22,19 +21,20 @@ protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, I if (parameterDeclarations.Count > maxParameters) { - var highlighting = new Highlighting(Warnings.TooManyMethodArguments); - consumer.AddHighlighting(highlighting, constructorDeclaration.GetNameDocumentRange()); + var highlighting = new Highlighting(Warnings.TooManyMethodArguments, + constructorDeclaration.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting); } } protected override int Value { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); } } protected override bool IsEnabled { - get { return this.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsEnabled); } + get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsEnabled); } } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs index d64cedc..e008104 100644 --- a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs +++ b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs @@ -26,7 +26,6 @@ #endregion using System.Reflection; using System.Runtime.InteropServices; -using JetBrains.Application.PluginSupport; [assembly: AssemblyTitle("ReSharper Clean Code Plugin")] [assembly: AssemblyCompany("Hadi Hariri")] @@ -41,6 +40,6 @@ [assembly: AssemblyVersion("4.0.0.*")] -[assembly: PluginTitle("Clean Code")] -[assembly: PluginDescription("Automates some of the concepts in Uncle Bob's Clean Code book")] -[assembly: PluginVendor("Hadi Hariri and Contributors")] +//[assembly: PluginTitle("Clean Code")] +//[assembly: PluginDescription("Automates some of the concepts in Uncle Bob's Clean Code book")] +//[assembly: PluginVendor("Hadi Hariri and Contributors")] diff --git a/CleanCode/src/CleanCode/Resources/Icons82/Settings/CleanCode.png b/CleanCode/src/CleanCode/Resources/Icons/Settings/CleanCode.png similarity index 100% rename from CleanCode/src/CleanCode/Resources/Icons82/Settings/CleanCode.png rename to CleanCode/src/CleanCode/Resources/Icons/Settings/CleanCode.png diff --git a/CleanCode/src/CleanCode/Resources/Icons82/Settings/ThemedIcons.Settings.Generated.Xaml b/CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xaml similarity index 100% rename from CleanCode/src/CleanCode/Resources/Icons82/Settings/ThemedIcons.Settings.Generated.Xaml rename to CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xaml diff --git a/CleanCode/src/CleanCode/Resources/Icons82/Settings/ThemedIcons.Settings.Generated.cs b/CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.cs similarity index 68% rename from CleanCode/src/CleanCode/Resources/Icons82/Settings/ThemedIcons.Settings.Generated.cs rename to CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.cs index 5a41f8f..79dec05 100644 --- a/CleanCode/src/CleanCode/Resources/Icons82/Settings/ThemedIcons.Settings.Generated.cs +++ b/CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.cs @@ -1,19 +1,19 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34003 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ -[assembly: global::System.Windows.Markup.XmlnsDefinitionAttribute("urn:shemas-jetbrains-com:ui-application-icons-settings", "CleanCode.Resources.Icons82")] -[assembly: global::JetBrains.UI.Icons.CompiledIcons.CompiledIconsPackAttribute(IconPackResourceIdentification="CleanCode.8.2;component/Resources/Icons82/Settings/ThemedIcons.Settings.Generat" + - "ed.Xaml", IconNames=new string[] { +[assembly: global::System.Windows.Markup.XmlnsDefinitionAttribute("urn:shemas-jetbrains-com:ui-application-icons-settings", "CleanCode.Resources.Icons")] +[assembly: global::JetBrains.UI.Icons.CompiledIcons.CompiledIconsPackAttribute(IconPackResourceIdentification="CleanCode.8.2;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.X" + + "aml", IconNames=new string[] { "CleanCode"})] -namespace CleanCode.Resources.Icons82 +namespace CleanCode.Resources.Icons { @@ -28,17 +28,17 @@ namespace CleanCode.Resources.Icons82 /// It has two primary goals: load the icons of this assembly to be registered with so that they were WPF-accessible and theme-sensitive; and emit early-bound accessors for referencing icons in codebehind in a compile-time-validated manner. ///

XAML

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

Attributes

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

CodeBehind

/// In codebehind, we have two distinct tasks: (a) specify some icon in the APIs and (b) render icon images onscreen. - /// On the APIs stage you should only manipulate icon identifier objects (of type , statically defined in in Id fields). Icon identifier classes (nested in ) should be turned into icon identifier objects as early as possible. Rendering is about getting an to assign to WPF, or to use with GDI+ / Windows Forms. + /// On the APIs stage you should only manipulate icon identifier objects (of type , statically defined in in Id fields). Icon identifier classes (nested in ) should be turned into icon identifier objects as early as possible. Rendering is about getting an to assign to WPF, or to use with GDI+ / Windows Forms. /// You should turn an identifier object into a rendered image as late as possible. The identifier is static and lightweight and does not depend on the current theme, while the image is themed and has to be loaded or generated/rasterized. You need an instance to get the image out of an icon identifier object. Once you got the image, you should take care to change it with theme changes — either by using a live image property, or by listening to the theme change event. See and its extensions for the related facilities. /// Example: /// // Getting IconId identifier object to use with APIs @@ -58,13 +58,13 @@ public sealed class SettingsThemedIcons /// /// /// Autogenerated identifier class for the CleanCode Themed Icon. - /// Identifier classes should be used in attributes, XAML, or generic parameters. Where an value is expected, use the identifier object in the field of the identifier class. + /// Identifier classes should be used in attributes, XAML, or generic parameters. Where an value is expected, use the identifier object in the field of the identifier class. /// /// /// - /// For details on Themed Icons and their use, see Remarks on class. + /// For details on Themed Icons and their use, see Remarks on class. /// - /// + /// /// /// <Image Source="{icons:ThemedIcon myres:SettingsThemedIcons+CleanCode}" /> <!-- XAML --> /// @@ -77,21 +77,21 @@ public sealed class SettingsThemedIcons /// /// themediconmanager.GetIcon<SettingsThemedIcons.CleanCode>() // Icon image for rendering /// - [global::JetBrains.UI.Icons.CompiledIcons.CompiledIconClassAttribute("CleanCode.8.2;component/Resources/Icons82/Settings/ThemedIcons.Settings.Generat" + - "ed.Xaml", 0, "CleanCode")] + [global::JetBrains.UI.Icons.CompiledIcons.CompiledIconClassAttribute("CleanCode.8.2;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.X" + + "aml", 0, "CleanCode")] public sealed class CleanCode : global::JetBrains.UI.Icons.CompiledIcons.CompiledIconClass { /// /// /// Autogenerated identifier object for the CleanCode Themed Icon. - /// Identifier objects should be used where an value is expected. In attributes, XAML, or generic parameters use the containing identifier class. + /// Identifier objects should be used where an value is expected. In attributes, XAML, or generic parameters use the containing identifier class. /// /// /// - /// For details on Themed Icons and their use, see Remarks on class. + /// For details on Themed Icons and their use, see Remarks on class. /// - /// + /// /// /// <Image Source="{icons:ThemedIcon myres:SettingsThemedIcons+CleanCode}" /> <!-- XAML --> /// @@ -104,8 +104,276 @@ public sealed class CleanCode : global::JetBrains.UI.Icons.CompiledIcons.Compile /// /// themediconmanager.GetIcon<SettingsThemedIcons.CleanCode>() // Icon image for rendering /// - public static global::JetBrains.UI.Icons.IconId Id = new global::JetBrains.UI.Icons.CompiledIcons.CompiledIconId("CleanCode.8.2;component/Resources/Icons82/Settings/ThemedIcons.Settings.Generat" + - "ed.Xaml", 0, "CleanCode"); + public static global::JetBrains.UI.Icons.IconId Id = new global::JetBrains.UI.Icons.CompiledIcons.CompiledIconId("CleanCode.8.2;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.X" + + "aml", 0, "CleanCode"); } } } + + +public sealed class RenderedIcons_ByPackResourceNameHash_759358C69B6C25A0E957D60B8E57EEED +{ + + public static byte[] CleanCode____png__x1 = new byte[] { + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 16, + 0, + 0, + 0, + 16, + 8, + 6, + 0, + 0, + 0, + 31, + 243, + 255, + 97, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 19, + 73, + 68, + 65, + 84, + 56, + 79, + 99, + 24, + 5, + 163, + 96, + 20, + 140, + 2, + 48, + 96, + 96, + 0, + 0, + 4, + 16, + 0, + 1, + 167, + 68, + 124, + 99, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130}; + + public static byte[] CleanCode____png__x2 = new byte[] { + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 32, + 0, + 0, + 0, + 32, + 8, + 6, + 0, + 0, + 0, + 115, + 122, + 122, + 244, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 26, + 73, + 68, + 65, + 84, + 88, + 71, + 237, + 193, + 1, + 1, + 0, + 0, + 0, + 130, + 32, + 255, + 175, + 110, + 72, + 64, + 0, + 0, + 0, + 192, + 185, + 26, + 16, + 32, + 0, + 1, + 157, + 120, + 73, + 67, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130}; +} diff --git a/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs b/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs index f2a1c1c..471333d 100644 --- a/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs +++ b/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs @@ -24,7 +24,7 @@ public CheckSettingViewModel([NotNull] IContextBoundSettingsStore settings, throw new ArgumentNullException("isEnabledSelector"); } - this.Settings = settings; + Settings = settings; this.isEnabledSelector = isEnabledSelector; } diff --git a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs index b732c6d..4ee5fc1 100644 --- a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs +++ b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs @@ -28,7 +28,7 @@ #endregion using JetBrains.Application.Settings; -using JetBrains.ReSharper.Settings; +using JetBrains.ReSharper.Resources.Settings; namespace CleanCode.Settings { diff --git a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml index 3b5f561..97dfe00 100644 --- a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml +++ b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml @@ -65,8 +65,7 @@ - + HorizontalAlignment="Stretch" Grid.Column="2" /> @@ -96,8 +95,7 @@ Grid.Column="2" VerticalAlignment="Center" MaxLength="400" - HorizontalAlignment="Stretch"> - + HorizontalAlignment="Stretch" /> @@ -156,3 +154,6 @@ + + + diff --git a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml.cs b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml.cs index e85c611..0a8613f 100644 --- a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml.cs +++ b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml.cs @@ -1,6 +1,6 @@ -using CleanCode.Resources.Icons82; +using CleanCode.Resources.Icons; using JetBrains.DataFlow; -using JetBrains.ReSharper.Features.Environment.Options.Inspections; +using JetBrains.ReSharper.Feature.Services.Daemon.OptionPages; using JetBrains.UI.Application; using JetBrains.UI.CrossFramework; using JetBrains.UI.Options; diff --git a/CleanCode/src/CleanCode/ZoneMarker.cs b/CleanCode/src/CleanCode/ZoneMarker.cs new file mode 100644 index 0000000..4bafde4 --- /dev/null +++ b/CleanCode/src/CleanCode/ZoneMarker.cs @@ -0,0 +1,9 @@ +using JetBrains.Application.BuildScript.Application.Zones; + +namespace CleanCode +{ + [ZoneMarker] + public class ZoneMarker + { + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/packages.config b/CleanCode/src/CleanCode/packages.config index 6301eb7..184d2a5 100644 --- a/CleanCode/src/CleanCode/packages.config +++ b/CleanCode/src/CleanCode/packages.config @@ -1,4 +1,49 @@  - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 2cdc312fc187920bcc1f24ddcd54b94caf48320f Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Fri, 2 Sep 2016 17:34:40 +0100 Subject: [PATCH 23/50] Updating nuspec --- .../Package.nuspec => CleanCode.nuspec} | 21 +- CleanCode/src/CleanCode.sln | 5 - CleanCode/src/CleanCode/CleanCode.csproj | 4 +- .../src/CleanCode/Properties/AssemblyInfo.cs | 9 +- .../CleanCode/Resources/LocalizedStrings.cs | 14 - CleanCode/src/NuGet.Packager/.gitignore | 2 - .../src/NuGet.Packager/NuGet.Packager.csproj | 93 ------ CleanCode/src/NuGet.Packager/NuGet.config | 8 - CleanCode/src/NuGet.Packager/NuGet.exe | Bin 1662976 -> 0 bytes CleanCode/src/NuGet.Packager/NuGetPackage.ps1 | 313 ------------------ CleanCode/src/NuGet.Packager/NuGetSetup.ps1 | 208 ------------ .../NuGet.Packager/Properties/AssemblyInfo.cs | 36 -- CleanCode/src/NuGet.Packager/tools/init.ps1 | 8 - .../src/NuGet.Packager/tools/install.ps1 | 8 - .../src/NuGet.Packager/tools/uninstall.ps1 | 8 - 15 files changed, 19 insertions(+), 718 deletions(-) rename CleanCode/src/{NuGet.Packager/Package.nuspec => CleanCode.nuspec} (68%) delete mode 100644 CleanCode/src/CleanCode/Resources/LocalizedStrings.cs delete mode 100644 CleanCode/src/NuGet.Packager/.gitignore delete mode 100644 CleanCode/src/NuGet.Packager/NuGet.Packager.csproj delete mode 100644 CleanCode/src/NuGet.Packager/NuGet.config delete mode 100644 CleanCode/src/NuGet.Packager/NuGet.exe delete mode 100644 CleanCode/src/NuGet.Packager/NuGetPackage.ps1 delete mode 100644 CleanCode/src/NuGet.Packager/NuGetSetup.ps1 delete mode 100644 CleanCode/src/NuGet.Packager/Properties/AssemblyInfo.cs delete mode 100644 CleanCode/src/NuGet.Packager/tools/init.ps1 delete mode 100644 CleanCode/src/NuGet.Packager/tools/install.ps1 delete mode 100644 CleanCode/src/NuGet.Packager/tools/uninstall.ps1 diff --git a/CleanCode/src/NuGet.Packager/Package.nuspec b/CleanCode/src/CleanCode.nuspec similarity index 68% rename from CleanCode/src/NuGet.Packager/Package.nuspec rename to CleanCode/src/CleanCode.nuspec index e115afd..1ef08cf 100644 --- a/CleanCode/src/NuGet.Packager/Package.nuspec +++ b/CleanCode/src/CleanCode.nuspec @@ -1,9 +1,9 @@  - CleanCode - 4.0.0.8 - CleanCode + CleanCode.CleanCode + 5.0.0 + Clean Code Hadi Hariri, Matt Ellis, SuperJMN Hadi Hariri, Matt Ellis https://raw.githubusercontent.com/hhariri/CleanCode/master/logo.png @@ -11,21 +11,26 @@ https://raw.github.com/hhariri/CleanCode/master/license.txt false Automates some of the concepts in Uncle Bob's Clean Code book - Major update, thanks to @SuperJMN! + +• Updated to ReSharper 2016.2 + +From 4.0.0: +• Warning if a method uses flag parameters • Warning if a method contains too many nested blocks • Warning if a method name is too short to be meaningful • Warning if an epression is breaking the Law of Demeter • Warning if a constructor has too many parameters, indicating too many dependencies • Warning if a method has too many arguments • Suggestion highlight if class has too many methods -• Suggestion highlight if method has too many statements - Copyright 2014 Hadi Hariri and Contributors +• Suggestion highlight if method has too many statements + + Copyright 2014-2016 Hadi Hariri and Contributors - + clean code - + diff --git a/CleanCode/src/CleanCode.sln b/CleanCode/src/CleanCode.sln index 42e9606..42b4822 100644 --- a/CleanCode/src/CleanCode.sln +++ b/CleanCode/src/CleanCode.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 12.0.40629.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanCode", "CleanCode\CleanCode.csproj", "{5F96119C-2646-4298-AD40-30209E7E7BB2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NuGet.Packager", "NuGet.Packager\NuGet.Packager.csproj", "{0451BAEF-DF2E-4B98-8644-94EE9415E389}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -17,9 +15,6 @@ Global {5F96119C-2646-4298-AD40-30209E7E7BB2}.Debug|Any CPU.Build.0 = Debug|Any CPU {5F96119C-2646-4298-AD40-30209E7E7BB2}.Release|Any CPU.ActiveCfg = Release|Any CPU {5F96119C-2646-4298-AD40-30209E7E7BB2}.Release|Any CPU.Build.0 = Release|Any CPU - {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0451BAEF-DF2E-4B98-8644-94EE9415E389}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index d941173..63e7875 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -233,7 +233,6 @@ True True - @@ -271,6 +270,9 @@ + + CleanCode.nuspec + diff --git a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs index e008104..36acfcd 100644 --- a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs +++ b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs @@ -31,15 +31,12 @@ [assembly: AssemblyCompany("Hadi Hariri")] [assembly: AssemblyProduct("ReSharper Clean Code Plugin")] [assembly: AssemblyDescription("Automates some of the concepts in Uncle Bob's Clean Code book")] -[assembly: AssemblyCopyright("Copyright ® 2014 Hadi Hariri and Contributors")] +[assembly: AssemblyCopyright("Copyright ® 2016 Hadi Hariri and Contributors")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] [assembly: Guid("97927FF9-8C9C-4DC5-A309-29C23F41DA47")] -[assembly: AssemblyVersion("4.0.0.*")] - -//[assembly: PluginTitle("Clean Code")] -//[assembly: PluginDescription("Automates some of the concepts in Uncle Bob's Clean Code book")] -//[assembly: PluginVendor("Hadi Hariri and Contributors")] +[assembly: AssemblyVersion("5.0.0.0")] +[assembly: AssemblyFileVersion("5.0.0.0")] diff --git a/CleanCode/src/CleanCode/Resources/LocalizedStrings.cs b/CleanCode/src/CleanCode/Resources/LocalizedStrings.cs deleted file mode 100644 index 6355e42..0000000 --- a/CleanCode/src/CleanCode/Resources/LocalizedStrings.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace CleanCode.Resources -{ - public class LocalizedStrings - { - - public LocalizedStrings() - { - Warnings = new Warnings(); - Settings = new Settings(); - } - public Warnings Warnings { get; set; } - public Settings Settings { get; set; } - } -} \ No newline at end of file diff --git a/CleanCode/src/NuGet.Packager/.gitignore b/CleanCode/src/NuGet.Packager/.gitignore deleted file mode 100644 index 2357e0d..0000000 --- a/CleanCode/src/NuGet.Packager/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.nupkg -lib/*.dll diff --git a/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj b/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj deleted file mode 100644 index 9351f37..0000000 --- a/CleanCode/src/NuGet.Packager/NuGet.Packager.csproj +++ /dev/null @@ -1,93 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {0451BAEF-DF2E-4B98-8644-94EE9415E389} - Library - Properties - NuGet.Packager - NuGet.Packager - v4.0 - - - 512 - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - AnyCPU - bin\Debug\ - - - AnyCPU - bin\Release\ - - - - - - - - - - - - - Designer - - - - - - - - - - - - - {5f96119c-2646-4298-ad40-30209e7e7bb2} - CleanCode - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CleanCode/src/NuGet.Packager/NuGet.config b/CleanCode/src/NuGet.Packager/NuGet.config deleted file mode 100644 index a7336c5..0000000 --- a/CleanCode/src/NuGet.Packager/NuGet.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/CleanCode/src/NuGet.Packager/NuGet.exe b/CleanCode/src/NuGet.Packager/NuGet.exe deleted file mode 100644 index c41a0d0debd870f8df2754f07a9f29c2d89a3d27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1662976 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§aghoAul?L0X>d$YAi*B*}Ui| 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≀u3%ll>HC17`Qjrp#2UXAU^9R4NKu~g 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%0Ac z*-+iF5H@OKjk&=a9d5SC2cXoQDuX2@@QtovgoTZMZvMW)&71l*bxsHSmWWZ~ZF@be z2{=YoYF|)ts}mC>TYo44CqOjf^Ou2tv@5nkWP>Y@RrIQjBGK}n_NtYIUsFdp*fJu3 zW^fjnaA4C}L0Ul7Z1XJD{K#fRHu4?Wn%DAwxQTDoyItVu7?0Kg1x&P%l>(ahp_U*; z*ut}DC1bF)5@hD&^(BE%|3wPDblu@lgLk^|P_qUw&?(*jDE(jhV?dji=~`x+@oV$r0^Z%dbbu zU0(@9AR=!7Zv-UrU=9+I$YP3+d2~gll0`vXpO!Ag{Nx|WbFj9OXG&*};O(iHdqlYySi18_}UkN|^{#4hAgO-HIoC*30ry`u1ovWLOh!B0!xOf_5H zY3P?7l=$*fsYhCRCA=VVaqsbqkFUeMiBVSPXttQ@(qx$@vwMFWcrFS6Vy3${PM_SN zvtleY6>da8hstmI&`!YZR)eyWt(;cc%({LA6{fdwkcYCMC|S%!-a%8fhnoxVB2OIk*NeD7>mX_ z!s)35qiYIILlvz`%Ji3%VwMB+t8=_}c#KXCfE+IeVSjs|J=l&RN&=GqB$7h?GA@E2 zsEd-(tJ5B-+pn>y(;wzPy7b`8*x2a{`ENF#eIxuB^Gmc=`lI~!C9aY9z0lh!|2b~X z;%&`+)8%WMeW0s*BRZ}<_t};F(nW2}0I|(e;kol?Q`9D~*}cm;8+ z&atJi3-)9pdCGe;1sk-J58q_%50k77#k;Bcg#=aJp2_*QXHsh;0GA+6$CTsc1|jXp z?ZLI!;-g>_fTElm9~{N~FUZnv;JELG=VrEo)u*|({!At@EgLF}+dFX}Wm$tn4an$s z@MI^-lmZ8~m%c&WR5JJ6TMxEhp4bUwP6D{45P|x5e!o*d2Kkt{v6ae+hTbTD$6m9@ z!*ATnF5*?<%*a~fgVn(xHz6mhte`E0eIG=vRB|=@)61_udTH15QTw^og}cahx%BvE zNE6A7XqV`?sUxqa*|1T#1yvA+} zON3YWpx%moZ9E#RLt%_x`|P+~4^FBiJGO)w*$8llODTLuH|v>&S3PtWhM(9}EV zbh#zoQY_Gv$u$v}lh_pwiT<%*4-k4mH)rtw@MiCsK~RV<*P1*%Jb7ASx&eF=hrtAZ z3ua`cPrX)H$6s60Zi&D?c@Od^w4y<#@dQXuN-f*VNj>YR25aGKH2+Fk;o`3jUZK2q z^U;gDpPYJP-_*{7QzuV&bCs!WPfbm1&^rCn)X~SLUU>m}P!6Bk{?tdOVF-PaV?UaB z_0rDMAH8qXgSTik(;hh*|KyvHG4VG1Ci*0rD2bxXdvZ4$jn)dPrc@Fr6m2VSL|G|4 zZB_B4hYK8FxDNhA$_TLoCQs1#c5uX$NRfq*w!(`Cxhj!^+_n$YU%DBj_b|yGwwg^# z4-V@077no_WHZvAA!<@iwySFyX#LxRfM5yP4^1f|;fHr}7sBQV-Umuv(Hy^SOgZTM zrhc^nI6qvP^L6dJE{wlp;Ro9jL>$UGgl%Dw43ZG!Ctk6gA?B{BO@}FSD{Yi-O>f+N zm96o@_Hv~B+EWv1NDfipvAu-ex7vqfiO+jzbcnJSEgz%a@>j-IAxf>fNIj?Cn)>O| zWrj(OJTIJKWsqr7(JeZLs}vR1Qj)>T5n+u} ztLXLU0~-X`^IiAfzhvIho8xQY%ig-2ETUEb%Eamc$d2Zim3tHlA6W%Z$}nHnf5i=F z+Ox2*bSX#)Kd`KD<%dqKJ1s2S_E)Di z?@X8hYDIh^njKwP)$9c(Uz<6-)$D)B9O{jMu+${weBJLSptx^LcX*=|UI1=a7HLg_R^kCH zcuS%fW8EV*Kc?-C()UXD%fcvj^k^YCMk+VXSduqt{po01f8Dw(8WchK4p0ePxSE~J zqB9S89GhJaBZEGQn<_Q zJ$N$Fp%Cepq@VYk_CbAuiZxWwNluk^eu6O3tT& zqhoHroNqszxsKL-8;G!@&}lBbdvPjaA^}xD>$HA+^l2p;ri~dvrM1uVfh0rdnzsA& z)kDYgSEsbUL+1ai~d`;N3VUnErbxGH+8ii5# z+-bbkV3;QXnc7Wy8edB|B;p0;T}#@>F_tstpqd>oN{=8sBrDwh^L5-ETA#m0xT9Ic z3Lh3k2p-xD3F02`jJx1+tChae=3^B0K_SJSHlCjxcHZ_IW>$=8*5@k}DMv%)v;~_9 zFSznMf$|IE6;uFdN^$b3rJX@6BQYO&m6(Z<6D~aFtX(f<*o6u<%e}+v2eQ-4gHw_6 zY$ME=!)kUkTWS`crr{=|(F(XrB{E$R?TP+LIk|5-5DX83N3+nv}XPQZ1i=aJyKbO5LN)YOyDk^T{LhEsCzBj4Ka z9Kgt`KX`hNQEU7>4NYUmWP>s8m33!8aaY2qqTYEPaJP?YJRE$bAsJCOt0A}Vupw8* ztP;?9u{Ro;tZ5Fz`pCDJ3p0+r^fmW0y~F!0E? zf&B3Y4yVVp(9~LJ=9Y$CLdyl)4ev+A1U2w<5NGH%Ou_fw1j86)jLJ)zV~dxo>zZAX zuQvvW7h%E4(TjW=EWWU~-8P78I~2H?2Tabz#w@ICGRt9Q%RkO9)JWH9Xd=t%9bfo` z3xeOd=WChxy~n4v!+i0kxLL>dU)Zqs!uZP<#%V{oxiXKX2f0O8Yano49I;F1OH^DK zR1jF~wO(+aqsJ`BKko9!M>mSp_1bg0=S?5qd~;XL%`@@ayl+!ZaI?6|R4H(5BB|fx zZ#QDz9wfO)S%mB-9feW1)*W$+S6SRdPWU`%UTtksI?sl9DCxZ3rZZpA%OXmO&i$~u zur7%S*{ZaQ;;37Nfc$ym^)jzMu0NPb(^9Qg?&Vm>U#UVv9nQWCp?r<$GIQF+%P0<3 za$3rjO@zpZjUHpH&~s)d!je9{M)Z|q&HM7 z1{!py#UZrLI1_#f5i!}mAu>3M8^AUUV44_MAlA#W4zc918WwB?$_c^?R*IJA)G7}G zLQ&kIpCfurZTJk?$dvo(qH5OISL1?#2bqd9jA3iq!;AC3BcDVsokuY17cN;0dxDjw z*?uY>6wdMe#h@;(Q#elw;N2rrXEp{Dy8{U3jQ4ShU2*CNO5hdwy#amT2_YNqDZur1 z(52%q!y9?!$#*nI2DD%|=s9ov%?cRh4K$`U#IKT$%PzCu>9*06k(Pg8I zAXuXQKx2fVEFeS_q_?uzSRvRdP{L+hlF&$IVA=7`V^oq6 zZi?$nvO954q%bBk$Q8Ihbty<9y_yYniBNWiFgwL|=P9DL#c?_b6xyEc!Z_7nWCXf6 za@qX_xm-je$FOFBE6y;(da7&V`-Qp!XN)NB3P6bPsfuc_DA?@-ePAgp1wq@yK8-Eg zf_lR%>Z^ItjC%`JqttJW4#8-Ac9UA4bi_=V`?z`>fzShrZV=9t5GwTy86jYLd-LkG za#&fq`I;NoIoes>Vs64#I|jOkx#V!KCIG*|%V~v&XJx=4E-n+uX>8X76{td+Yq3o^O6X$&nZkOW!9qZ!81<`?5 zFbJe?aL1PwVA(ex9ERR>P4IqJ7hXVzee4m4Y=oaQ(!Uy_=S0w=7UZh7e3d zY4x=^IuFQjXaT)_(*pDS)REc8EW}qhGRJY>w4fX&;ph|?;Xpvss(WZH%Wm#`>L2~+ zM=`{~fqY7s^mz+X=pqFo!jlmlvr$z|0nq!?Oy!>}$g#B^7YJh!D`2dM`ToX&7!Zhv zD4!o%XLSSv{IP@upT8iw`3VHe*mo4%dpkB_!*5$4lv78=>-nRc65Vw<>zvXJA^v6N zFM8VH0g{`|DJ8V{=kDWG)7Y;Spe13wQPKAYmp|As^{YMM`?SUsx%)>~#y93a`Kr?Q zpSySYAdR2$(wVrRS+1qtJ#-5+t(RgqI&<#AsPdg&~g9Nk4=j}QK75H-kILD zy#N~h9H7zBwWMs~%TEvahv^yY5fq+D_xO$TPg?{!wkh-WLldCd67o5e{Zhtex51?O z?bypS?itW_WF0G`lc&W+Q_cS5673V|_yrns-&W6;SJI2}*QeKVV$amSbmtl zG=Gme=IamF`sm_yhU~fCp#h8(TI#QhERq7$7!vW(suC}*Y}%7ra-Eg1hA?)oIF%F{gk`n{B=UQ{>K#3E`OSTo-hAQW?o*deKSSFh zC@e@@Upjo)n~A2)056eN`K`Va{M3tw_6W-S!Ru4oo(~^xeB`tESfAe~3^s<1m8 zzbA^jf%;fuh^+rEZhojKX#NOo8$d4C`dCiGYuGjfbpw@8zI&?K!Ur8gr@9rTVeg)5v|7}|m5o(6W17U}# zNjXwC6*NAQ_LHZ7R}N3U47iLWgWZtEq6~W&GAMAX?P22ED@hKEUxtxsRYewhpkduV zJy2TMfok_{Fk5XnU@~H)P`W}7s(az@0i_SZZE7qvP#4>a{hp*bt8(Px?sZd}Uo`f& zjtZLb_boA?OhLdtEB6b19RL5U0MSYts7)t{Uvdb)DddZRCwzctB&*PU13ye=clwF_ z*EUgGb80&uEK%_G>nbdmK2V?=fg5fs2P&%@*+n}V70lSu55_G`3d*og;u+zQ2h_t; zYpQpcKgI@W=c(EoEfG3N+Ui1-u5FE}C(XH2$b()=7{czSnD)nM*M}(wTjw**beC2I zCuuQ|_;;d^0ljQQpA=U$dy10mnS!9i;E4#30t>tS)Q3;1JEvoRPGi7qh2(lKp8+6JcrCu1VAjMH8u--I%h4 zhUiG_3Av$E%~VpY2IFZcCqszV68r009V(8(v{HYN?uoZA!cI6_HCkJNZ+42hs2G-ynzx<@7_Bbf-*N+d!CF+~iK z91WEqL`*?Y60WH&=|#0sS~8GmtAy6n@B3M6?S1x1Qup@$zTemHpWe@BY0f!&uf6u( zYdz~3-p~7?!q&jVAi7JqVhs@b5I~+d52U&P$Ah#TdJbg;&;Ui^wj+^(>|S1;5u>&X8!#<3%l|6Np>W9TgKLP0N zrAG~^d11kXg`4FCe3dF$Uw*QL2dAoyhygde>5|2a8?535bPNoXg-na+CN%z41gEdD}PVSI{po~dA&`zN(1){Ju z7}03o^F)nTHYKo7q5LXSVk$Ovw#H~WVTTJrCX5fn60$omWayiGj`1+NTK8nT9xzX$ zTkx9E(W=E6U89sWQho^9gtF6zsmu@KCJ{s=%aI$$Dmqll5<&{UFnN$#K{K*?sYX+7 zva(N)lyYdP0 z1dSFu3pQE7K3?)c91W^<`Hj$2LUD#L$XD=p-?t$JvzBkfP%a`G^MUkJl7@?P_c#d&Cc$?@g^u0okf_sv05(KHr zrF2Lx;k=ww{#N!20aq`JQ|OM6+wwiJ?zB=ovPNJhxaU>=na~{Yr)47#P*H&a?R>rKaS-PM`Hi&YliEx(PR_hrfwct_| zz6QZoowBqt?m$KSvWj>J;6O!1lPe&Ab9$b>FovpmBauT*bf|JVkU}Io9SEPQK8aP{ zVT6a620^pHWr*Iw7?~oR465mhDQYZxfVo1inMq{4RskxNC#x<<*`^tv1#_|SNeaW! zc%roJzbJCRawV1lLdrN=2t0~!Ag=%1rGXz!^i74Ng|aS`o;277;0EEF0mL-WR7iKg zE}uTiE`LzO9D! zV{|IO)wj6(GgeMmE8F&JKq0sM2}@YPiQ&^?bcYls z4*+UKBQf0#6Iu04SUm%h;aoMLBz|E1pc1jPBbe!9E^Wc2lu6UsA0`zxXr^6`0n)FU zaZMgM)7gyl?Xh8S%3%KosTHhgt|Blan^R6Q&4306c5|&%BB3A?Uv*5DQx-8dGbz`Z z>3#!{x4zAH3pPbk5r`UIVh@35nyjvLCJLop+6bSR0{jsy-J ziU_K}Qdh)^5$AIpwz^YJrj9krsoOYxhqS4@dcFCG!X7nh$H>De}Gmr5yR=QGYTzLP?OoWccOBXUdt!7|~N_v7N zB1_{7i2^%97#-Mch@SJ5K~do_&GC`VL7ahb2=TQeTEYvQ;3wcjVdE*sBP|J5^&B{a zp(?^!pm88aqHxoH9vHYVAt^B?^h&i?SO*y1te{}UCY2|sR*J35IMvmPA@Y|{etZ_B zE!ot_306w2KyV-(j#XY{>#$}Z4kYd{jG>DPJ(VHnNpO4WptvLb7z@@P&z3|v*F*7_ zFk9i21fM7JB($J+hwu;dhSvllL0sN=ZLZR)!hhnb6e%Ltml!^J<}@`{)n+h?ErfX^ z4V>f<90y+TEnqW=tczT4n0a182Eo-OD|t-sMJ*W|PeOsIhq4x0OT3Y%fuoMi7Wv*7 zj}*qE)}t9e2$WXA7s!*xNjSknq3FRv<8~qim`Sc+JV&HMldJxf0|~(P5G-F7N6WN3 z)gFcFZmGQZ?-HJYT7#y0hEPUjN;oD!J_rLESbaq_DoziK55igQTu2)6UJ-7?>nCnj zm8{2u=ikw3G!ukm_5u@6jia?l!$(FqiqWue1igSiyRvLfP`w+uBO*FPkN|T-9-u6r zjd!M%Zb`^HC#R9(>6BkT)A4QTt-}5^K6k}90Foaa!($VQP!8Xq#H}MDBKTvCrU#;( zUN|8*h{)vh?4{zSYaWPI;2%ovb<7Abf2dw~?H5MSE0EIojfw5m?p7<^B@8|mpB33w@^7pCWw&|h597RN9 z9?u({N}qf|$K zDEmnUyueJ)WrAIJRk-gF`xb`61Sw8u+X!U=tB*m&5gmNT^jmPj7PgJ3q#1_7;4`=p zW)w3Mf^}h}6i^MG`9svYF7CLl!V-WCN<`m~l25Tc_$^iD?WF_YzfVLwPKoo;F-X6x zZa4pDgbO+{^gQ2Q&ZC*WP;ZN)#a5|x+@XozGC5v+$VpzQsFEl zMN(N_;}OgU;OPbCH()xH^TfBB2-2QlzR{v%PFi*(^Zp_VCR<+oC&We7E(Gu-IQU`n z4AuF;Z$Pmcer0(`(0!_{5QId)iA|JqaFH`r4Eq;5OkBXUd#Sg(J?)`nC=LbDsSNRx zHCbkA4P_WOIs_=de(v^alc?5{xG6)Y$sk9qyFE8SYCoQt5$t$@b;MN^rJbF^HSOwm zOQ)zXk9O|%u3Svjb{Ss9h)ywrAK&J;&-B6C&QaaJ41@g3PYk0{)Rg~l4FQV$%a_1y zDBE1Em*5PHbnh}+5~rxdJm_la<%2J-wnr?8bMaCXR~|cF=0vGB2kA0FbFdB$5Ny=R z-QHxyA7H1->#w%Uk^2Lun9%F?b+?xnR;@QkE&;l(35s&|B&2D=H515EC@C+S2R3}D z$N~9l-~=OX5^P))2!S^mA1KreiBIK5J(cswhl0L5SqJ3A;LFyBfOf$s7aMrz#Ae`} z%8qV8m34)Wk#$$Pd~wO1!@NQo>rctnHnOy_!k~0CcU$nz#5GEetRZ&+L5!6%rNENt zT)N(Y&u~43>w{fSK3IVe!?G6)Z0gIvz$e-dejj%?>?1q>$WGoZyO{cX=@U1qhyhF8 z2sfsOL?#6+bQYHR4;*V6oW2FsMz`>z8Lto3;nj$`8`XQpqeX~I!HcF#2stqJ`B1?C zf(N34G%JA^1QZoZRYj(TS4^yDe#9Qa9upWWQP>ntC2j|Eo1Fe-)^2T`lfBIz*IQ#z zVADUy2ci^K4Ih+NS}BbV(*;B7l6|8fs4>4qsD`E%>?=7VSZyN0kuR#2VG6=l#*H|z>Jg_ihBP035i;3K)7SA0du9dMIzCKdDI6JyDrPXq5xQn)z<)s#2?aV7@(}hk zcpzOVI;I0nqj*ldqP90YyNLL5Q&CQ9$Fqa$L0o{}i4AWs=T6oSqB2 zHZ4OQ>cQjSwbF=gOuZUK@i4|#My_H}2o)XBL$p=8A+wToP5t4z)fQ!z;3Jd+>L^~S z=Iay`WT@Chk3`91=ZjArMxu+>Fy<5%v1rArzT=>Z4rBJx@nDVC-#2Uq}mpULJ+j`Qwxkg}O6 z$C+%JblhME&ihGsz=ctmE!*P)3pe?mK2BQ|#~2)=IbU#0wP8vB0O_V`v$5s75&3M% zb&3I~cPfDm;8dA!yNEfe+8KzWUdU^rnV|7Qi{Y_Wgrcn2(}AR=k;(@O!Op|_2r#Oi zARNRVAjqa}=<$KAksSrUq%D0X1RtDLsmocodq*u|k{*x^9W9HX^}8x^)>dpImLy^> zrm<8S18n?RvH{{zk~BbpcY+7KV%5*noz4%0DrL)V%eZ8Le!)%3tCGfmdsQCB3>>Xm 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

?KYszH*fnDu=4;_B$|9I%@XZ_8?y@!r_ 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 liI`dCHeT!%<7;}X+9xBJ*iwwM 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
  1. Eoy%{Iz*Kx9b1E=UMI90!iDY|Iq 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 EFFYo8OaK4? diff --git a/CleanCode/src/NuGet.Packager/NuGetPackage.ps1 b/CleanCode/src/NuGet.Packager/NuGetPackage.ps1 deleted file mode 100644 index fbcff49..0000000 --- a/CleanCode/src/NuGet.Packager/NuGetPackage.ps1 +++ /dev/null @@ -1,313 +0,0 @@ -Param ( - [switch]$Publish -) - -$ErrorActionPreference = "Stop" -$global:ExitCode = 1 - -function Write-Log { - - #region Parameters - - [cmdletbinding()] - Param( - [Parameter(ValueFromPipeline=$true)] - [array] $Messages, - - [Parameter()] [ValidateSet("Error", "Warn", "Info")] - [string] $Level = "Info", - - [Parameter()] - [Switch] $NoConsoleOut = $false, - - [Parameter()] - [String] $ForegroundColor = 'White', - - [Parameter()] [ValidateRange(1,30)] - [Int16] $Indent = 0, - - [Parameter()] - [IO.FileInfo] $Path = ".\NuGet.log", - - [Parameter()] - [Switch] $Clobber, - - [Parameter()] - [String] $EventLogName, - - [Parameter()] - [String] $EventSource, - - [Parameter()] - [Int32] $EventID = 1 - - ) - - #endregion - - Begin {} - - Process { - - $ErrorActionPreference = "Continue" - - if ($Messages.Length -gt 0) { - try { - foreach($m in $Messages) { - if ($NoConsoleOut -eq $false) { - switch ($Level) { - 'Error' { - Write-Error $m -ErrorAction SilentlyContinue - Write-Host ('{0}{1}' -f (" " * $Indent), $m) -ForegroundColor Red - } - 'Warn' { - Write-Warning $m - } - 'Info' { - Write-Host ('{0}{1}' -f (" " * $Indent), $m) -ForegroundColor $ForegroundColor - } - } - } - - if ($m.Trim().Length -gt 0) { - $msg = '{0}{1} [{2}] : {3}' -f (" " * $Indent), (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $Level.ToUpper(), $m - - if ($Clobber) { - $msg | Out-File -FilePath $Path -Force - } else { - $msg | Out-File -FilePath $Path -Append - } - } - - if ($EventLogName) { - - if (-not $EventSource) { - $EventSource = ([IO.FileInfo] $MyInvocation.ScriptName).Name - } - - if(-not [Diagnostics.EventLog]::SourceExists($EventSource)) { - [Diagnostics.EventLog]::CreateEventSource($EventSource, $EventLogName) - } - - $log = New-Object System.Diagnostics.EventLog - $log.set_log($EventLogName) - $log.set_source($EventSource) - - switch ($Level) { - "Error" { $log.WriteEntry($Message, 'Error', $EventID) } - "Warn" { $log.WriteEntry($Message, 'Warning', $EventID) } - "Info" { $log.WriteEntry($Message, 'Information', $EventID) } - } - } - } - } - catch { - throw "Failed to create log entry in: '$Path'. The error was: '$_'." - } - } - } - - End {} - - <# - .SYNOPSIS - Writes logging information to screen and log file simultaneously. - - .DESCRIPTION - Writes logging information to screen and log file simultaneously. Supports multiple log levels. - - .PARAMETER Messages - The messages to be logged. - - .PARAMETER Level - The type of message to be logged. - - .PARAMETER NoConsoleOut - Specifies to not display the message to the console. - - .PARAMETER ConsoleForeground - Specifies what color the text should be be displayed on the console. Ignored when switch 'NoConsoleOut' is specified. - - .PARAMETER Indent - The number of spaces to indent the line in the log file. - - .PARAMETER Path - The log file path. - - .PARAMETER Clobber - Existing log file is deleted when this is specified. - - .PARAMETER EventLogName - The name of the system event log, e.g. 'Application'. - - .PARAMETER EventSource - The name to appear as the source attribute for the system event log entry. This is ignored unless 'EventLogName' is specified. - - .PARAMETER EventID - The ID to appear as the event ID attribute for the system event log entry. This is ignored unless 'EventLogName' is specified. - - .EXAMPLE - PS C:\> Write-Log -Message "It's all good!" -Path C:\MyLog.log -Clobber -EventLogName 'Application' - - .EXAMPLE - PS C:\> Write-Log -Message "Oops, not so good!" -Level Error -EventID 3 -Indent 2 -EventLogName 'Application' -EventSource "My Script" - - .INPUTS - System.String - - .OUTPUTS - No output. - - .NOTES - Revision History: - 2011-03-10 : Andy Arismendi - Created. - #> -} - -function Create-Process() { - param([string] $fileName, [string] $arguments) - - $pinfo = New-Object System.Diagnostics.ProcessStartInfo - $pinfo.RedirectStandardError = $true - $pinfo.RedirectStandardOutput = $true - $pinfo.UseShellExecute = $false - $pinfo.FileName = $fileName - $pinfo.Arguments = $arguments - - $p = New-Object System.Diagnostics.Process - $p.StartInfo = $pinfo - - return $p -} - -function HandlePublishError { - param([string] $ErrorMessage) - - # Run NuGet Setup - $encodedMessage = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($ErrorMessage)) - $setupTask = Start-Process PowerShell.exe "-ExecutionPolicy Unrestricted -File .\NuGetSetup.ps1 -Url $url -Base64EncodedMessage $encodedMessage" -Wait -PassThru - - #Write-Log ("NuGet Setup Task Exit Code: " + $setupTask.ExitCode) - - if ($setupTask.ExitCode -eq 0) { - # Try to push package again - $publishTask = Create-Process .\NuGet.exe ("push " + $_.Name + " -Source " + $url) - $publishTask.Start() | Out-Null - $publishTask.WaitForExit() - - $output = ($publishTask.StandardOutput.ReadToEnd() -Split '[\r\n]') |? {$_} - $error = (($publishTask.StandardError.ReadToEnd() -Split '[\r\n]') |? {$_}) - Write-Log $output - Write-Log $error Error - - if ($publishTask.ExitCode -eq 0) { - $global:ExitCode = 0 - } - } - elseif ($setupTask.ExitCode -eq 2) { - $global:ExitCode = 2 - } - else { - $global:ExitCode = 0 - } -} - -function Publish { - - Write-Log " " - Write-Log "Publishing package..." -ForegroundColor Green - - # Get nuget config - [xml]$nugetConfig = Get-Content .\NuGet.Config - - $nugetConfig.configuration.packageSources.add | ForEach-Object { - $url = $_.value - - Write-Log "Repository Url: $url" - Write-Log " " - - Get-ChildItem *.nupkg | Where-Object { $_.Name.EndsWith(".symbols.nupkg") -eq $false } | ForEach-Object { - - # Try to push package - $task = Create-Process .\NuGet.exe ("push " + $_.Name + " -Source " + $url) - $task.Start() | Out-Null - $task.WaitForExit() - - $output = ($task.StandardOutput.ReadToEnd() -Split '[\r\n]') |? { $_ } - $error = ($task.StandardError.ReadToEnd() -Split '[\r\n]') |? { $_ } - Write-Log $output - Write-Log $error Error - - if ($task.ExitCode -gt 0) { - HandlePublishError -ErrorMessage $error - #Write-Log ("HandlePublishError() Exit Code: " + $global:ExitCode) - } - else { - $global:ExitCode = 0 - } - } - } -} - -Write-Log " " -Write-Log "NuGet Packager 2.0.3" -ForegroundColor Yellow - -# Make sure the nuget executable is writable -Set-ItemProperty NuGet.exe -Name IsReadOnly -Value $false - -# Make sure the nupkg files are writeable and create backup -if (Test-Path *.nupkg) { - Set-ItemProperty *.nupkg -Name IsReadOnly -Value $false - - Write-Log " " - Write-Log "Creating backup..." -ForegroundColor Green - - Get-ChildItem *.nupkg | ForEach-Object { - Move-Item $_.Name ($_.Name + ".bak") -Force - Write-Log ("Renamed " + $_.Name + " to " + $_.Name + ".bak") - } -} - -Write-Log " " -Write-Log "Updating NuGet..." -ForegroundColor Green -Write-Log (Invoke-Command {.\NuGet.exe update -Self} -ErrorAction Stop) - -Write-Log " " -Write-Log "Creating package..." -ForegroundColor Green - -# Create symbols package if any .pdb files are located in the lib folder -If ((Get-ChildItem *.pdb -Path .\lib -Recurse).Count -gt 0) { - $packageTask = Create-Process .\NuGet.exe ("pack Package.nuspec -Symbol -Verbosity Detailed") - $packageTask.Start() | Out-Null - $packageTask.WaitForExit() - - $output = ($packageTask.StandardOutput.ReadToEnd() -Split '[\r\n]') |? {$_} - $error = (($packageTask.StandardError.ReadToEnd() -Split '[\r\n]') |? {$_}) - Write-Log $output - Write-Log $error Error - - $global:ExitCode = $packageTask.ExitCode -} -Else { - $packageTask = Create-Process .\NuGet.exe ("pack Package.nuspec -Verbosity Detailed") - $packageTask.Start() | Out-Null - $packageTask.WaitForExit() - - $output = ($packageTask.StandardOutput.ReadToEnd() -Split '[\r\n]') |? {$_} - $error = (($packageTask.StandardError.ReadToEnd() -Split '[\r\n]') |? {$_}) - Write-Log $output - Write-Log $error Error - - $global:ExitCode = $packageTask.ExitCode -} - -# Check if package should be published -if ($Publish -and $global:ExitCode -eq 0) { - Publish -} - -Write-Log " " -Write-Log "Exit Code: $global:ExitCode" -ForegroundColor Gray - -$host.SetShouldExit($global:ExitCode) -Exit $global:ExitCode \ No newline at end of file diff --git a/CleanCode/src/NuGet.Packager/NuGetSetup.ps1 b/CleanCode/src/NuGet.Packager/NuGetSetup.ps1 deleted file mode 100644 index bd9aa5e..0000000 --- a/CleanCode/src/NuGet.Packager/NuGetSetup.ps1 +++ /dev/null @@ -1,208 +0,0 @@ -Param ( - [string]$Url, - [string]$Base64EncodedMessage -) - -$ErrorActionPreference = "Stop" -$ExitCode = 1 - -function Write-Log { - - #region Parameters - - [cmdletbinding()] - Param( - [Parameter(ValueFromPipeline=$true)] - [array] $Messages, - - [Parameter()] [ValidateSet("Error", "Warn", "Info")] - [string] $Level = "Info", - - [Parameter()] - [Switch] $NoConsoleOut = $false, - - [Parameter()] - [String] $ForegroundColor = 'White', - - [Parameter()] [ValidateRange(1,30)] - [Int16] $Indent = 0, - - [Parameter()] - [IO.FileInfo] $Path = ".\NuGet.log", - - [Parameter()] - [Switch] $Clobber, - - [Parameter()] - [String] $EventLogName, - - [Parameter()] - [String] $EventSource, - - [Parameter()] - [Int32] $EventID = 1 - - ) - - #endregion - - Begin {} - - Process { - - $ErrorActionPreference = "Continue" - - if ($Messages.Length -gt 0) { - try { - foreach($m in $Messages) { - if ($NoConsoleOut -eq $false) { - switch ($Level) { - 'Error' { - Write-Error $m -ErrorAction SilentlyContinue - Write-Host ('{0}{1}' -f (" " * $Indent), $m) -ForegroundColor Red - } - 'Warn' { - Write-Warning $m - } - 'Info' { - Write-Host ('{0}{1}' -f (" " * $Indent), $m) -ForegroundColor $ForegroundColor - } - } - } - - if ($m.Trim().Length -gt 0) { - $msg = '{0}{1} [{2}] : {3}' -f (" " * $Indent), (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $Level.ToUpper(), $m - - if ($Clobber) { - $msg | Out-File -FilePath $Path -Force - } else { - $msg | Out-File -FilePath $Path -Append - } - } - - if ($EventLogName) { - - if (-not $EventSource) { - $EventSource = ([IO.FileInfo] $MyInvocation.ScriptName).Name - } - - if(-not [Diagnostics.EventLog]::SourceExists($EventSource)) { - [Diagnostics.EventLog]::CreateEventSource($EventSource, $EventLogName) - } - - $log = New-Object System.Diagnostics.EventLog - $log.set_log($EventLogName) - $log.set_source($EventSource) - - switch ($Level) { - "Error" { $log.WriteEntry($Message, 'Error', $EventID) } - "Warn" { $log.WriteEntry($Message, 'Warning', $EventID) } - "Info" { $log.WriteEntry($Message, 'Information', $EventID) } - } - } - } - } - catch { - throw "Failed to create log entry in: '$Path'. The error was: '$_'." - } - } - } - - End {} - - <# - .SYNOPSIS - Writes logging information to screen and log file simultaneously. - - .DESCRIPTION - Writes logging information to screen and log file simultaneously. Supports multiple log levels. - - .PARAMETER Messages - The messages to be logged. - - .PARAMETER Level - The type of message to be logged. - - .PARAMETER NoConsoleOut - Specifies to not display the message to the console. - - .PARAMETER ConsoleForeground - Specifies what color the text should be be displayed on the console. Ignored when switch 'NoConsoleOut' is specified. - - .PARAMETER Indent - The number of spaces to indent the line in the log file. - - .PARAMETER Path - The log file path. - - .PARAMETER Clobber - Existing log file is deleted when this is specified. - - .PARAMETER EventLogName - The name of the system event log, e.g. 'Application'. - - .PARAMETER EventSource - The name to appear as the source attribute for the system event log entry. This is ignored unless 'EventLogName' is specified. - - .PARAMETER EventID - The ID to appear as the event ID attribute for the system event log entry. This is ignored unless 'EventLogName' is specified. - - .EXAMPLE - PS C:\> Write-Log -Message "It's all good!" -Path C:\MyLog.log -Clobber -EventLogName 'Application' - - .EXAMPLE - PS C:\> Write-Log -Message "Oops, not so good!" -Level Error -EventID 3 -Indent 2 -EventLogName 'Application' -EventSource "My Script" - - .INPUTS - System.String - - .OUTPUTS - No output. - - .NOTES - Revision History: - 2011-03-10 : Andy Arismendi - Created. - #> -} - -$choices = [System.Management.Automation.Host.ChoiceDescription[]]( - (New-Object System.Management.Automation.Host.ChoiceDescription "&Add API Key","Add an API Key for this URL"), - (New-Object System.Management.Automation.Host.ChoiceDescription "&Skip","Skip pushing to this URL")) - - Write-Output "" - Write-Log "Invalid API key for this repository URL, or there is a version conflict" Warn - - If ($Base64EncodedMessage) { - Write-Warning ([System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Base64EncodedMessage))) - } - - $firstAnswer = $Host.UI.PromptForChoice(("Would you like to try adding an API key for " + $Url + "?"), "", $choices, (1)) - - if ($firstAnswer -eq 0) { - $fields = new-object "System.Collections.ObjectModel.Collection``1[[System.Management.Automation.Host.FieldDescription]]" - - $f = New-Object System.Management.Automation.Host.FieldDescription "API Key for $Url" - $f.SetParameterType( [System.Security.SecureString] ) - $f.HelpMessage = "Please enter API Key for $Url" - $f.Label = "&API Key for $Url" - - $fields.Add($f) - - $results = $Host.UI.Prompt( "Add API Key", "", $fields ) - - $pass = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($results["API Key for $Url"])) - - # Add API Key to config file - Write-Log (.\NuGet.exe setApiKey $pass -Source $Url) - - if ($LASTEXITCODE -le 0) { - $ExitCode = 0 - } - } - else { - Write-Log "Skipping..." - $ExitCode = 2 - } - -$host.SetShouldExit($ExitCode) -Exit $ExitCode \ No newline at end of file diff --git a/CleanCode/src/NuGet.Packager/Properties/AssemblyInfo.cs b/CleanCode/src/NuGet.Packager/Properties/AssemblyInfo.cs deleted file mode 100644 index cb3fd4b..0000000 --- a/CleanCode/src/NuGet.Packager/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("NuGet.Packager")] -[assembly: AssemblyDescription("Project template made by EyeCatch (http://www.eyecatch.no/)")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("NuGet.Packager")] -[assembly: AssemblyCopyright("Copyright © 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("5b586874-8d3e-4137-9ba8-e982413416d5")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CleanCode/src/NuGet.Packager/tools/init.ps1 b/CleanCode/src/NuGet.Packager/tools/init.ps1 deleted file mode 100644 index a686abf..0000000 --- a/CleanCode/src/NuGet.Packager/tools/init.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -# Runs the first time a package is installed in a solution, and every time the solution is opened. - -param($installPath, $toolsPath, $package, $project) - -# $installPath is the path to the folder where the package is installed. -# $toolsPath is the path to the tools directory in the folder where the package is installed. -# $package is a reference to the package object. -# $project is null in init.ps1 diff --git a/CleanCode/src/NuGet.Packager/tools/install.ps1 b/CleanCode/src/NuGet.Packager/tools/install.ps1 deleted file mode 100644 index c175998..0000000 --- a/CleanCode/src/NuGet.Packager/tools/install.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -# Runs every time a package is installed in a project - -param($installPath, $toolsPath, $package, $project) - -# $installPath is the path to the folder where the package is installed. -# $toolsPath is the path to the tools directory in the folder where the package is installed. -# $package is a reference to the package object. -# $project is a reference to the project the package was installed to. diff --git a/CleanCode/src/NuGet.Packager/tools/uninstall.ps1 b/CleanCode/src/NuGet.Packager/tools/uninstall.ps1 deleted file mode 100644 index 0ed95e5..0000000 --- a/CleanCode/src/NuGet.Packager/tools/uninstall.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -# Runs every time a package is uninstalled - -param($installPath, $toolsPath, $package, $project) - -# $installPath is the path to the folder where the package is installed. -# $toolsPath is the path to the tools directory in the folder where the package is installed. -# $package is a reference to the package object. -# $project is a reference to the project the package was installed to. From 64a9b4c5a7c5bb72e1627e4d6661c3206e7ca816 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Fri, 2 Sep 2016 17:38:28 +0100 Subject: [PATCH 24/50] Removed unnecessary license comment --- CleanCode/src/CleanCode/CleanCode.csproj | 1 - .../ChainedReferences/Highlighting.cs | 27 ----------------- .../InvalidateOnMaximumChainedCalls.cs | 27 ----------------- .../ChainedReferences/TypeEqualityComparer.cs | 18 ----------- .../Features/ClassTooBig/Highlighting.cs | 27 ----------------- .../InvalidateOnMaximumMethodsPerClass.cs | 27 ----------------- .../ComplexExpression/Highlighting.cs | 27 ----------------- .../InvalidateOnComplexExpressionChange.cs | 27 ----------------- .../ExcessiveIndentation/Highlighting.cs | 30 ------------------- .../Features/FlagArguments/Highlighting.cs | 27 ----------------- .../Features/HollowNames/Highlighting.cs | 27 ----------------- .../InvalidateOnHollowTypeNameStringChange.cs | 27 ----------------- .../MethodNameNotMeaningful/Highlighting.cs | 30 ------------------- ...validateOnMinimumMethodNameLenghtChange.cs | 27 ----------------- .../Features/MethodTooLong/Highlighting.cs | 27 ----------------- .../InvalidateOnMaximumLinesChange.cs | 27 ----------------- .../TooManyDeclarations/Highlighting.cs | 27 ----------------- .../InvalidateOnMaximumDeclarationsChange.cs | 27 ----------------- .../TooManyDependencies/Highlighting.cs | 27 ----------------- .../InvalidateOnMaximumDependenciesChange.cs | 27 ----------------- .../TooManyMethodArguments/Highlighting.cs | 27 ----------------- ...nvalidateOnMaximumMethodArgumentsChange.cs | 27 ----------------- 22 files changed, 565 deletions(-) delete mode 100644 CleanCode/src/CleanCode/Features/ChainedReferences/TypeEqualityComparer.cs diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index 63e7875..58e85c4 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -202,7 +202,6 @@ - diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs index c39aaf1..99ac8a6 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Features.ChainedReferences; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs index daf2c28..e51c21e 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Settings; using JetBrains.Application.Settings; using JetBrains.DataFlow; diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/TypeEqualityComparer.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/TypeEqualityComparer.cs deleted file mode 100644 index 54a0093..0000000 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/TypeEqualityComparer.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; -using JetBrains.ReSharper.Psi; - -namespace CleanCode.Features.ChainedReferences -{ - internal class TypeEqualityComparer : IEqualityComparer - { - public bool Equals(IType x, IType y) - { - return x.ToString().Equals(y.ToString()); - } - - public int GetHashCode(IType obj) - { - return obj.ToString().GetHashCode(); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs index afbda4c..d79c2bf 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Features.ClassTooBig; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs index d1d661a..8f4790c 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Settings; using JetBrains.Application.Settings; using JetBrains.DataFlow; diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs index f01225e..70e6772 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Features.ComplexExpression; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs index fcf836e..3f26c49 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Settings; using JetBrains.Application.Settings; using JetBrains.DataFlow; diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs index 02f92cb..04ddc71 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Features.ExcessiveIndentation; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; @@ -36,9 +9,6 @@ namespace CleanCode.Features.ExcessiveIndentation { - /// - /// The highlighting that warns about high complexity - /// [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] public class Highlighting : IHighlighting { diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs b/CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs index d88187c..1ecd3df 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Features.FlagArguments; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; diff --git a/CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs b/CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs index 8a12aa8..a4762c4 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Features.HollowNames; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; diff --git a/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs b/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs index 3778288..2068239 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Settings; using JetBrains.Application.Settings; using JetBrains.DataFlow; diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs index f6b1793..0c12352 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Features.MethodNameNotMeaningful; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; @@ -37,9 +10,6 @@ namespace CleanCode.Features.MethodNameNotMeaningful { - /// - /// The highlighting that warns about high complexity - /// [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] public class Highlighting : IHighlighting { diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs index 4f4ff0e..21db1c2 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Settings; using JetBrains.Application.Settings; using JetBrains.DataFlow; diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs index 96778e2..2d6d95e 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Features.MethodTooLong; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs index acffdb8..c8fcb17 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Settings; using JetBrains.Application.Settings; using JetBrains.DataFlow; diff --git a/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs b/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs index d0dddfa..293ba95 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Features.TooManyDeclarations; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; diff --git a/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs b/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs index b5e1825..f17d78e 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Settings; using JetBrains.Application.Settings; using JetBrains.DataFlow; diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs index 6ac6963..e631393 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Features.TooManyDependencies; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs index d1337af..a7629d2 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Settings; using JetBrains.Application.Settings; using JetBrains.DataFlow; diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs index bc02ca8..e7348d2 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Features.TooManyMethodArguments; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs index dbd642e..17800dc 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using CleanCode.Settings; using JetBrains.Application.Settings; using JetBrains.DataFlow; From e03a5d047c2132648db76fd774f817fa8369d382 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Mon, 5 Sep 2016 14:52:57 +0100 Subject: [PATCH 25/50] Minor clean up --- .../src/CleanCode/CleanCodeDaemonStage.cs | 29 ---------------- .../CleanCode/CleanCodeDaemonStageProcess.cs | 34 ------------------- 2 files changed, 63 deletions(-) diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs index 0a52bdd..2776f7f 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs @@ -1,32 +1,3 @@ -#region License - -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. - -#endregion - using JetBrains.Application.Settings; using JetBrains.ReSharper.Feature.Services.CSharp.Daemon; using JetBrains.ReSharper.Feature.Services.Daemon; diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 9416ebd..635ac46 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -1,30 +1,3 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - using System; using CleanCode.Features.ChainedReferences; using CleanCode.Features.ClassTooBig; @@ -37,7 +10,6 @@ using CleanCode.Features.TooManyDeclarations; using CleanCode.Features.TooManyDependencies; using CleanCode.Features.TooManyMethodArguments; -using JetBrains.Application.Progress; using JetBrains.Application.Settings; using JetBrains.ReSharper.Daemon.CSharp.Stages; using JetBrains.ReSharper.Feature.Services.Daemon; @@ -48,7 +20,6 @@ namespace CleanCode { public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase { - private readonly IDaemonProcess daemonProcess; private readonly IContextBoundSettingsStore settingsStore; private readonly MethodTooLongCheck methodTooLongCheck; private readonly ClassTooBigCheck classTooBigCheck; @@ -65,7 +36,6 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile file, IContextBoundSettingsStore settingsStore) : base(daemonProcess, file) { - this.daemonProcess = daemonProcess; this.settingsStore = settingsStore; // TODO: This is starting to feel like a beach of Benidorm in July. Refactoring needed. @@ -85,10 +55,6 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil public override void Execute(Action commiter) { HighlightInFile((file, consumer) => file.ProcessDescendants(this, consumer), commiter, settingsStore); - if (daemonProcess.InterruptFlag) - { - throw new ProcessCancelledException(); - } } public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration, IHighlightingConsumer context) From a609ba21e907e19e00817ae4e406bcaf59a9b7e3 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Mon, 5 Sep 2016 14:54:23 +0100 Subject: [PATCH 26/50] Rename assembly --- CleanCode/src/CleanCode/CleanCode.csproj | 2 +- .../Icons/Settings/ThemedIcons.Settings.Generated.cs | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index 58e85c4..10c1dc2 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -10,7 +10,7 @@ Library Properties CleanCode - CleanCode.8.2 + CleanCode v4.0 512 diff --git a/CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.cs b/CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.cs index 79dec05..ae6a859 100644 --- a/CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.cs +++ b/CleanCode/src/CleanCode/Resources/Icons/Settings/ThemedIcons.Settings.Generated.cs @@ -9,8 +9,7 @@ //------------------------------------------------------------------------------ [assembly: global::System.Windows.Markup.XmlnsDefinitionAttribute("urn:shemas-jetbrains-com:ui-application-icons-settings", "CleanCode.Resources.Icons")] -[assembly: global::JetBrains.UI.Icons.CompiledIcons.CompiledIconsPackAttribute(IconPackResourceIdentification="CleanCode.8.2;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.X" + - "aml", IconNames=new string[] { +[assembly: global::JetBrains.UI.Icons.CompiledIcons.CompiledIconsPackAttribute(IconPackResourceIdentification="CleanCode;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xaml", IconNames=new string[] { "CleanCode"})] namespace CleanCode.Resources.Icons @@ -77,8 +76,7 @@ public sealed class SettingsThemedIcons /// /// themediconmanager.GetIcon<SettingsThemedIcons.CleanCode>() // Icon image for rendering /// - [global::JetBrains.UI.Icons.CompiledIcons.CompiledIconClassAttribute("CleanCode.8.2;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.X" + - "aml", 0, "CleanCode")] + [global::JetBrains.UI.Icons.CompiledIcons.CompiledIconClassAttribute("CleanCode;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xaml", 0, "CleanCode")] public sealed class CleanCode : global::JetBrains.UI.Icons.CompiledIcons.CompiledIconClass { @@ -104,14 +102,13 @@ public sealed class CleanCode : global::JetBrains.UI.Icons.CompiledIcons.Compile /// /// themediconmanager.GetIcon<SettingsThemedIcons.CleanCode>() // Icon image for rendering /// - public static global::JetBrains.UI.Icons.IconId Id = new global::JetBrains.UI.Icons.CompiledIcons.CompiledIconId("CleanCode.8.2;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.X" + - "aml", 0, "CleanCode"); + public static global::JetBrains.UI.Icons.IconId Id = new global::JetBrains.UI.Icons.CompiledIcons.CompiledIconId("CleanCode;component/Resources/Icons/Settings/ThemedIcons.Settings.Generated.Xaml", 0, "CleanCode"); } } } -public sealed class RenderedIcons_ByPackResourceNameHash_759358C69B6C25A0E957D60B8E57EEED +public sealed class RenderedIcons_ByPackResourceNameHash_E1185BB5DC155E8A999AD43CA329D4ED { public static byte[] CleanCode____png__x1 = new byte[] { From 6e8f52094fdb047ac8ea3f1a65d04b37b5e1fdd3 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Mon, 5 Sep 2016 17:05:44 +0100 Subject: [PATCH 27/50] Searchable settings page --- CleanCode/src/CleanCode/CleanCode.csproj | 1 + .../CleanCode/Resources/Settings.Designer.cs | 137 ++++++++------- .../src/CleanCode/Resources/Settings.resx | 35 ++-- .../Settings/CheckSettingViewModel.cs | 45 ----- .../Settings/CheckTemplateSelector.cs | 50 ------ .../Settings/CleanCodeOptionsPage.cs | 58 +++++++ .../MonoValueCheckSettingViewModel.cs | 28 --- .../src/CleanCode/Settings/OptionsPage.xaml | 159 ------------------ .../CleanCode/Settings/OptionsPage.xaml.cs | 46 ----- .../CleanCode/Settings/OptionsViewModel.cs | 141 ---------------- CleanCode/src/CleanCode/Settings/ViewModel.cs | 18 -- 11 files changed, 151 insertions(+), 567 deletions(-) delete mode 100644 CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs delete mode 100644 CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs create mode 100644 CleanCode/src/CleanCode/Settings/CleanCodeOptionsPage.cs delete mode 100644 CleanCode/src/CleanCode/Settings/MonoValueCheckSettingViewModel.cs delete mode 100644 CleanCode/src/CleanCode/Settings/OptionsPage.xaml delete mode 100644 CleanCode/src/CleanCode/Settings/OptionsPage.xaml.cs delete mode 100644 CleanCode/src/CleanCode/Settings/OptionsViewModel.cs delete mode 100644 CleanCode/src/CleanCode/Settings/ViewModel.cs diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index 10c1dc2..543a523 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -233,6 +233,7 @@ True + OptionsPage.xaml diff --git a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs index 2ae88dc..aa1fc6b 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs @@ -60,15 +60,6 @@ internal Settings() { } } - /// - /// Looks up a localized string similar to Maximum Methods Per Class. - /// - public static string ClassTooBig { - get { - return ResourceManager.GetString("ClassTooBig", resourceCulture); - } - } - /// /// Looks up a localized string similar to Maximum Methods Per Class Check. /// @@ -88,16 +79,7 @@ public static string ComplexExpressionCheck { } /// - /// Looks up a localized string similar to Set the maximum of expressions that can be part of a condition. - /// - public static string ComplexExpressionMaximum { - get { - return ResourceManager.GetString("ComplexExpressionMaximum", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Maximum number of declarations per method. + /// Looks up a localized string similar to Maximum declarations per method. /// public static string DeclarationsMaximum { get { @@ -105,15 +87,6 @@ public static string DeclarationsMaximum { } } - /// - /// Looks up a localized string similar to Maximum level of nesting. - /// - public static string ExcessiveDepth { - get { - return ResourceManager.GetString("ExcessiveDepth", resourceCulture); - } - } - /// /// Looks up a localized string similar to Excessive Depth Of Nesting Check. /// @@ -142,29 +115,29 @@ public static string HollowTypeNameCheck { } /// - /// Looks up a localized string similar to List of meaningless suffixes. + /// Looks up a localized string similar to Maximum Chained References Check. /// - public static string HollowTypeNameWords { + public static string MaxChainedReferencesCheck { get { - return ResourceManager.GetString("HollowTypeNameWords", resourceCulture); + return ResourceManager.GetString("MaxChainedReferencesCheck", resourceCulture); } } /// - /// Looks up a localized string similar to Maximum Chained References. + /// Looks up a localized string similar to Maximum chained references. /// - public static string MaxChainedReferences { + public static string MaximumChainedReferences { get { - return ResourceManager.GetString("MaxChainedReferences", resourceCulture); + return ResourceManager.GetString("MaximumChainedReferences", resourceCulture); } } /// - /// Looks up a localized string similar to Maximum Chained References Check. + /// Looks up a localized string similar to Maximum interface dependencies for a constructor. /// - public static string MaxChainedReferencesCheck { + public static string MaximumConstructorDependencies { get { - return ResourceManager.GetString("MaxChainedReferencesCheck", resourceCulture); + return ResourceManager.GetString("MaximumConstructorDependencies", resourceCulture); } } @@ -177,6 +150,24 @@ public static string MaximumDependenciesCheck { } } + /// + /// Looks up a localized string similar to Maximum expressions inside a condition. + /// + public static string MaximumExpressionsInsideACondition { + get { + return ResourceManager.GetString("MaximumExpressionsInsideACondition", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Maximum level of nesting in a method. + /// + public static string MaximumLevelOfNestingInAMethod { + get { + return ResourceManager.GetString("MaximumLevelOfNestingInAMethod", resourceCulture); + } + } + /// /// Looks up a localized string similar to Maximum Method Arguments Check. /// @@ -187,83 +178,101 @@ public static string MaximumMethodArgumentsCheck { } /// - /// Looks up a localized string similar to Maximum Statements Per Method Check. + /// Looks up a localized string similar to Maximum method declaration parameters. /// - public static string MethodTooLongCheck { + public static string MaximumMethodDeclarationParameters { get { - return ResourceManager.GetString("MethodTooLongCheck", resourceCulture); + return ResourceManager.GetString("MaximumMethodDeclarationParameters", resourceCulture); } } /// - /// Looks up a localized string similar to Minimum length for the name of methods. + /// Looks up a localized string similar to Maximum methods per class. /// - public static string MinimumMethodNameLength { + public static string MaximumMethodsPerClass { get { - return ResourceManager.GetString("MinimumMethodNameLength", resourceCulture); + return ResourceManager.GetString("MaximumMethodsPerClass", resourceCulture); } } /// - /// Looks up a localized string similar to Minimum Method Name Length. + /// Looks up a localized string similar to Maximum statements per method. /// - public static string MinimumMethodNameLengthCheck { + public static string MaximumStatementsPerMethod { get { - return ResourceManager.GetString("MinimumMethodNameLengthCheck", resourceCulture); + return ResourceManager.GetString("MaximumStatementsPerMethod", resourceCulture); } } /// - /// Looks up a localized string similar to The options below help enforce certain practices that can be considered to leading to cleaner and more maintainable code.. + /// Looks up a localized string similar to List of meaningless suffixes. /// - public static string Options_Header { + public static string MeaninglessNameSuffixes { get { - return ResourceManager.GetString("Options_Header", resourceCulture); + return ResourceManager.GetString("MeaninglessNameSuffixes", resourceCulture); } } /// - /// Looks up a localized string similar to Note: All references to Clean Code, including but not limited to the Clean Code icon are used with permission of Robert C. Martin (a.k.a. UncleBob). + /// Looks up a localized string similar to Separate items with commas. /// - public static string Options_SubHeader { + public static string MeaninglessNameSuffixesTooltip { get { - return ResourceManager.GetString("Options_SubHeader", resourceCulture); + return ResourceManager.GetString("MeaninglessNameSuffixesTooltip", resourceCulture); } } /// - /// Looks up a localized string similar to Maximum statements per method. + /// Looks up a localized string similar to Maximum Statements Per Method Check. /// - public static string TooLongLinesPerMethod { + public static string MethodTooLongCheck { get { - return ResourceManager.GetString("TooLongLinesPerMethod", resourceCulture); + return ResourceManager.GetString("MethodTooLongCheck", resourceCulture); } } /// - /// Looks up a localized string similar to Too Many Declarations Check. + /// Looks up a localized string similar to Minimum method name length. /// - public static string TooManyDeclarationsCheck { + public static string MinimumMethodNameLength { get { - return ResourceManager.GetString("TooManyDeclarationsCheck", resourceCulture); + return ResourceManager.GetString("MinimumMethodNameLength", resourceCulture); } } /// - /// Looks up a localized string similar to Set maximum dependencies to. + /// Looks up a localized string similar to Minimum Method Name Length. /// - public static string TooManyDependencies { + public static string MinimumMethodNameLengthCheck { get { - return ResourceManager.GetString("TooManyDependencies", resourceCulture); + return ResourceManager.GetString("MinimumMethodNameLengthCheck", resourceCulture); } } /// - /// Looks up a localized string similar to Set maximum arguments to. + /// Looks up a localized string similar to The options below help enforce certain practices that can be considered to leading to cleaner and more maintainable code.. /// - public static string TooManyMethodArguments { + public static string Options_Header { + get { + return ResourceManager.GetString("Options_Header", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Note: All references to Clean Code, including but not limited to the Clean Code icon are used with permission of Robert C. Martin (a.k.a. UncleBob). + /// + public static string Options_SubHeader { get { - return ResourceManager.GetString("TooManyMethodArguments", resourceCulture); + return ResourceManager.GetString("Options_SubHeader", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Too Many Declarations Check. + /// + public static string TooManyDeclarationsCheck { + get { + return ResourceManager.GetString("TooManyDeclarationsCheck", resourceCulture); } } } diff --git a/CleanCode/src/CleanCode/Resources/Settings.resx b/CleanCode/src/CleanCode/Resources/Settings.resx index c346985..683c2b1 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.resx +++ b/CleanCode/src/CleanCode/Resources/Settings.resx @@ -129,38 +129,38 @@ Maximum Statements Per Method Check - + Maximum statements per method - - Set maximum dependencies to + + Maximum interface dependencies for a constructor - - Set maximum arguments to + + Maximum method declaration parameters Note: All references to Clean Code, including but not limited to the Clean Code icon are used with permission of Robert C. Martin (a.k.a. UncleBob) - - Maximum level of nesting + + Maximum level of nesting in a method Excessive Depth Of Nesting Check - - Maximum Methods Per Class + + Maximum methods per class Maximum Methods Per Class Check - - Maximum Chained References + + Maximum chained references Maximum Chained References Check - Minimum length for the name of methods + Minimum method name length Minimum Method Name Length @@ -168,8 +168,8 @@ Complex expression check (conditions) - - Set the maximum of expressions that can be part of a condition + + Maximum expressions inside a condition Flag Arguments Check @@ -177,11 +177,14 @@ Hollow Type Name Check - + List of meaningless suffixes + + Separate items with commas + - Maximum number of declarations per method + Maximum declarations per method Too Many Declarations Check diff --git a/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs b/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs deleted file mode 100644 index 471333d..0000000 --- a/CleanCode/src/CleanCode/Settings/CheckSettingViewModel.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Linq.Expressions; -using JetBrains.Annotations; -using JetBrains.Application.Settings; - -namespace CleanCode.Settings -{ - public class CheckSettingViewModel : ViewModel - { - private readonly Expression> isEnabledSelector; - - protected readonly IContextBoundSettingsStore Settings; - - public CheckSettingViewModel([NotNull] IContextBoundSettingsStore settings, - [NotNull] Expression> isEnabledSelector) - { - if (settings == null) - { - throw new ArgumentNullException("settings"); - } - - if (isEnabledSelector == null) - { - throw new ArgumentNullException("isEnabledSelector"); - } - - Settings = settings; - this.isEnabledSelector = isEnabledSelector; - } - - public string Category { get; set; } - - public bool IsEnabled - { - get { return Settings.GetValue(isEnabledSelector); } - set - { - Settings.SetValue(isEnabledSelector, value); - OnPropertyChanged(); - } - } - - public string IsEnabledDescription { get; set; } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs b/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs deleted file mode 100644 index 02da0c9..0000000 --- a/CleanCode/src/CleanCode/Settings/CheckTemplateSelector.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Linq; -using System.Windows; -using System.Windows.Controls; - -namespace CleanCode.Settings -{ - public class CheckTemplateSelector : DataTemplateSelector - { - public DataTemplate ThresholdCheckTemplate { get; set; } - public DataTemplate BasicCheckTemplate { get; set; } - public DataTemplate StringCheckTemplate { get; set; } - - public override DataTemplate SelectTemplate(object item, DependencyObject container) - { - if (item == null) - { - return base.SelectTemplate(item, container); - } - - var type = item.GetType(); - - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(MonoValueCheckSettingViewModel<>)) - { - return GetTemplateFromGenericType(type); - } - if (item is CheckSettingViewModel) - { - return BasicCheckTemplate; - } - return base.SelectTemplate(item, container); - } - - private DataTemplate GetTemplateFromGenericType(Type type) - { - var firstType = type.GetGenericArguments().First(); - if (firstType == typeof (string)) - { - return StringCheckTemplate; - } - return ThresholdCheckTemplate; - } - - - bool IsTypeof(object t) - { - return (t is T); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/CleanCodeOptionsPage.cs b/CleanCode/src/CleanCode/Settings/CleanCodeOptionsPage.cs new file mode 100644 index 0000000..35b1b17 --- /dev/null +++ b/CleanCode/src/CleanCode/Settings/CleanCodeOptionsPage.cs @@ -0,0 +1,58 @@ +using CleanCode.Resources.Icons; +using JetBrains.DataFlow; +using JetBrains.ReSharper.Feature.Services.Daemon.OptionPages; +using JetBrains.UI.Options; +using JetBrains.UI.Options.OptionsDialog2.SimpleOptions; + +namespace CleanCode.Settings +{ + [OptionsPage(PageId, "Clean Code", typeof(SettingsThemedIcons.CleanCode), ParentId = CodeInspectionPage.PID)] + public class CleanCodeOptionsPage : CustomSimpleOptionsPage + { + private const string PageId = "CleanCode"; + + public CleanCodeOptionsPage(Lifetime lifetime, OptionsSettingsSmartContext optionsSettingsSmartContext) + : base(lifetime, optionsSettingsSmartContext) + { + AddHeader("Single Responsibility"); + AddText("A class should only have a single responsibility. Do not do too much in a class or method."); + AddIntOption((CleanCodeSettings s) => s.ClassTooBigMaximum, + Resources.Settings.MaximumMethodsPerClass, + "Too many method declarations in a class is an indicator that the class is doing too much."); + AddIntOption((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum, + Resources.Settings.MaximumMethodDeclarationParameters, + "Too many parameters in a method declaration is an indicator of having more than one responsibility"); + AddIntOption((CleanCodeSettings s) => s.MethodTooLongMaximum, Resources.Settings.MaximumStatementsPerMethod, + "Long methods are indicator of having more than one responsibility."); + AddIntOption((CleanCodeSettings s) => s.TooManyDeclarationsMaximum, + Resources.Settings.DeclarationsMaximum, + "Too many variables are an indicator of having more than one responsibility."); + AddIntOption((CleanCodeSettings s) => s.ExcessiveIndentationMaximum, + Resources.Settings.MaximumLevelOfNestingInAMethod, + "Too much nesting in a method is an indicator of having more than one responsibility."); + + AddHeader("Coupling"); + AddText("Avoid excessive coupling beween classes."); + AddIntOption((CleanCodeSettings s) => s.TooManyDependenciesMaximum, + Resources.Settings.MaximumConstructorDependencies); + AddIntOption((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum, + Resources.Settings.MaximumChainedReferences, + "Avoid breaking the Law of Demeter."); + + AddHeader("Legibility"); + AddText("Names should be meaningful."); + AddIntOption((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimum, + Resources.Settings.MinimumMethodNameLength); + AddStringOption((CleanCodeSettings s) => s.HollowTypeNameString, + Resources.Settings.MeaninglessNameSuffixes, + Resources.Settings.MeaninglessNameSuffixesTooltip); + + AddHeader("Complexity"); + AddText("Reduce complexity in individual statements."); + AddIntOption((CleanCodeSettings s) => s.ComplexExpressionMaximum, + Resources.Settings.MaximumExpressionsInsideACondition); + + FinishPage(); + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/MonoValueCheckSettingViewModel.cs b/CleanCode/src/CleanCode/Settings/MonoValueCheckSettingViewModel.cs deleted file mode 100644 index ab0767d..0000000 --- a/CleanCode/src/CleanCode/Settings/MonoValueCheckSettingViewModel.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Linq.Expressions; -using JetBrains.Application.Settings; - -namespace CleanCode.Settings -{ - public class MonoValueCheckSettingViewModel : CheckSettingViewModel - { - private readonly Expression> valueSelector; - - public MonoValueCheckSettingViewModel(IContextBoundSettingsStore settings, Expression> isEnabledSelector, Expression> valueSelector) : base(settings, isEnabledSelector) - { - this.valueSelector = valueSelector; - } - - public TType Value - { - get { return Settings.GetValue(valueSelector); } - set - { - Settings.SetValue(valueSelector, value); - OnPropertyChanged(); - } - } - - public string ValueDescription { get; set; } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml deleted file mode 100644 index 97dfe00..0000000 --- a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml.cs b/CleanCode/src/CleanCode/Settings/OptionsPage.xaml.cs deleted file mode 100644 index 0a8613f..0000000 --- a/CleanCode/src/CleanCode/Settings/OptionsPage.xaml.cs +++ /dev/null @@ -1,46 +0,0 @@ -using CleanCode.Resources.Icons; -using JetBrains.DataFlow; -using JetBrains.ReSharper.Feature.Services.Daemon.OptionPages; -using JetBrains.UI.Application; -using JetBrains.UI.CrossFramework; -using JetBrains.UI.Options; - -namespace CleanCode.Settings -{ - [OptionsPage(PageId, "Clean Code", typeof(SettingsThemedIcons.CleanCode), ParentId = CodeInspectionPage.PID)] - public partial class OptionsPage : IOptionsPage - { - const string PageId = "CleanCode"; - - public OptionsPage(Lifetime lifetime, IUIApplication environment, OptionsSettingsSmartContext settings) - : this() - { - DataContext = new OptionsViewModel(settings); - } - - private OptionsPage() - { - InitializeComponent(); - } - - public bool OnOk() - { - return true; - } - - public bool ValidatePage() - { - return true; - } - - public EitherControl Control - { - get - { - return this; - } - } - - public string Id { get; private set; } - } -} diff --git a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs b/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs deleted file mode 100644 index 5958f30..0000000 --- a/CleanCode/src/CleanCode/Settings/OptionsViewModel.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System.Collections; -using JetBrains.Application.Settings; - -namespace CleanCode.Settings -{ - public sealed class OptionsViewModel : ViewModel - { - public OptionsViewModel(IContextBoundSettingsStore settings) - { - Options = GetViewModels(settings); - } - - public ArrayList Options { get; set; } - - // TODO: We need to refactor this method. - // ReSharper disable once MethodTooLong - private static ArrayList GetViewModels(IContextBoundSettingsStore settings) - { - var viewModels = new ArrayList(); - - viewModels.Add(new MonoValueCheckSettingViewModel( - settings, - codeSettings => codeSettings.MethodTooLongEnabled, - codeSettings => codeSettings.MethodTooLongMaximum) - { - IsEnabledDescription = Resources.Settings.MethodTooLongCheck, - ValueDescription = Resources.Settings.TooLongLinesPerMethod, - Category = Categories.Size, - }); - - viewModels.Add(new MonoValueCheckSettingViewModel( - settings, - e => e.TooManyDependenciesMaximumEnabled, - e => e.TooManyDependenciesMaximum) - { - IsEnabledDescription = Resources.Settings.MaximumDependenciesCheck, - ValueDescription = Resources.Settings.TooManyDependencies, - Category = Categories.Coupling, - }); - - viewModels.Add(new MonoValueCheckSettingViewModel( - settings, - e => e.TooManyMethodArgumentsEnabled, - e => e.TooManyMethodArgumentsMaximum) - { - IsEnabledDescription = Resources.Settings.MaximumMethodArgumentsCheck, - ValueDescription = Resources.Settings.TooManyMethodArguments, - Category = Categories.Responsibility, - }); - - viewModels.Add(new MonoValueCheckSettingViewModel( - settings, - e => e.ExcessiveIndentationEnabled, - e => e.ExcessiveIndentationMaximum) - { - IsEnabledDescription = Resources.Settings.ExcessiveDepthCheck, - ValueDescription = Resources.Settings.ExcessiveDepth, - Category = Categories.Coupling, - }); - - viewModels.Add(new MonoValueCheckSettingViewModel( - settings, - e => e.ClassTooBigEnabled, - e => e.ClassTooBigMaximum) - { - IsEnabledDescription = Resources.Settings.ClassTooBigCheck, - ValueDescription = Resources.Settings.ClassTooBig, - Category = Categories.Size, - }); - - viewModels.Add(new MonoValueCheckSettingViewModel( - settings, - e => e.TooManyChainedReferencesEnabled, - e => e.TooManyChainedReferencesMaximum) - { - IsEnabledDescription = Resources.Settings.MaxChainedReferencesCheck, - ValueDescription = Resources.Settings.MaxChainedReferences, - Category = Categories.Responsibility, - }); - - viewModels.Add(new MonoValueCheckSettingViewModel( - settings, - e => e.MethodNameNotMeaningfulMinimumEnabled, - e => e.MethodNameNotMeaningfulMinimum) - { - IsEnabledDescription = Resources.Settings.MinimumMethodNameLengthCheck, - ValueDescription = Resources.Settings.MinimumMethodNameLength, - Category = Categories.Legibility, - }); - - viewModels.Add(new MonoValueCheckSettingViewModel( - settings, - e => e.ComplexExpressionEnabled, - e => e.ComplexExpressionMaximum) - { - IsEnabledDescription = Resources.Settings.ComplexExpressionCheck, - ValueDescription = Resources.Settings.ComplexExpressionMaximum, - Category = Categories.Complexity, - }); - - viewModels.Add(new CheckSettingViewModel( - settings, - e => e.FlagArgumentsEnabled) - { - IsEnabledDescription = Resources.Settings.FlagArgumentsCheck, - Category = Categories.Responsibility, - }); - - viewModels.Add(new MonoValueCheckSettingViewModel( - settings, - codeSettings => codeSettings.HollowTypeNameEnabled, - codeSettings => codeSettings.HollowTypeNameString) - { - IsEnabledDescription = Resources.Settings.HollowTypeNameCheck, - ValueDescription = Resources.Settings.HollowTypeNameWords, - Category = Categories.Legibility, - }); - - viewModels.Add(new MonoValueCheckSettingViewModel( - settings, - codeSettings => codeSettings.TooManyDeclarationsEnabled, - codeSettings => codeSettings.TooManyDeclarationsMaximum) - { - IsEnabledDescription = Resources.Settings.TooManyDeclarationsCheck, - ValueDescription = Resources.Settings.DeclarationsMaximum, - Category = Categories.Responsibility, - }); - - return viewModels; - } - } - - public class Categories - { - public const string Size = "Size"; - public const string Complexity = "Complexity"; - public const string Coupling = "Coupling"; - public const string Responsibility = "Responsibility"; - public const string Legibility = "Legibility"; - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/ViewModel.cs b/CleanCode/src/CleanCode/Settings/ViewModel.cs deleted file mode 100644 index 2513048..0000000 --- a/CleanCode/src/CleanCode/Settings/ViewModel.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.ComponentModel; -using System.Runtime.CompilerServices; -using JetBrains.Annotations; - -namespace CleanCode.Settings -{ - public abstract class ViewModel : INotifyPropertyChanged - { - public virtual event PropertyChangedEventHandler PropertyChanged; - - [NotifyPropertyChangedInvocator] - protected void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - var handler = PropertyChanged; - if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); - } - } -} \ No newline at end of file From 0a6d2d31f6e7e4c3063b690084755a2c94e672c3 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Mon, 5 Sep 2016 17:09:14 +0100 Subject: [PATCH 28/50] Replace multiple settings watchers with just one --- CleanCode/src/CleanCode/CleanCode.csproj | 29 +----------- .../InvalidateOnMaximumChainedCalls.cs | 18 -------- .../InvalidateOnMaximumMethodsPerClass.cs | 18 -------- .../InvalidateOnComplexExpressionChange.cs | 18 -------- .../InvalidateOnExcessiveIndentationChange.cs | 45 ------------------- .../InvalidateOnHollowTypeNameStringChange.cs | 19 -------- ...validateOnMinimumMethodNameLenghtChange.cs | 18 -------- .../InvalidateOnMaximumLinesChange.cs | 18 -------- .../InvalidateOnMaximumDeclarationsChange.cs | 18 -------- .../InvalidateOnMaximumDependenciesChange.cs | 18 -------- ...nvalidateOnMaximumMethodArgumentsChange.cs | 19 -------- .../CleanCode/InvalidateOnSettingsChange.cs | 18 ++++++++ 12 files changed, 19 insertions(+), 237 deletions(-) delete mode 100644 CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs delete mode 100644 CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs delete mode 100644 CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs delete mode 100644 CleanCode/src/CleanCode/Features/ExcessiveIndentation/InvalidateOnExcessiveIndentationChange.cs delete mode 100644 CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs delete mode 100644 CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs delete mode 100644 CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs delete mode 100644 CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs delete mode 100644 CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs delete mode 100644 CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs create mode 100644 CleanCode/src/CleanCode/InvalidateOnSettingsChange.cs diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index 543a523..1a51ff3 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -168,17 +168,13 @@ - - - - Code @@ -189,37 +185,26 @@ - - Code - - Code - - Code - - Code - Code - - Code - + @@ -232,16 +217,8 @@ True True - - - OptionsPage.xaml - - - - - @@ -261,10 +238,6 @@ MSBuild:Compile Designer - - Designer - MSBuild:Compile - diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs deleted file mode 100644 index e51c21e..0000000 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/InvalidateOnMaximumChainedCalls.cs +++ /dev/null @@ -1,18 +0,0 @@ -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Feature.Services.Daemon; - -namespace CleanCode.Features.ChainedReferences -{ - [SolutionComponent] - public class InvalidateOnMaximumChainedCalls - { - public InvalidateOnMaximumChainedCalls(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) - { - var maxDepth = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); - settingsStore.AdviseChange(lifetime, maxDepth, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs deleted file mode 100644 index 8f4790c..0000000 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/InvalidateOnMaximumMethodsPerClass.cs +++ /dev/null @@ -1,18 +0,0 @@ -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Feature.Services.Daemon; - -namespace CleanCode.Features.ClassTooBig -{ - [SolutionComponent] - public class InvalidateOnMaximumMethodsPerClass - { - public InvalidateOnMaximumMethodsPerClass(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) - { - var maxDepth = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.ClassTooBigMaximum); - settingsStore.AdviseChange(lifetime, maxDepth, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs deleted file mode 100644 index 3f26c49..0000000 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/InvalidateOnComplexExpressionChange.cs +++ /dev/null @@ -1,18 +0,0 @@ -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Feature.Services.Daemon; - -namespace CleanCode.Features.ComplexExpression -{ - [SolutionComponent] - public class InvalidateOnComplexExpressionChange - { - public InvalidateOnComplexExpressionChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) - { - var maxDepth = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.ComplexExpressionMaximum); - settingsStore.AdviseChange(lifetime, maxDepth, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/InvalidateOnExcessiveIndentationChange.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/InvalidateOnExcessiveIndentationChange.cs deleted file mode 100644 index 57aaef3..0000000 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/InvalidateOnExcessiveIndentationChange.cs +++ /dev/null @@ -1,45 +0,0 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion - -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Feature.Services.Daemon; - -namespace CleanCode.Features.ExcessiveIndentation -{ - [SolutionComponent] - public class InvalidateOnExcessiveIndentationChange - { - public InvalidateOnExcessiveIndentationChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) - { - var maxDepth = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.ExcessiveIndentationMaximum); - settingsStore.AdviseChange(lifetime, maxDepth, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs b/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs deleted file mode 100644 index 2068239..0000000 --- a/CleanCode/src/CleanCode/Features/HollowNames/InvalidateOnHollowTypeNameStringChange.cs +++ /dev/null @@ -1,19 +0,0 @@ -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Feature.Services.Daemon; - -namespace CleanCode.Features.HollowNames -{ - - [SolutionComponent] - public class InvalidateOnHollowTypeNameStringChange - { - public InvalidateOnHollowTypeNameStringChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) - { - var maxLines = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.HollowTypeNameString); - settingsStore.AdviseChange(lifetime, maxLines, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs deleted file mode 100644 index 21db1c2..0000000 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/InvalidateOnMinimumMethodNameLenghtChange.cs +++ /dev/null @@ -1,18 +0,0 @@ -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Feature.Services.Daemon; - -namespace CleanCode.Features.MethodNameNotMeaningful -{ - [SolutionComponent] - public class InvalidateOnMinimumMethodNameLenghtChange - { - public InvalidateOnMinimumMethodNameLenghtChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) - { - var minMethodNameLenght = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimumEnabled); - settingsStore.AdviseChange(lifetime, minMethodNameLenght, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs deleted file mode 100644 index c8fcb17..0000000 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/InvalidateOnMaximumLinesChange.cs +++ /dev/null @@ -1,18 +0,0 @@ -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Feature.Services.Daemon; - -namespace CleanCode.Features.MethodTooLong -{ - [SolutionComponent] - public class InvalidateOnMaximumLinesChange - { - public InvalidateOnMaximumLinesChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) - { - var maxLines = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.MethodTooLongMaximum); - settingsStore.AdviseChange(lifetime, maxLines, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs b/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs deleted file mode 100644 index f17d78e..0000000 --- a/CleanCode/src/CleanCode/Features/TooManyDeclarations/InvalidateOnMaximumDeclarationsChange.cs +++ /dev/null @@ -1,18 +0,0 @@ -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Feature.Services.Daemon; - -namespace CleanCode.Features.TooManyDeclarations -{ - [SolutionComponent] - public class InvalidateOnMaximumDeclarationsChange - { - public InvalidateOnMaximumDeclarationsChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) - { - var maxLines = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyDeclarationsMaximum); - settingsStore.AdviseChange(lifetime, maxLines, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs deleted file mode 100644 index a7629d2..0000000 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/InvalidateOnMaximumDependenciesChange.cs +++ /dev/null @@ -1,18 +0,0 @@ -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Feature.Services.Daemon; - -namespace CleanCode.Features.TooManyDependencies -{ - [SolutionComponent] - public class InvalidateOnMaximumDependenciesChange - { - public InvalidateOnMaximumDependenciesChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) - { - var maxParams = settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyDependenciesMaximum); - settingsStore.AdviseChange(lifetime, maxParams, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs deleted file mode 100644 index 17800dc..0000000 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/InvalidateOnMaximumMethodArgumentsChange.cs +++ /dev/null @@ -1,19 +0,0 @@ -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.DataFlow; -using JetBrains.ProjectModel; -using JetBrains.ReSharper.Feature.Services.Daemon; - -namespace CleanCode.Features.TooManyMethodArguments -{ - [SolutionComponent] - public class InvalidateOnMaximumMethodArgumentsChange - { - public InvalidateOnMaximumMethodArgumentsChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) - { - var maxArguments = - settingsStore.Schema.GetScalarEntry((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); - settingsStore.AdviseChange(lifetime, maxArguments, daemon.Invalidate); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/InvalidateOnSettingsChange.cs b/CleanCode/src/CleanCode/InvalidateOnSettingsChange.cs new file mode 100644 index 0000000..4005a1a --- /dev/null +++ b/CleanCode/src/CleanCode/InvalidateOnSettingsChange.cs @@ -0,0 +1,18 @@ +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.DataFlow; +using JetBrains.ProjectModel; +using JetBrains.ReSharper.Feature.Services.Daemon; + +namespace CleanCode +{ + [SolutionComponent] + public class InvalidateOnSettingsChange + { + public InvalidateOnSettingsChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore) + { + var settingsKey = settingsStore.Schema.GetKey(); + settingsStore.AdviseChange(lifetime, settingsKey, daemon.Invalidate); + } + } +} \ No newline at end of file From 0e4aaf0d871666843db60ff4698caca8b179e5d8 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Mon, 5 Sep 2016 18:15:22 +0100 Subject: [PATCH 29/50] ChainedRefernce is now an ElementProblemAnalyser --- CleanCode/src/CleanCode/CleanCode.csproj | 3 +- .../CleanCode/CleanCodeDaemonStageProcess.cs | 8 ---- .../CleanCodeHighlightingGroupIds.cs | 12 +++++ .../ChainedReferencesCheck.cs | 45 ++++++++----------- ...> MaximumChainedReferencesHighlighting.cs} | 11 ++--- 5 files changed, 38 insertions(+), 41 deletions(-) create mode 100644 CleanCode/src/CleanCode/CleanCodeHighlightingGroupIds.cs rename CleanCode/src/CleanCode/Features/ChainedReferences/{Highlighting.cs => MaximumChainedReferencesHighlighting.cs} (65%) diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index 1a51ff3..262f624 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -167,7 +167,8 @@ - + + diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 635ac46..9b13fcc 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -1,5 +1,4 @@ using System; -using CleanCode.Features.ChainedReferences; using CleanCode.Features.ClassTooBig; using CleanCode.Features.ComplexExpression; using CleanCode.Features.ExcessiveIndentation; @@ -27,7 +26,6 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase private readonly ExcessiveIndentationCheck excessiveIndentationCheck; private readonly TooManyDependenciesCheck tooManyDependenciesCheck; private readonly MethodNameNotMeaningfulCheck methodNamesNotMeaningfulCheck; - private readonly ChainedReferencesCheck chainedReferencesCheck; private readonly FlagArgumentsCheck flagArgumentsCheck; private readonly ComplexExpressionCheck complexExpressionCheck; private readonly HollowNamesCheck hollowNamesCheck; @@ -45,7 +43,6 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil excessiveIndentationCheck = new ExcessiveIndentationCheck(settingsStore); tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); methodNamesNotMeaningfulCheck = new MethodNameNotMeaningfulCheck(settingsStore); - chainedReferencesCheck = new ChainedReferencesCheck(settingsStore); flagArgumentsCheck = new FlagArgumentsCheck(settingsStore); complexExpressionCheck = new ComplexExpressionCheck(settingsStore); hollowNamesCheck = new HollowNamesCheck(settingsStore); @@ -67,11 +64,6 @@ public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration tooManyDeclarationsCheck.ExecuteIfEnabled(methodDeclaration, context); } - public override void VisitCSharpStatement(ICSharpStatement cSharpStatementParam, IHighlightingConsumer context) - { - chainedReferencesCheck.ExecuteIfEnabled(cSharpStatementParam, context); - } - public override void VisitConstructorDeclaration(IConstructorDeclaration constructorDeclaration, IHighlightingConsumer context) { tooManyDependenciesCheck.ExecuteIfEnabled(constructorDeclaration, context); diff --git a/CleanCode/src/CleanCode/CleanCodeHighlightingGroupIds.cs b/CleanCode/src/CleanCode/CleanCodeHighlightingGroupIds.cs new file mode 100644 index 0000000..30d5108 --- /dev/null +++ b/CleanCode/src/CleanCode/CleanCodeHighlightingGroupIds.cs @@ -0,0 +1,12 @@ +using CleanCode; +using JetBrains.ReSharper.Feature.Services.Daemon; + +[assembly: RegisterConfigurableHighlightingsGroup(CleanCodeHighlightingGroupIds.CleanCode, "Clean Code")] + +namespace CleanCode +{ + public static class CleanCodeHighlightingGroupIds + { + public const string CleanCode = "CleanCode"; + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs index c9c28fe..420885a 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs @@ -2,6 +2,7 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.CSharp.Tree; @@ -9,22 +10,22 @@ namespace CleanCode.Features.ChainedReferences { - public class ChainedReferencesCheck : MonoValueCheck + [ElementProblemAnalyzer(typeof(ICSharpStatement), HighlightingTypes = new [] { - public ChainedReferencesCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override void ExecuteCore(ICSharpStatement constructorDeclaration, IHighlightingConsumer consumer) + typeof(MaximumChainedReferencesHighlighting) + })] + public class ChainedReferencesCheck : ElementProblemAnalyzer + { + protected override void Run(ICSharpStatement element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - if (constructorDeclaration != null && !constructorDeclaration.IsEmbeddedStatement) + if (!element.IsEmbeddedStatement) { - HighlightMethodChainsThatAreTooLong(constructorDeclaration, consumer); + var threshold = data.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); + HighlightMethodChainsThatAreTooLong(element, consumer, threshold); } } - private void HighlightMethodChainsThatAreTooLong(ITreeNode statement, IHighlightingConsumer consumer) + private void HighlightMethodChainsThatAreTooLong(ITreeNode statement, IHighlightingConsumer consumer, int threshold) { var children = statement.Children(); @@ -33,16 +34,16 @@ private void HighlightMethodChainsThatAreTooLong(ITreeNode statement, IHighlight var referenceExpression = treeNode as IReferenceExpression; if (referenceExpression != null) { - HightlightReferenceExpressionIfNeeded(referenceExpression, consumer); + HighlightReferenceExpressionIfNeeded(referenceExpression, consumer, threshold); } else { - HighlightMethodChainsThatAreTooLong(treeNode, consumer); + HighlightMethodChainsThatAreTooLong(treeNode, consumer, threshold); } } } - private void HightlightReferenceExpressionIfNeeded(IReferenceExpression referenceExpression, IHighlightingConsumer consumer) + private void HighlightReferenceExpressionIfNeeded(IReferenceExpression referenceExpression, IHighlightingConsumer consumer, int threshold) { var types = new HashSet(); @@ -66,28 +67,18 @@ private void HightlightReferenceExpressionIfNeeded(IReferenceExpression referenc if (!isFluentChain) { - if (chainLength > Value) + if (chainLength > threshold) { - AddHighlightning(referenceExpression, consumer); + AddHighlighting(referenceExpression, consumer); } } } - protected override int Value - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesEnabled); } - } - - private static void AddHighlightning(IReferenceExpression reference, IHighlightingConsumer consumer) + private static void AddHighlighting(IReferenceExpression reference, IHighlightingConsumer consumer) { var nameIdentifier = reference.NameIdentifier; var documentRange = nameIdentifier.GetDocumentRange(); - var highlighting = new Highlighting(Warnings.ChainedReferences, documentRange); + var highlighting = new MaximumChainedReferencesHighlighting(Warnings.ChainedReferences, documentRange); consumer.AddHighlighting(highlighting); } } diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs similarity index 65% rename from CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs rename to CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs index 99ac8a6..6d30153 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs @@ -1,22 +1,23 @@ +using CleanCode; using CleanCode.Features.ChainedReferences; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Chained References", "There are too many chained references.", +[assembly: RegisterConfigurableSeverity(MaximumChainedReferencesHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Too many chained references", "Too many chained references can break the Law of Demeter.", Severity.WARNING, false)] namespace CleanCode.Features.ChainedReferences { [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting + public class MaximumChainedReferencesHighlighting : IHighlighting { - internal const string SeverityID = "MaximumChainedReferences"; + internal const string SeverityID = "TooManyChainedReferences"; private readonly string tooltip; private readonly DocumentRange documentRange; - public Highlighting(string toolTip, DocumentRange documentRange) + public MaximumChainedReferencesHighlighting(string toolTip, DocumentRange documentRange) { tooltip = toolTip; this.documentRange = documentRange; From c98f680bdcf63a2f364d9930540bfab5d2fd3e3b Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Mon, 5 Sep 2016 18:19:40 +0100 Subject: [PATCH 30/50] ClassTooBig as EPA --- CleanCode/src/CleanCode/CleanCode.csproj | 2 +- .../CleanCode/CleanCodeDaemonStageProcess.cs | 4 --- .../MaximumChainedReferencesHighlighting.cs | 1 + .../Features/ClassTooBig/ClassTooBigCheck.cs | 32 +++++++------------ ...lighting.cs => ClassTooBigHighlighting.cs} | 10 +++--- 5 files changed, 19 insertions(+), 30 deletions(-) rename CleanCode/src/CleanCode/Features/ClassTooBig/{Highlighting.cs => ClassTooBigHighlighting.cs} (73%) diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index 262f624..c5a4959 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -171,7 +171,7 @@ - + diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 9b13fcc..cc0abef 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -1,5 +1,4 @@ using System; -using CleanCode.Features.ClassTooBig; using CleanCode.Features.ComplexExpression; using CleanCode.Features.ExcessiveIndentation; using CleanCode.Features.FlagArguments; @@ -21,7 +20,6 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase { private readonly IContextBoundSettingsStore settingsStore; private readonly MethodTooLongCheck methodTooLongCheck; - private readonly ClassTooBigCheck classTooBigCheck; private readonly TooManyMethodArgumentsCheck tooManyArgumentsCheck; private readonly ExcessiveIndentationCheck excessiveIndentationCheck; private readonly TooManyDependenciesCheck tooManyDependenciesCheck; @@ -38,7 +36,6 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil // TODO: This is starting to feel like a beach of Benidorm in July. Refactoring needed. methodTooLongCheck = new MethodTooLongCheck(settingsStore); - classTooBigCheck = new ClassTooBigCheck(settingsStore); tooManyArgumentsCheck = new TooManyMethodArgumentsCheck(settingsStore); excessiveIndentationCheck = new ExcessiveIndentationCheck(settingsStore); tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); @@ -71,7 +68,6 @@ public override void VisitConstructorDeclaration(IConstructorDeclaration constru public override void VisitClassDeclaration(IClassDeclaration classDeclaration, IHighlightingConsumer context) { - classTooBigCheck.ExecuteIfEnabled(classDeclaration, context); hollowNamesCheck.ExecuteIfEnabled(classDeclaration, context); } diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs index 6d30153..1f5df58 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs @@ -14,6 +14,7 @@ namespace CleanCode.Features.ChainedReferences public class MaximumChainedReferencesHighlighting : IHighlighting { internal const string SeverityID = "TooManyChainedReferences"; + private readonly string tooltip; private readonly DocumentRange documentRange; diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs index 9e5c860..535d3af 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs @@ -1,41 +1,31 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; namespace CleanCode.Features.ClassTooBig { - public class ClassTooBigCheck : MonoValueCheck + [ElementProblemAnalyzer(typeof(IClassDeclaration), HighlightingTypes = new [] { - public ClassTooBigCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override void ExecuteCore(IClassDeclaration constructorDeclaration, IHighlightingConsumer consumer) + typeof(ClassTooBigHighlighting) + })] + public class ClassTooBigCheck : ElementProblemAnalyzer + { + protected override void Run(IClassDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var maxLength = Value; + var maxLength = data.SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigMaximum); - var statementCount = constructorDeclaration.CountChildren(); + var statementCount = element.CountChildren(); if (statementCount > maxLength) { - var declarationIdentifier = constructorDeclaration.NameIdentifier; + var declarationIdentifier = element.NameIdentifier; var documentRange = declarationIdentifier.GetDocumentRange(); - var highlighting = new Highlighting(Warnings.ClassTooBig, documentRange); + var highlighting = new ClassTooBigHighlighting(Warnings.ClassTooBig, documentRange); consumer.AddHighlighting(highlighting); } } - - protected override int Value - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigEnabled); } - } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs similarity index 73% rename from CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs rename to CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs index d79c2bf..6107f63 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs @@ -1,22 +1,24 @@ +using CleanCode; using CleanCode.Features.ClassTooBig; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Class Too Big", "This class contains too many methods", +[assembly: RegisterConfigurableSeverity(ClassTooBigHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Class too big", "This class contains too many methods", Severity.SUGGESTION, false)] namespace CleanCode.Features.ClassTooBig { [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting + public class ClassTooBigHighlighting : IHighlighting { internal const string SeverityID = "ClassTooBig"; + private readonly string tooltip; private readonly DocumentRange documentRange; - public Highlighting(string toolTip, DocumentRange documentRange) + public ClassTooBigHighlighting(string toolTip, DocumentRange documentRange) { tooltip = toolTip; this.documentRange = documentRange; From 4670422416a5bf928e7d7918c9acdfa5448b2a1a Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 09:33:41 +0100 Subject: [PATCH 31/50] Complex condition expression as EPA --- CleanCode/src/CleanCode/CleanCode.csproj | 4 +- .../CleanCode/CleanCodeDaemonStageProcess.cs | 23 ------ .../ComplexConditionExpressionCheck.cs | 76 +++++++++++++++++++ ...ComplexConditionExpressionHighlighting.cs} | 20 ++--- .../ComplexExpressionCheck.cs | 41 ---------- .../CleanCode/Resources/Warnings.Designer.cs | 2 +- .../src/CleanCode/Resources/Warnings.resx | 2 +- 7 files changed, 90 insertions(+), 78 deletions(-) create mode 100644 CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs rename CleanCode/src/CleanCode/Features/ComplexExpression/{Highlighting.cs => ComplexConditionExpressionHighlighting.cs} (55%) delete mode 100644 CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index c5a4959..32973d5 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -173,8 +173,8 @@ - - + + diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index cc0abef..1e9275b 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -1,5 +1,4 @@ using System; -using CleanCode.Features.ComplexExpression; using CleanCode.Features.ExcessiveIndentation; using CleanCode.Features.FlagArguments; using CleanCode.Features.HollowNames; @@ -25,7 +24,6 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase private readonly TooManyDependenciesCheck tooManyDependenciesCheck; private readonly MethodNameNotMeaningfulCheck methodNamesNotMeaningfulCheck; private readonly FlagArgumentsCheck flagArgumentsCheck; - private readonly ComplexExpressionCheck complexExpressionCheck; private readonly HollowNamesCheck hollowNamesCheck; private readonly TooManyDeclarationsCheck tooManyDeclarationsCheck; @@ -41,7 +39,6 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); methodNamesNotMeaningfulCheck = new MethodNameNotMeaningfulCheck(settingsStore); flagArgumentsCheck = new FlagArgumentsCheck(settingsStore); - complexExpressionCheck = new ComplexExpressionCheck(settingsStore); hollowNamesCheck = new HollowNamesCheck(settingsStore); tooManyDeclarationsCheck = new TooManyDeclarationsCheck(settingsStore); } @@ -70,25 +67,5 @@ public override void VisitClassDeclaration(IClassDeclaration classDeclaration, I { hollowNamesCheck.ExecuteIfEnabled(classDeclaration, context); } - - public override void VisitIfStatement(IIfStatement ifStatementParam, IHighlightingConsumer context) - { - complexExpressionCheck.ExecuteIfEnabled(ifStatementParam.Condition, context); - } - - public override void VisitWhileStatement(IWhileStatement whileStatementParam, IHighlightingConsumer context) - { - complexExpressionCheck.ExecuteIfEnabled(whileStatementParam.Condition, context); - } - - public override void VisitForStatement(IForStatement forStatementParam, IHighlightingConsumer context) - { - complexExpressionCheck.ExecuteIfEnabled(forStatementParam.Condition, context); - } - - public override void VisitDoStatement(IDoStatement doStatementParam, IHighlightingConsumer context) - { - complexExpressionCheck.ExecuteIfEnabled(doStatementParam.Condition, context); - } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs new file mode 100644 index 0000000..fbeeba6 --- /dev/null +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs @@ -0,0 +1,76 @@ +using System.Linq; +using CleanCode.Settings; +using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; +using JetBrains.ReSharper.Feature.Services.Daemon; +using JetBrains.ReSharper.Psi.CSharp.Tree; +using JetBrains.ReSharper.Psi.Tree; + +namespace CleanCode.Features.ComplexExpression +{ + // TODO: This might be better working with IOperatorExpression + // Walk up from the operator to the highest containing expression + // and count depth? + [ElementProblemAnalyzer(typeof(IIfStatement), + typeof(ILoopWithConditionStatement), + typeof(IConditionalTernaryExpression), + typeof(IAssignmentExpression), + typeof(IExpressionInitializer), + HighlightingTypes = new[] + { + typeof(ComplexConditionExpressionHighlighting) + })] + public class ComplexConditionExpressionCheck : ElementProblemAnalyzer + { + protected override void Run(ICSharpTreeNode element, ElementProblemAnalyzerData data, + IHighlightingConsumer consumer) + { + var expression = GetExpression(element); + if (expression != null) + CheckExpression(expression, data, consumer); + } + + private static IExpression GetExpression(ITreeNode node) + { + // Covers for, while and do + var loopStatement = node as ILoopWithConditionStatement; + if (loopStatement != null) + return loopStatement.Condition; + + var ifStatement = node as IIfStatement; + if (ifStatement != null) + return ifStatement.Condition; + + var conditionalTernaryExpression = node as IConditionalTernaryExpression; + if (conditionalTernaryExpression != null) + return conditionalTernaryExpression.ConditionOperand; + + // TODO: Should these two be part of this check? + // Perhaps they should also check the type of the resulting + // variable to be bool? + var assignmentExpression = node as IAssignmentExpression; + if (assignmentExpression != null) + return assignmentExpression.Source; + + var expressionInitializer = node as IExpressionInitializer; + if (expressionInitializer != null) + return expressionInitializer.Value; + + return null; + } + + private static void CheckExpression(IExpression expression, ElementProblemAnalyzerData data, + IHighlightingConsumer consumer) + { + var maxExpressions = data.SettingsStore.GetValue((CleanCodeSettings s) => s.ComplexExpressionMaximum); + var expressionCount = expression.GetChildrenRecursive().Count(); + + if (expressionCount > maxExpressions) + { + var documentRange = expression.GetDocumentRange(); + var highlighting = new ComplexConditionExpressionHighlighting(documentRange); + consumer.AddHighlighting(highlighting); + } + } + } +} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs similarity index 55% rename from CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs rename to CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs index 70e6772..5d7b531 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs @@ -1,25 +1,25 @@ +using CleanCode; using CleanCode.Features.ComplexExpression; +using CleanCode.Resources; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; -[assembly:RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Expression Too Complex", "The expression contains too complex.", +[assembly:RegisterConfigurableSeverity(ComplexConditionExpressionHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Condition expression too complex", "The expression in the condition is too complex.", Severity.WARNING, false)] namespace CleanCode.Features.ComplexExpression { - [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting + public class ComplexConditionExpressionHighlighting : IHighlighting { - internal const string SeverityID = "ComplexExpression"; - private readonly string tooltip; + internal const string SeverityID = "ComplexConditionExpression"; + private readonly DocumentRange documentRange; - public Highlighting(string toolTip, DocumentRange documentRange) + public ComplexConditionExpressionHighlighting(DocumentRange documentRange) { - tooltip = toolTip; this.documentRange = documentRange; } @@ -30,12 +30,12 @@ public DocumentRange CalculateRange() public string ToolTip { - get { return tooltip; } + get { return Warnings.ExpressionTooComplex; } } public string ErrorStripeToolTip { - get { return tooltip; } + get { return ToolTip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs deleted file mode 100644 index b0eee83..0000000 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexExpressionCheck.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Linq; -using CleanCode.Resources; -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.ReSharper.Feature.Services.Daemon; -using JetBrains.ReSharper.Psi.CSharp.Tree; -using JetBrains.ReSharper.Psi.Tree; - -namespace CleanCode.Features.ComplexExpression -{ - public class ComplexExpressionCheck : MonoValueCheck - { - public ComplexExpressionCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override int Value - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ComplexExpressionMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ComplexExpressionEnabled); } - } - - protected override void ExecuteCore(IExpression constructorDeclaration, IHighlightingConsumer consumer) - { - var maxExpressions = Value; - var depth = constructorDeclaration.GetChildrenRecursive().Count(); - - if (depth > maxExpressions) - { - var documentRange = constructorDeclaration.GetDocumentRange(); - var highlighting = new ExcessiveIndentation.Highlighting(Warnings.ExpressionTooComplex, documentRange); - consumer.AddHighlighting(highlighting); - } - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs index f38bc25..2c4fc3b 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs @@ -88,7 +88,7 @@ public static string ExcessiveDepth { } /// - /// Looks up a localized string similar to This expression is too complex to be legible. Please, simplify it.. + /// Looks up a localized string similar to This expression is too complex.. /// public static string ExpressionTooComplex { get { diff --git a/CleanCode/src/CleanCode/Resources/Warnings.resx b/CleanCode/src/CleanCode/Resources/Warnings.resx index 8c96f76..1479384 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.resx +++ b/CleanCode/src/CleanCode/Resources/Warnings.resx @@ -145,7 +145,7 @@ This argument is used as a flag in the method. It usually means that the method has more than one responsibility. - This expression is too complex to be legible. Please, simplify it. + This expression is too complex. The usage of the suffix '{0}' is discouraged because it's too generic. Please, choose a meaningful name instead to clarify its intent and responsibilities. From 0034c81cae400e235f60c37673da07fb5e8e6035 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 09:37:11 +0100 Subject: [PATCH 32/50] Excessive indent as EPA --- CleanCode/src/CleanCode/CleanCode.csproj | 2 +- .../CleanCode/CleanCodeDaemonStageProcess.cs | 4 --- ...ting.cs => ExcessiveIndentHighlighting.cs} | 16 ++++----- .../ExcessiveIndentationCheck.cs | 34 +++++++------------ 4 files changed, 21 insertions(+), 35 deletions(-) rename CleanCode/src/CleanCode/Features/ExcessiveIndentation/{Highlighting.cs => ExcessiveIndentHighlighting.cs} (63%) diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index 32973d5..4803dd6 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -175,7 +175,7 @@ - + Code diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 1e9275b..c8b29fc 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -1,5 +1,4 @@ using System; -using CleanCode.Features.ExcessiveIndentation; using CleanCode.Features.FlagArguments; using CleanCode.Features.HollowNames; using CleanCode.Features.MethodNameNotMeaningful; @@ -20,7 +19,6 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase private readonly IContextBoundSettingsStore settingsStore; private readonly MethodTooLongCheck methodTooLongCheck; private readonly TooManyMethodArgumentsCheck tooManyArgumentsCheck; - private readonly ExcessiveIndentationCheck excessiveIndentationCheck; private readonly TooManyDependenciesCheck tooManyDependenciesCheck; private readonly MethodNameNotMeaningfulCheck methodNamesNotMeaningfulCheck; private readonly FlagArgumentsCheck flagArgumentsCheck; @@ -35,7 +33,6 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil // TODO: This is starting to feel like a beach of Benidorm in July. Refactoring needed. methodTooLongCheck = new MethodTooLongCheck(settingsStore); tooManyArgumentsCheck = new TooManyMethodArgumentsCheck(settingsStore); - excessiveIndentationCheck = new ExcessiveIndentationCheck(settingsStore); tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); methodNamesNotMeaningfulCheck = new MethodNameNotMeaningfulCheck(settingsStore); flagArgumentsCheck = new FlagArgumentsCheck(settingsStore); @@ -52,7 +49,6 @@ public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration { methodTooLongCheck.ExecuteIfEnabled(methodDeclaration, context); tooManyArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); - excessiveIndentationCheck.ExecuteIfEnabled(methodDeclaration, context); methodNamesNotMeaningfulCheck.ExecuteIfEnabled(methodDeclaration, context); flagArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); tooManyDeclarationsCheck.ExecuteIfEnabled(methodDeclaration, context); diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs similarity index 63% rename from CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs rename to CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs index 04ddc71..d3dd420 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs @@ -1,24 +1,24 @@ +using CleanCode; using CleanCode.Features.ExcessiveIndentation; +using CleanCode.Resources; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; -[assembly:RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Excessive Depth", "The nesting in this method is excessive.", +[assembly:RegisterConfigurableSeverity(ExcessiveIndentHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Excessive indentation", "The nesting in this method is excessive.", Severity.WARNING, false)] namespace CleanCode.Features.ExcessiveIndentation { [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting + public class ExcessiveIndentHighlighting : IHighlighting { internal const string SeverityID = "ExcessiveIndentation"; - private readonly string tooltip; private readonly DocumentRange documentRange; - public Highlighting(string toolTip, DocumentRange documentRange) + public ExcessiveIndentHighlighting(DocumentRange documentRange) { - tooltip = toolTip; this.documentRange = documentRange; } @@ -29,12 +29,12 @@ public DocumentRange CalculateRange() public string ToolTip { - get { return tooltip; } + get { return Warnings.ExcessiveDepth; } } public string ErrorStripeToolTip { - get { return tooltip; } + get { return ToolTip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs index 450524c..f5f1b3d 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs @@ -1,40 +1,30 @@ -using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; namespace CleanCode.Features.ExcessiveIndentation { - public class ExcessiveIndentationCheck : MonoValueCheck - { - public ExcessiveIndentationCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) + [ElementProblemAnalyzer(typeof(IMethodDeclaration), + HighlightingTypes = new [] { - } - - protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, IHighlightingConsumer consumer) + typeof(ExcessiveIndentHighlighting) + })] + public class ExcessiveIndentationCheck : ElementProblemAnalyzer + { + protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var maxIndentation = Value; - var depth = constructorDeclaration.GetChildrenDepth(); + var maxIndentation = data.SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationMaximum); + var depth = element.GetChildrenDepth(); if (depth > maxIndentation) { - var documentRange = constructorDeclaration.GetNameDocumentRange(); - var highlighting = new Highlighting(Warnings.ExcessiveDepth, documentRange); + var documentRange = element.GetNameDocumentRange(); + var highlighting = new ExcessiveIndentHighlighting(documentRange); consumer.AddHighlighting(highlighting); } } - - protected override int Value - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.ExcessiveIndentationEnabled); } - } } } \ No newline at end of file From 241fe63f2106b85643040f03dc1a37e6680e85c7 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 09:41:53 +0100 Subject: [PATCH 33/50] FlagArgument as EPA --- CleanCode/src/CleanCode/CleanCode.csproj | 2 +- .../CleanCode/CleanCodeDaemonStageProcess.cs | 4 --- .../FlagArguments/FlagArgumentsCheck.cs | 35 ++++++++----------- ...ghting.cs => FlagArgumentsHighlighting.cs} | 17 +++++---- 4 files changed, 23 insertions(+), 35 deletions(-) rename CleanCode/src/CleanCode/Features/FlagArguments/{Highlighting.cs => FlagArgumentsHighlighting.cs} (62%) diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index 4803dd6..b5bc95c 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -183,7 +183,7 @@ Code - + diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index c8b29fc..fb77468 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -1,5 +1,4 @@ using System; -using CleanCode.Features.FlagArguments; using CleanCode.Features.HollowNames; using CleanCode.Features.MethodNameNotMeaningful; using CleanCode.Features.MethodTooLong; @@ -21,7 +20,6 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase private readonly TooManyMethodArgumentsCheck tooManyArgumentsCheck; private readonly TooManyDependenciesCheck tooManyDependenciesCheck; private readonly MethodNameNotMeaningfulCheck methodNamesNotMeaningfulCheck; - private readonly FlagArgumentsCheck flagArgumentsCheck; private readonly HollowNamesCheck hollowNamesCheck; private readonly TooManyDeclarationsCheck tooManyDeclarationsCheck; @@ -35,7 +33,6 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil tooManyArgumentsCheck = new TooManyMethodArgumentsCheck(settingsStore); tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); methodNamesNotMeaningfulCheck = new MethodNameNotMeaningfulCheck(settingsStore); - flagArgumentsCheck = new FlagArgumentsCheck(settingsStore); hollowNamesCheck = new HollowNamesCheck(settingsStore); tooManyDeclarationsCheck = new TooManyDeclarationsCheck(settingsStore); } @@ -50,7 +47,6 @@ public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration methodTooLongCheck.ExecuteIfEnabled(methodDeclaration, context); tooManyArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); methodNamesNotMeaningfulCheck.ExecuteIfEnabled(methodDeclaration, context); - flagArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); tooManyDeclarationsCheck.ExecuteIfEnabled(methodDeclaration, context); } diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs index a35bdae..cb97d11 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsCheck.cs @@ -1,44 +1,35 @@ using System.Linq; -using CleanCode.Resources; -using CleanCode.Settings; -using JetBrains.Application.Settings; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; using System.Collections.Generic; using System.Diagnostics; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.Util; namespace CleanCode.Features.FlagArguments { - public class FlagArgumentsCheck : Check - { - public FlagArgumentsCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) + [ElementProblemAnalyzer(typeof(IMethodDeclaration), + HighlightingTypes = new [] { - } - - protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, IHighlightingConsumer consumer) + typeof(FlagArgumentsHighlighting) + })] + public class FlagArgumentsCheck : ElementProblemAnalyzer + { + protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var parameterDeclarations = constructorDeclaration.ParameterDeclarations; + var parameterDeclarations = element.ParameterDeclarations; foreach (var parameterDeclaration in parameterDeclarations) { - if (IsFlagArgument(parameterDeclaration, constructorDeclaration.Body)) + if (IsFlagArgument(parameterDeclaration, element.Body)) { AddHighlighting(consumer, parameterDeclaration); } } } - private static void AddHighlighting(IHighlightingConsumer consumer, ICSharpParameterDeclaration parameterDeclaration) - { - var documentRange = parameterDeclaration.GetDocumentRange(); - var highlighting = new Highlighting(Warnings.FlagArgument, documentRange); - consumer.AddHighlighting(highlighting); - } - private static bool IsFlagArgument(ITypeOwnerDeclaration typeOwnerDeclaration, ITreeNode node) { if (IsOfTypeThatCanBeUsedAsFlag(typeOwnerDeclaration)) @@ -88,9 +79,11 @@ private static bool IsReferenceToArgument(IReferenceExpression referenceExpressi return declaredElement.ShortName == toFind.ShortName; } - protected override bool IsEnabled + private static void AddHighlighting(IHighlightingConsumer consumer, ICSharpParameterDeclaration parameterDeclaration) { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.FlagArgumentsEnabled); } + var documentRange = parameterDeclaration.GetDocumentRange(); + var highlighting = new FlagArgumentsHighlighting(documentRange); + consumer.AddHighlighting(highlighting); } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs similarity index 62% rename from CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs rename to CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs index 1ecd3df..eac3912 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs @@ -1,24 +1,23 @@ using CleanCode.Features.FlagArguments; +using CleanCode.Resources; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Flag Argument", "An argument that is used as a flag.", +[assembly: RegisterConfigurableSeverity(FlagArgumentsHighlighting.SeverityID, null, + HighlightingGroupIds.CodeSmell, "Flag argument", "An argument that is used as a flag.", Severity.WARNING, false)] namespace CleanCode.Features.FlagArguments { [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting + public class FlagArgumentsHighlighting : IHighlighting { - internal const string SeverityID = "FlagArguments"; - private readonly string tooltip; + internal const string SeverityID = "FlagArgument"; private readonly DocumentRange documentRange; - public Highlighting(string toolTip, DocumentRange documentRange) + public FlagArgumentsHighlighting(DocumentRange documentRange) { - tooltip = toolTip; this.documentRange = documentRange; } @@ -29,12 +28,12 @@ public DocumentRange CalculateRange() public string ToolTip { - get { return tooltip; } + get { return Warnings.FlagArgument; } } public string ErrorStripeToolTip { - get { return tooltip; } + get { return ToolTip; } } public bool IsValid() From 98b046e53cd46b9126552cf9ae1107a55610885c Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 09:45:29 +0100 Subject: [PATCH 34/50] HollowTypeName as EPA --- CleanCode/src/CleanCode/CleanCode.csproj | 2 +- .../CleanCode/CleanCodeDaemonStageProcess.cs | 8 ---- .../Features/HollowNames/HollowNamesCheck.cs | 46 +++++++------------ ...hting.cs => HollowTypeNameHighlighting.cs} | 9 ++-- 4 files changed, 22 insertions(+), 43 deletions(-) rename CleanCode/src/CleanCode/Features/HollowNames/{Highlighting.cs => HollowTypeNameHighlighting.cs} (71%) diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index b5bc95c..0d98d21 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -185,7 +185,7 @@ - + diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index fb77468..291e06f 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -1,5 +1,4 @@ using System; -using CleanCode.Features.HollowNames; using CleanCode.Features.MethodNameNotMeaningful; using CleanCode.Features.MethodTooLong; using CleanCode.Features.TooManyDeclarations; @@ -20,7 +19,6 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase private readonly TooManyMethodArgumentsCheck tooManyArgumentsCheck; private readonly TooManyDependenciesCheck tooManyDependenciesCheck; private readonly MethodNameNotMeaningfulCheck methodNamesNotMeaningfulCheck; - private readonly HollowNamesCheck hollowNamesCheck; private readonly TooManyDeclarationsCheck tooManyDeclarationsCheck; public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile file, IContextBoundSettingsStore settingsStore) @@ -33,7 +31,6 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil tooManyArgumentsCheck = new TooManyMethodArgumentsCheck(settingsStore); tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); methodNamesNotMeaningfulCheck = new MethodNameNotMeaningfulCheck(settingsStore); - hollowNamesCheck = new HollowNamesCheck(settingsStore); tooManyDeclarationsCheck = new TooManyDeclarationsCheck(settingsStore); } @@ -54,10 +51,5 @@ public override void VisitConstructorDeclaration(IConstructorDeclaration constru { tooManyDependenciesCheck.ExecuteIfEnabled(constructorDeclaration, context); } - - public override void VisitClassDeclaration(IClassDeclaration classDeclaration, IHighlightingConsumer context) - { - hollowNamesCheck.ExecuteIfEnabled(classDeclaration, context); - } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs index f59a0d2..2684f8e 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs @@ -4,37 +4,33 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; -using IContextBoundSettingsStore = JetBrains.Application.Settings.IContextBoundSettingsStore; namespace CleanCode.Features.HollowNames { - public class HollowNamesCheck : MonoValueCheck - { - private const string Separator = ","; - - public HollowNamesCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) + [ElementProblemAnalyzer(typeof(IClassDeclaration), + HighlightingTypes = new [] { - } - - protected override void ExecuteCore(IClassDeclaration constructorDeclaration, IHighlightingConsumer consumer) + typeof(HollowTypeNameHighlighting) + })] + public class HollowNamesCheck : ElementProblemAnalyzer + { + protected override void Run(IClassDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var suffixes = GetSuffixes(); - - var match = GetFirstMatchOrDefault(constructorDeclaration.DeclaredName, suffixes); + var suffixes = GetSuffixes(data.SettingsStore); + var match = GetFirstMatchOrDefault(element.DeclaredName, suffixes); if (match != null) - { - AddHightlightning(match, consumer, constructorDeclaration); - } + AddHighlighting(match, consumer, element); } - private IEnumerable GetSuffixes() + private IEnumerable GetSuffixes(IContextBoundSettingsStore dataSettingsStore) { - return Value.Split(new[] { Separator }, StringSplitOptions.RemoveEmptyEntries); + var suffixes = dataSettingsStore.GetValue((CleanCodeSettings s) => s.HollowTypeNameString); + return suffixes.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); } private static string GetFirstMatchOrDefault(string declaredName, IEnumerable suffixes) @@ -42,22 +38,12 @@ private static string GetFirstMatchOrDefault(string declaredName, IEnumerable s.HollowTypeNameEnabled); } - } - - protected override string Value - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.HollowTypeNameString); } - } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs b/CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs similarity index 71% rename from CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs rename to CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs index a4762c4..e512824 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs @@ -1,22 +1,23 @@ +using CleanCode; using CleanCode.Features.HollowNames; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Hollow Type Name", "This type has a name that doesn't express its intent.", +[assembly: RegisterConfigurableSeverity(HollowTypeNameHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Hollow type name", "This type has a name that doesn't express its intent.", Severity.SUGGESTION, false)] namespace CleanCode.Features.HollowNames { [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting + public class HollowTypeNameHighlighting : IHighlighting { internal const string SeverityID = "HollowTypeName"; private readonly string tooltip; private readonly DocumentRange documentRange; - public Highlighting(string toolTip, DocumentRange documentRange) + public HollowTypeNameHighlighting(string toolTip, DocumentRange documentRange) { tooltip = toolTip; this.documentRange = documentRange; From a1cde87bf15f8ea8c3c4f446ffc59ccfa2203371 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 09:48:47 +0100 Subject: [PATCH 35/50] MethodNameNotMeaningul as EPA --- CleanCode/src/CleanCode/CleanCode.csproj | 2 +- .../CleanCode/CleanCodeDaemonStageProcess.cs | 4 -- .../MethodNameNotMeaningfulCheck.cs | 42 +++++++------------ ...=> MethodNameNotMeaningfulHighlighting.cs} | 19 ++++----- 4 files changed, 25 insertions(+), 42 deletions(-) rename CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/{Highlighting.cs => MethodNameNotMeaningfulHighlighting.cs} (56%) diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index 0d98d21..d2637b1 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -187,7 +187,7 @@ - + Code diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 291e06f..c39f61f 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -1,5 +1,4 @@ using System; -using CleanCode.Features.MethodNameNotMeaningful; using CleanCode.Features.MethodTooLong; using CleanCode.Features.TooManyDeclarations; using CleanCode.Features.TooManyDependencies; @@ -18,7 +17,6 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase private readonly MethodTooLongCheck methodTooLongCheck; private readonly TooManyMethodArgumentsCheck tooManyArgumentsCheck; private readonly TooManyDependenciesCheck tooManyDependenciesCheck; - private readonly MethodNameNotMeaningfulCheck methodNamesNotMeaningfulCheck; private readonly TooManyDeclarationsCheck tooManyDeclarationsCheck; public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile file, IContextBoundSettingsStore settingsStore) @@ -30,7 +28,6 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil methodTooLongCheck = new MethodTooLongCheck(settingsStore); tooManyArgumentsCheck = new TooManyMethodArgumentsCheck(settingsStore); tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); - methodNamesNotMeaningfulCheck = new MethodNameNotMeaningfulCheck(settingsStore); tooManyDeclarationsCheck = new TooManyDeclarationsCheck(settingsStore); } @@ -43,7 +40,6 @@ public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration { methodTooLongCheck.ExecuteIfEnabled(methodDeclaration, context); tooManyArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); - methodNamesNotMeaningfulCheck.ExecuteIfEnabled(methodDeclaration, context); tooManyDeclarationsCheck.ExecuteIfEnabled(methodDeclaration, context); } diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs index 8dd6f15..724e869 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs @@ -1,46 +1,34 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; namespace CleanCode.Features.MethodNameNotMeaningful { - public class MethodNameNotMeaningfulCheck : MonoValueCheck + [ElementProblemAnalyzer(typeof(IMethodDeclaration), HighlightingTypes = new [] { - public MethodNameNotMeaningfulCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, IHighlightingConsumer consumer) + typeof(MethodNameNotMeaningfulHighlighting) + })] + public class MethodNameNotMeaningfulCheck : ElementProblemAnalyzer + { + protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var minimumMethodNameLenght = Value; - - if (constructorDeclaration.NameIdentifier == null) - { + if (element.NameIdentifier == null) return; - } - var name = constructorDeclaration.NameIdentifier.GetText(); - var methodNameLenght = name.Length; - if (methodNameLenght < minimumMethodNameLenght) + var minimumMethodNameLength = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimum); + + var name = element.NameIdentifier.GetText(); + var methodNameLength = name.Length; + if (methodNameLength < minimumMethodNameLength) { - var documentRange = constructorDeclaration.GetNameDocumentRange(); - var highlighting = new Highlighting(Warnings.MethodNameNotMeaningful, documentRange); + var documentRange = element.GetNameDocumentRange(); + var highlighting = new MethodNameNotMeaningfulHighlighting(documentRange); consumer.AddHighlighting(highlighting); } } - - protected override int Value - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimumEnabled); } - } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs similarity index 56% rename from CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs rename to CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs index 0c12352..a30201d 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs @@ -1,25 +1,24 @@ using CleanCode.Features.MethodNameNotMeaningful; +using CleanCode.Resources; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Method Name Not Meaningful", - "This method name is to short to be meaningful. Please, choose a better name that describes its intent.", +[assembly: RegisterConfigurableSeverity(MethodNameNotMeaningfulHighlighting.SeverityID, null, + HighlightingGroupIds.CodeSmell, "Method name not meaningful", + "This method name is too short to be meaningful.", Severity.WARNING, false)] namespace CleanCode.Features.MethodNameNotMeaningful { [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting + public class MethodNameNotMeaningfulHighlighting : IHighlighting { - internal const string SeverityID = "MethodNamesNotMeaningful"; - private readonly string tooltip; + internal const string SeverityID = "MethodNameNotMeaningful"; private readonly DocumentRange documentRange; - public Highlighting(string toolTip, DocumentRange documentRange) + public MethodNameNotMeaningfulHighlighting(DocumentRange documentRange) { - tooltip = toolTip; this.documentRange = documentRange; } @@ -30,12 +29,12 @@ public DocumentRange CalculateRange() public string ToolTip { - get { return tooltip; } + get { return Warnings.MethodNameNotMeaningful; } } public string ErrorStripeToolTip { - get { return tooltip; } + get { return ToolTip; } } public bool IsValid() From 20e501d3c3d3562d11d7ea13e3802b9f4b0d5659 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 09:52:45 +0100 Subject: [PATCH 36/50] MethodTooLong as EPA --- CleanCode/src/CleanCode/CleanCode.csproj | 2 +- .../CleanCode/CleanCodeDaemonStageProcess.cs | 4 --- .../MethodTooLong/MethodTooLongCheck.cs | 31 ++++++------------- ...ghting.cs => MethodTooLongHighlighting.cs} | 16 +++++----- .../TooManyDeclarationsCheck.cs | 2 +- .../CleanCode/Resources/Warnings.Designer.cs | 18 +++++------ .../src/CleanCode/Resources/Warnings.resx | 4 +-- 7 files changed, 31 insertions(+), 46 deletions(-) rename CleanCode/src/CleanCode/Features/MethodTooLong/{Highlighting.cs => MethodTooLongHighlighting.cs} (63%) diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index d2637b1..97eac75 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -189,7 +189,7 @@ - + Code diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index c39f61f..c432fbf 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -1,5 +1,4 @@ using System; -using CleanCode.Features.MethodTooLong; using CleanCode.Features.TooManyDeclarations; using CleanCode.Features.TooManyDependencies; using CleanCode.Features.TooManyMethodArguments; @@ -14,7 +13,6 @@ namespace CleanCode public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase { private readonly IContextBoundSettingsStore settingsStore; - private readonly MethodTooLongCheck methodTooLongCheck; private readonly TooManyMethodArgumentsCheck tooManyArgumentsCheck; private readonly TooManyDependenciesCheck tooManyDependenciesCheck; private readonly TooManyDeclarationsCheck tooManyDeclarationsCheck; @@ -25,7 +23,6 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil this.settingsStore = settingsStore; // TODO: This is starting to feel like a beach of Benidorm in July. Refactoring needed. - methodTooLongCheck = new MethodTooLongCheck(settingsStore); tooManyArgumentsCheck = new TooManyMethodArgumentsCheck(settingsStore); tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); tooManyDeclarationsCheck = new TooManyDeclarationsCheck(settingsStore); @@ -38,7 +35,6 @@ public override void Execute(Action commiter) public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration, IHighlightingConsumer context) { - methodTooLongCheck.ExecuteIfEnabled(methodDeclaration, context); tooManyArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); tooManyDeclarationsCheck.ExecuteIfEnabled(methodDeclaration, context); } diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs index 1e071eb..7eaa1b0 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs @@ -1,39 +1,28 @@ -using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; namespace CleanCode.Features.MethodTooLong { - public class MethodTooLongCheck : MonoValueCheck + [ElementProblemAnalyzer(typeof(IMethodDeclaration), HighlightingTypes = new [] { - public MethodTooLongCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, IHighlightingConsumer consumer) + typeof(MethodTooLongHighlighting) + })] + public class MethodTooLongCheck : ElementProblemAnalyzer + { + protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var maxLength = Value; + var maxLength = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongMaximum); - var statementCount = constructorDeclaration.CountChildren(); + var statementCount = element.CountChildren(); if (statementCount > maxLength) { - var highlighting = new Highlighting(Warnings.Warning_MethodTooLong, constructorDeclaration.GetNameDocumentRange()); + var highlighting = new MethodTooLongHighlighting(element.GetNameDocumentRange()); consumer.AddHighlighting(highlighting); } } - - protected override int Value - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongEnabled); } - } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs similarity index 63% rename from CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs rename to CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs index 2d6d95e..c44924a 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs @@ -1,24 +1,24 @@ +using CleanCode; using CleanCode.Features.MethodTooLong; +using CleanCode.Resources; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Method Too Long", "The method is bigger than it should be.", +[assembly: RegisterConfigurableSeverity(MethodTooLongHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Method too long", "The method is bigger than it should be.", Severity.SUGGESTION, false)] namespace CleanCode.Features.MethodTooLong { [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting + public class MethodTooLongHighlighting : IHighlighting { internal const string SeverityID = "MethodTooLong"; - private readonly string tooltip; private readonly DocumentRange documentRange; - public Highlighting(string toolTip, DocumentRange documentRange) + public MethodTooLongHighlighting(DocumentRange documentRange) { - tooltip = toolTip; this.documentRange = documentRange; } @@ -29,12 +29,12 @@ public DocumentRange CalculateRange() public string ToolTip { - get { return tooltip; } + get { return Warnings.MethodTooLong; } } public string ErrorStripeToolTip { - get { return tooltip; } + get { return ToolTip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs index 5db2fa5..868cb0e 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs @@ -21,7 +21,7 @@ protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, I var statementCount = constructorDeclaration.CountChildren(); if (statementCount > maxLength) { - var highlighting = new MethodTooLong.Highlighting(Warnings.Warning_TooManyDeclarations, + var highlighting = new Highlighting(Warnings.Warning_TooManyDeclarations, constructorDeclaration.GetNameDocumentRange()); consumer.AddHighlighting(highlighting); } diff --git a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs index 2c4fc3b..c7b4061 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs @@ -133,29 +133,29 @@ public static string MethodNameNotMeaningful { } /// - /// Looks up a localized string similar to There are too many interfaces being passed in to this constructor. You might be violating SRP.. + /// Looks up a localized string similar to This method is too long.. /// - public static string TooManyDependencies { + public static string MethodTooLong { get { - return ResourceManager.GetString("TooManyDependencies", resourceCulture); + return ResourceManager.GetString("MethodTooLong", resourceCulture); } } /// - /// Looks up a localized string similar to This method requires too many arguments.. + /// Looks up a localized string similar to There are too many interfaces being passed in to this constructor. You might be violating SRP.. /// - public static string TooManyMethodArguments { + public static string TooManyDependencies { get { - return ResourceManager.GetString("TooManyMethodArguments", resourceCulture); + return ResourceManager.GetString("TooManyDependencies", resourceCulture); } } /// - /// Looks up a localized string similar to This method contains too many statements.. + /// Looks up a localized string similar to This method requires too many arguments.. /// - public static string Warning_MethodTooLong { + public static string TooManyMethodArguments { get { - return ResourceManager.GetString("Warning_MethodTooLong", resourceCulture); + return ResourceManager.GetString("TooManyMethodArguments", resourceCulture); } } diff --git a/CleanCode/src/CleanCode/Resources/Warnings.resx b/CleanCode/src/CleanCode/Resources/Warnings.resx index 1479384..73fd1e7 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.resx +++ b/CleanCode/src/CleanCode/Resources/Warnings.resx @@ -123,8 +123,8 @@ This method requires too many arguments. - - This method contains too many statements. + + This method is too long. Excessive depth of nested code blocks. From 24dc24998778a1af5210c97b620666147c809519 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 09:58:22 +0100 Subject: [PATCH 37/50] Merge method too long checks --- CleanCode/src/CleanCode/CleanCode.csproj | 2 - .../CleanCode/CleanCodeDaemonStageProcess.cs | 4 -- .../MethodTooLong/MethodTooLongCheck.cs | 13 ++++-- .../TooManyDeclarations/Highlighting.cs | 45 ------------------- .../TooManyDeclarationsCheck.cs | 40 ----------------- 5 files changed, 9 insertions(+), 95 deletions(-) delete mode 100644 CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs delete mode 100644 CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index 97eac75..aeaa754 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -194,8 +194,6 @@ - - Code diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index c432fbf..6edb014 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -1,5 +1,4 @@ using System; -using CleanCode.Features.TooManyDeclarations; using CleanCode.Features.TooManyDependencies; using CleanCode.Features.TooManyMethodArguments; using JetBrains.Application.Settings; @@ -15,7 +14,6 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase private readonly IContextBoundSettingsStore settingsStore; private readonly TooManyMethodArgumentsCheck tooManyArgumentsCheck; private readonly TooManyDependenciesCheck tooManyDependenciesCheck; - private readonly TooManyDeclarationsCheck tooManyDeclarationsCheck; public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile file, IContextBoundSettingsStore settingsStore) : base(daemonProcess, file) @@ -25,7 +23,6 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil // TODO: This is starting to feel like a beach of Benidorm in July. Refactoring needed. tooManyArgumentsCheck = new TooManyMethodArgumentsCheck(settingsStore); tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); - tooManyDeclarationsCheck = new TooManyDeclarationsCheck(settingsStore); } public override void Execute(Action commiter) @@ -36,7 +33,6 @@ public override void Execute(Action commiter) public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration, IHighlightingConsumer context) { tooManyArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); - tooManyDeclarationsCheck.ExecuteIfEnabled(methodDeclaration, context); } public override void VisitConstructorDeclaration(IConstructorDeclaration constructorDeclaration, IHighlightingConsumer context) diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs index 7eaa1b0..7b15a8c 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs @@ -15,14 +15,19 @@ public class MethodTooLongCheck : ElementProblemAnalyzer { protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var maxLength = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongMaximum); + var maxStatements = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongMaximum); + var maxDeclarations = data.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDeclarationsMaximum); var statementCount = element.CountChildren(); - if (statementCount > maxLength) + if (statementCount <= maxStatements) { - var highlighting = new MethodTooLongHighlighting(element.GetNameDocumentRange()); - consumer.AddHighlighting(highlighting); + var declarationCount = element.CountChildren(); + if (declarationCount <= maxDeclarations) + return; } + + var highlighting = new MethodTooLongHighlighting(element.GetNameDocumentRange()); + consumer.AddHighlighting(highlighting); } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs b/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs deleted file mode 100644 index 293ba95..0000000 --- a/CleanCode/src/CleanCode/Features/TooManyDeclarations/Highlighting.cs +++ /dev/null @@ -1,45 +0,0 @@ -using CleanCode.Features.TooManyDeclarations; -using JetBrains.DocumentModel; -using JetBrains.ReSharper.Feature.Services.Daemon; -using JetBrains.ReSharper.Psi.CSharp; - -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Method Too Long", "The method is bigger than it should be.", - Severity.SUGGESTION, false)] - -namespace CleanCode.Features.TooManyDeclarations -{ - [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting - { - internal const string SeverityID = "MethodTooLong"; - private readonly string tooltip; - private readonly DocumentRange documentRange; - - public Highlighting(string toolTip, DocumentRange documentRange) - { - tooltip = toolTip; - this.documentRange = documentRange; - } - - public DocumentRange CalculateRange() - { - return documentRange; - } - - public string ToolTip - { - get { return tooltip; } - } - - public string ErrorStripeToolTip - { - get { return tooltip; } - } - - public bool IsValid() - { - return true; - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs deleted file mode 100644 index 868cb0e..0000000 --- a/CleanCode/src/CleanCode/Features/TooManyDeclarations/TooManyDeclarationsCheck.cs +++ /dev/null @@ -1,40 +0,0 @@ -using CleanCode.Resources; -using CleanCode.Settings; -using JetBrains.Application.Settings; -using JetBrains.ReSharper.Feature.Services.Daemon; -using JetBrains.ReSharper.Psi.CSharp.Tree; -using JetBrains.ReSharper.Psi.Tree; - -namespace CleanCode.Features.TooManyDeclarations -{ - public class TooManyDeclarationsCheck : MonoValueCheck - { - public TooManyDeclarationsCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, IHighlightingConsumer consumer) - { - var maxLength = Value; - - var statementCount = constructorDeclaration.CountChildren(); - if (statementCount > maxLength) - { - var highlighting = new Highlighting(Warnings.Warning_TooManyDeclarations, - constructorDeclaration.GetNameDocumentRange()); - consumer.AddHighlighting(highlighting); - } - } - - protected override int Value - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDeclarationsMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDeclarationsEnabled); } - } - } -} \ No newline at end of file From 8ccc7822f37d101e91405b875037bcef25d0914d Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 10:01:36 +0100 Subject: [PATCH 38/50] TooManyDependencies as EPA --- .../CleanCode/CleanCodeDaemonStageProcess.cs | 8 ----- .../TooManyDependenciesCheck.cs | 33 ++++++------------- ....cs => TooManyDependenciesHighlighting.cs} | 16 ++++----- .../CleanCode/Resources/Warnings.Designer.cs | 2 +- .../src/CleanCode/Resources/Warnings.resx | 2 +- 5 files changed, 20 insertions(+), 41 deletions(-) rename CleanCode/src/CleanCode/Features/TooManyDependencies/{Highlighting.cs => TooManyDependenciesHighlighting.cs} (62%) diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs index 6edb014..6dc0fe0 100644 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs @@ -1,5 +1,4 @@ using System; -using CleanCode.Features.TooManyDependencies; using CleanCode.Features.TooManyMethodArguments; using JetBrains.Application.Settings; using JetBrains.ReSharper.Daemon.CSharp.Stages; @@ -13,7 +12,6 @@ public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase { private readonly IContextBoundSettingsStore settingsStore; private readonly TooManyMethodArgumentsCheck tooManyArgumentsCheck; - private readonly TooManyDependenciesCheck tooManyDependenciesCheck; public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile file, IContextBoundSettingsStore settingsStore) : base(daemonProcess, file) @@ -22,7 +20,6 @@ public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile fil // TODO: This is starting to feel like a beach of Benidorm in July. Refactoring needed. tooManyArgumentsCheck = new TooManyMethodArgumentsCheck(settingsStore); - tooManyDependenciesCheck = new TooManyDependenciesCheck(settingsStore); } public override void Execute(Action commiter) @@ -34,10 +31,5 @@ public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration { tooManyArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); } - - public override void VisitConstructorDeclaration(IConstructorDeclaration constructorDeclaration, IHighlightingConsumer context) - { - tooManyDependenciesCheck.ExecuteIfEnabled(constructorDeclaration, context); - } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs index 406c23f..b953203 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs @@ -1,7 +1,7 @@ using System.Linq; -using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; @@ -9,39 +9,26 @@ namespace CleanCode.Features.TooManyDependencies { - public class TooManyDependenciesCheck : MonoValueCheck + [ElementProblemAnalyzer(typeof(IConstructorDeclaration), HighlightingTypes = new [] { - public TooManyDependenciesCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override void ExecuteCore(IConstructorDeclaration constructorDeclaration, IHighlightingConsumer consumer) + typeof(TooManyDependenciesHighlighting) + })] + public class TooManyDependenciesCheck : ElementProblemAnalyzer + { + protected override void Run(IConstructorDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var maxDependencies = Value; + var maxDependencies = data.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximum); - var dependencies = constructorDeclaration.ParameterDeclarations.Select( + var dependencies = element.ParameterDeclarations.Select( declaration => declaration.DeclaredElement != null && declaration.DeclaredElement.Type.IsInterfaceType()); var dependenciesCount = dependencies.Count(); - if (dependenciesCount > maxDependencies) { - var highlighting = new Highlighting(Warnings.TooManyDependencies, - constructorDeclaration.GetNameDocumentRange()); + var highlighting = new TooManyDependenciesHighlighting(element.GetNameDocumentRange()); consumer.AddHighlighting(highlighting); } } - - protected override int Value - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDependenciesMaximumEnabled); } - } } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs similarity index 62% rename from CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs rename to CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs index e631393..2b60f29 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs @@ -1,24 +1,24 @@ +using CleanCode; using CleanCode.Features.TooManyDependencies; +using CleanCode.Resources; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Too Many Dependencies", "Too many dependencies passed into constructor.", +[assembly: RegisterConfigurableSeverity(TooManyDependenciesHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Too many dependencies", "Too many dependencies passed into constructor.", Severity.WARNING, false)] namespace CleanCode.Features.TooManyDependencies { [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting + public class TooManyDependenciesHighlighting : IHighlighting { internal const string SeverityID = "TooManyDependencies"; - private readonly string tooltip; private readonly DocumentRange documentRange; - public Highlighting(string toolTip, DocumentRange documentRange) + public TooManyDependenciesHighlighting(DocumentRange documentRange) { - tooltip = toolTip; this.documentRange = documentRange; } @@ -29,12 +29,12 @@ public DocumentRange CalculateRange() public string ToolTip { - get { return tooltip; } + get { return Warnings.TooManyDependencies; } } public string ErrorStripeToolTip { - get { return tooltip; } + get { return ToolTip; } } public bool IsValid() diff --git a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs index c7b4061..cc07a0f 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs @@ -142,7 +142,7 @@ public static string MethodTooLong { } /// - /// Looks up a localized string similar to There are too many interfaces being passed in to this constructor. You might be violating SRP.. + /// Looks up a localized string similar to There are too many interfaces being passed in to this constructor. You might be violating the Single Responsibility Principle.. /// public static string TooManyDependencies { get { diff --git a/CleanCode/src/CleanCode/Resources/Warnings.resx b/CleanCode/src/CleanCode/Resources/Warnings.resx index 73fd1e7..79e1e61 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.resx +++ b/CleanCode/src/CleanCode/Resources/Warnings.resx @@ -118,7 +118,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - There are too many interfaces being passed in to this constructor. You might be violating SRP. + There are too many interfaces being passed in to this constructor. You might be violating the Single Responsibility Principle. This method requires too many arguments. From 404623d93df5c231967417783e91dc7ca6d83c5a Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 10:04:31 +0100 Subject: [PATCH 39/50] Remove daemon stage --- CleanCode/src/CleanCode/CleanCode.csproj | 10 ++---- .../src/CleanCode/CleanCodeDaemonStage.cs | 17 --------- .../CleanCode/CleanCodeDaemonStageProcess.cs | 35 ------------------- .../MethodNameNotMeaningfulCheck.cs | 1 - ...ing.cs => TooManyArgumentsHighlighting.cs} | 9 ++--- .../TooManyMethodArgumentsCheck.cs | 32 ++++++----------- 6 files changed, 18 insertions(+), 86 deletions(-) delete mode 100644 CleanCode/src/CleanCode/CleanCodeDaemonStage.cs delete mode 100644 CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs rename CleanCode/src/CleanCode/Features/TooManyMethodArguments/{Highlighting.cs => TooManyArgumentsHighlighting.cs} (72%) diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index aeaa754..4f90651 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -177,12 +177,6 @@ - - Code - - - Code - @@ -194,12 +188,12 @@ - + Code - + Code diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs deleted file mode 100644 index 2776f7f..0000000 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStage.cs +++ /dev/null @@ -1,17 +0,0 @@ -using JetBrains.Application.Settings; -using JetBrains.ReSharper.Feature.Services.CSharp.Daemon; -using JetBrains.ReSharper.Feature.Services.Daemon; -using JetBrains.ReSharper.Psi.CSharp.Tree; - -namespace CleanCode -{ - [DaemonStage] - public class CleanCodeDaemonStage : CSharpDaemonStageBase - { - protected override IDaemonStageProcess CreateProcess(IDaemonProcess process, IContextBoundSettingsStore settings, - DaemonProcessKind processKind, ICSharpFile file) - { - return new CleanCodeDaemonStageProcess(process, file, settings); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs b/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs deleted file mode 100644 index 6dc0fe0..0000000 --- a/CleanCode/src/CleanCode/CleanCodeDaemonStageProcess.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using CleanCode.Features.TooManyMethodArguments; -using JetBrains.Application.Settings; -using JetBrains.ReSharper.Daemon.CSharp.Stages; -using JetBrains.ReSharper.Feature.Services.Daemon; -using JetBrains.ReSharper.Psi; -using JetBrains.ReSharper.Psi.CSharp.Tree; - -namespace CleanCode -{ - public class CleanCodeDaemonStageProcess : CSharpDaemonStageProcessBase - { - private readonly IContextBoundSettingsStore settingsStore; - private readonly TooManyMethodArgumentsCheck tooManyArgumentsCheck; - - public CleanCodeDaemonStageProcess(IDaemonProcess daemonProcess, ICSharpFile file, IContextBoundSettingsStore settingsStore) - : base(daemonProcess, file) - { - this.settingsStore = settingsStore; - - // TODO: This is starting to feel like a beach of Benidorm in July. Refactoring needed. - tooManyArgumentsCheck = new TooManyMethodArgumentsCheck(settingsStore); - } - - public override void Execute(Action commiter) - { - HighlightInFile((file, consumer) => file.ProcessDescendants(this, consumer), commiter, settingsStore); - } - - public override void VisitMethodDeclaration(IMethodDeclaration methodDeclaration, IHighlightingConsumer context) - { - tooManyArgumentsCheck.ExecuteIfEnabled(methodDeclaration, context); - } - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs index 724e869..fdbd910 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs @@ -1,4 +1,3 @@ -using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; using JetBrains.ReSharper.Daemon.Stages.Dispatcher; diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs similarity index 72% rename from CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs rename to CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs index e7348d2..54917c7 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/Highlighting.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs @@ -1,22 +1,23 @@ +using CleanCode; using CleanCode.Features.TooManyMethodArguments; using JetBrains.DocumentModel; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp; -[assembly: RegisterConfigurableSeverity(Highlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Too Many Arguments", "Too many arguments passed to a method.", +[assembly: RegisterConfigurableSeverity(TooManyArgumentsHighlighting.SeverityID, null, + CleanCodeHighlightingGroupIds.CleanCode, "Too many arguments", "Too many arguments passed to a method.", Severity.WARNING, false)] namespace CleanCode.Features.TooManyMethodArguments { [ConfigurableSeverityHighlighting(SeverityID, CSharpLanguage.Name)] - public class Highlighting : IHighlighting + public class TooManyArgumentsHighlighting : IHighlighting { internal const string SeverityID = "TooManyArguments"; private readonly string tooltip; private readonly DocumentRange documentRange; - public Highlighting(string toolTip, DocumentRange documentRange) + public TooManyArgumentsHighlighting(string toolTip, DocumentRange documentRange) { tooltip = toolTip; this.documentRange = documentRange; diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs index 77a3751..01527a7 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs @@ -1,40 +1,30 @@ using CleanCode.Resources; using CleanCode.Settings; using JetBrains.Application.Settings; +using JetBrains.ReSharper.Daemon.Stages.Dispatcher; using JetBrains.ReSharper.Feature.Services.Daemon; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.Tree; namespace CleanCode.Features.TooManyMethodArguments { - public class TooManyMethodArgumentsCheck : MonoValueCheck + [ElementProblemAnalyzer(typeof(IMethodDeclaration), HighlightingTypes = new [] { - public TooManyMethodArgumentsCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected override void ExecuteCore(IMethodDeclaration constructorDeclaration, IHighlightingConsumer consumer) + typeof(TooManyArgumentsHighlighting) + })] + public class TooManyMethodArgumentsCheck : ElementProblemAnalyzer + { + protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var parameterDeclarations = constructorDeclaration.ParameterDeclarations; - var maxParameters = Value; + var maxParameters = data.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); + var parameterDeclarations = element.ParameterDeclarations; if (parameterDeclarations.Count > maxParameters) { - var highlighting = new Highlighting(Warnings.TooManyMethodArguments, - constructorDeclaration.GetNameDocumentRange()); + var highlighting = new TooManyArgumentsHighlighting(Warnings.TooManyMethodArguments, + element.GetNameDocumentRange()); consumer.AddHighlighting(highlighting); } } - - protected override int Value - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum); } - } - - protected override bool IsEnabled - { - get { return SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyMethodArgumentsEnabled); } - } } } \ No newline at end of file From 6ac159b0f4f988b3026d42fada73cd33dfd6499b Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 11:49:57 +0100 Subject: [PATCH 40/50] Clean up --- CleanCode/src/CleanCode/CleanCode.csproj | 2 -- CleanCode/src/CleanCode/Features/Check.cs | 36 ------------------- .../src/CleanCode/Features/MonoValueCheck.cs | 16 --------- 3 files changed, 54 deletions(-) delete mode 100644 CleanCode/src/CleanCode/Features/Check.cs delete mode 100644 CleanCode/src/CleanCode/Features/MonoValueCheck.cs diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index 4f90651..e5ac133 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -170,7 +170,6 @@ - @@ -187,7 +186,6 @@ Code - Code diff --git a/CleanCode/src/CleanCode/Features/Check.cs b/CleanCode/src/CleanCode/Features/Check.cs deleted file mode 100644 index b9136e2..0000000 --- a/CleanCode/src/CleanCode/Features/Check.cs +++ /dev/null @@ -1,36 +0,0 @@ -using JetBrains.Application.Settings; -using JetBrains.ReSharper.Feature.Services.Daemon; -using JetBrains.ReSharper.Psi.Tree; - -namespace CleanCode.Features -{ - public abstract class Check - where TElement : ITreeNode - { - private readonly IContextBoundSettingsStore settingsStore; - - protected Check(IContextBoundSettingsStore settingsStore) - { - this.settingsStore = settingsStore; - } - - protected abstract bool IsEnabled { get; } - - protected IContextBoundSettingsStore SettingsStore - { - get { return settingsStore; } - } - - public void ExecuteIfEnabled(TElement methodDeclaration, IHighlightingConsumer context) - { - if (!IsEnabled) - { - return; - } - - ExecuteCore(methodDeclaration, context); - } - - protected abstract void ExecuteCore(TElement constructorDeclaration, IHighlightingConsumer consumer); - } -} \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MonoValueCheck.cs b/CleanCode/src/CleanCode/Features/MonoValueCheck.cs deleted file mode 100644 index 0c87c88..0000000 --- a/CleanCode/src/CleanCode/Features/MonoValueCheck.cs +++ /dev/null @@ -1,16 +0,0 @@ -using JetBrains.Application.Settings; -using JetBrains.ReSharper.Psi.Tree; - -namespace CleanCode.Features -{ - public abstract class MonoValueCheck : Check - where TElement : ITreeNode - { - protected MonoValueCheck(IContextBoundSettingsStore settingsStore) - : base(settingsStore) - { - } - - protected abstract TValue Value { get; } - } -} \ No newline at end of file From 393ec32c325c37b1782f4c49b658b928012f1507 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 12:03:47 +0100 Subject: [PATCH 41/50] Reset release build dirs --- CleanCode/src/CleanCode/CleanCode.csproj | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index e5ac133..3e43a4d 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -21,23 +21,17 @@ full false bin\Debug\ - TRACE;DEBUG;JET_MODE_ASSERT,RESHARPER_82 + TRACE;DEBUG;JET_MODE_ASSERT prompt 4 pdbonly true - ..\NuGet.Packager\lib\ - TRACE;RESHARPER_81 + TRACE prompt 4 - - - Program - $(VsInstallDir)devenv.exe - /ReSharper.Plugin $(AssemblyName).dll /ReSharper.Internal - $(MSBuildProjectDirectory)\$(OutputPath) + bin\Release\ From 0fc02de7bd899d329e9e92563d8e68859679c64c Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 12:05:24 +0100 Subject: [PATCH 42/50] Update gitignore --- .gitignore | 200 +---------------------------------------------------- 1 file changed, 2 insertions(+), 198 deletions(-) diff --git a/.gitignore b/.gitignore index 4ead766..f9ca77d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,215 +1,19 @@ -################# -## Eclipse -################# - -*.pydevproject -.project -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.classpath -.settings/ -.loadpath - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# CDT-specific -.cproject - -# PDT-specific -.buildpath - - ################# ## Visual Studio ################# -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - # User-specific files *.suo *.user -*.sln.docstates # Build results - [Dd]ebug/ [Rr]elease/ -x64/ -build/ [Bb]in/ [Oo]bj/ -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -*_i.c -*_p.c -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.log -*.scc - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -*.ncrunch* -.*crunch*.local.xml - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.Publish.xml -*.pubxml - # NuGet Packages Directory -## TODO: If you have NuGet Package Restore enabled, uncomment the next line packages/ -# Windows Azure Build Output -csx -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.[Pp]ublish.xml -*.pfx -*.publishsettings - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file to a newer -# Visual Studio version. Backup files are not needed, because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -App_Data/*.mdf -App_Data/*.ldf - -############# -## Windows detritus -############# - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Mac crap -.DS_Store - - -############# -## Python -############# - -*.py[co] - -# Packages -*.egg -*.egg-info -dist/ -build/ -eggs/ -parts/ -var/ -sdist/ -develop-eggs/ -.installed.cfg - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -.tox - -#Translations -*.mo - -#Mr Developer -.mr.developer.cfg +# Build artifacts +*.nupkg From 94aec87c0ca2a704292b068a0d2b1b7cf409a7c4 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 12:21:32 +0100 Subject: [PATCH 43/50] Cleaning up settings --- .../ChainedReferencesCheck.cs | 2 +- .../Features/ClassTooBig/ClassTooBigCheck.cs | 2 +- .../ComplexConditionExpressionCheck.cs | 2 +- .../ExcessiveIndentationCheck.cs | 2 +- .../FlagArgumentsHighlighting.cs | 3 +- .../Features/HollowNames/HollowNamesCheck.cs | 2 +- .../MethodNameNotMeaningfulCheck.cs | 2 +- .../MethodNameNotMeaningfulHighlighting.cs | 3 +- .../MethodTooLong/MethodTooLongCheck.cs | 4 +- .../TooManyDependenciesCheck.cs | 2 +- .../TooManyMethodArgumentsCheck.cs | 2 +- .../CleanCode/Resources/Settings.Designer.cs | 117 ------------------ .../src/CleanCode/Resources/Settings.resx | 39 ------ .../CleanCode/Resources/Warnings.Designer.cs | 30 +---- .../src/CleanCode/Resources/Warnings.resx | 18 +-- .../Settings/CleanCodeOptionsPage.cs | 28 +++-- .../CleanCode/Settings/CleanCodeSettings.cs | 97 +++------------ 17 files changed, 63 insertions(+), 292 deletions(-) diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs index 420885a..ba8d649 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs @@ -20,7 +20,7 @@ protected override void Run(ICSharpStatement element, ElementProblemAnalyzerData { if (!element.IsEmbeddedStatement) { - var threshold = data.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum); + var threshold = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumChainedReferences); HighlightMethodChainsThatAreTooLong(element, consumer, threshold); } } diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs index 535d3af..14c7b69 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigCheck.cs @@ -16,7 +16,7 @@ public class ClassTooBigCheck : ElementProblemAnalyzer { protected override void Run(IClassDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var maxLength = data.SettingsStore.GetValue((CleanCodeSettings s) => s.ClassTooBigMaximum); + var maxLength = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumMethodsInClass); var statementCount = element.CountChildren(); if (statementCount > maxLength) diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs index fbeeba6..7ab38d1 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs @@ -62,7 +62,7 @@ private static IExpression GetExpression(ITreeNode node) private static void CheckExpression(IExpression expression, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var maxExpressions = data.SettingsStore.GetValue((CleanCodeSettings s) => s.ComplexExpressionMaximum); + var maxExpressions = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumExpressionsInCondition); var expressionCount = expression.GetChildrenRecursive().Count(); if (expressionCount > maxExpressions) diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs index f5f1b3d..4f664cf 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentationCheck.cs @@ -16,7 +16,7 @@ public class ExcessiveIndentationCheck : ElementProblemAnalyzer s.ExcessiveIndentationMaximum); + var maxIndentation = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumIndentationDepth); var depth = element.GetChildrenDepth(); if (depth > maxIndentation) diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs index eac3912..0f1f0b2 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs @@ -1,3 +1,4 @@ +using CleanCode; using CleanCode.Features.FlagArguments; using CleanCode.Resources; using JetBrains.DocumentModel; @@ -5,7 +6,7 @@ using JetBrains.ReSharper.Psi.CSharp; [assembly: RegisterConfigurableSeverity(FlagArgumentsHighlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Flag argument", "An argument that is used as a flag.", + CleanCodeHighlightingGroupIds.CleanCode, "Flag argument", "An argument that is used as a flag.", Severity.WARNING, false)] namespace CleanCode.Features.FlagArguments diff --git a/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs index 2684f8e..7c0c23e 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/HollowNamesCheck.cs @@ -29,7 +29,7 @@ protected override void Run(IClassDeclaration element, ElementProblemAnalyzerDat private IEnumerable GetSuffixes(IContextBoundSettingsStore dataSettingsStore) { - var suffixes = dataSettingsStore.GetValue((CleanCodeSettings s) => s.HollowTypeNameString); + var suffixes = dataSettingsStore.GetValue((CleanCodeSettings s) => s.MeaninglessClassNameSuffixes); return suffixes.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); } diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs index fdbd910..a267f79 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulCheck.cs @@ -18,7 +18,7 @@ protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerDa if (element.NameIdentifier == null) return; - var minimumMethodNameLength = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimum); + var minimumMethodNameLength = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MinimumMeaningfulMethodNameLength); var name = element.NameIdentifier.GetText(); var methodNameLength = name.Length; diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs index a30201d..65fe18c 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs @@ -1,3 +1,4 @@ +using CleanCode; using CleanCode.Features.MethodNameNotMeaningful; using CleanCode.Resources; using JetBrains.DocumentModel; @@ -5,7 +6,7 @@ using JetBrains.ReSharper.Psi.CSharp; [assembly: RegisterConfigurableSeverity(MethodNameNotMeaningfulHighlighting.SeverityID, null, - HighlightingGroupIds.CodeSmell, "Method name not meaningful", + CleanCodeHighlightingGroupIds.CleanCode, "Method name not meaningful", "This method name is too short to be meaningful.", Severity.WARNING, false)] diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs index 7b15a8c..6789f38 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs @@ -15,8 +15,8 @@ public class MethodTooLongCheck : ElementProblemAnalyzer { protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - var maxStatements = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MethodTooLongMaximum); - var maxDeclarations = data.SettingsStore.GetValue((CleanCodeSettings s) => s.TooManyDeclarationsMaximum); + var maxStatements = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumMethodStatements); + var maxDeclarations = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumDeclarationsInMethod); var statementCount = element.CountChildren(); if (statementCount <= maxStatements) diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs index b953203..06f8ad5 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesCheck.cs @@ -17,7 +17,7 @@ public class TooManyDependenciesCheck : ElementProblemAnalyzer s.TooManyDependenciesMaximum); + var maxDependencies = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumConstructorDependencies); var dependencies = element.ParameterDeclarations.Select( declaration => declaration.DeclaredElement != null && diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs index 01527a7..5928b94 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyMethodArgumentsCheck.cs @@ -16,7 +16,7 @@ public class TooManyMethodArgumentsCheck : ElementProblemAnalyzer s.TooManyMethodArgumentsMaximum); + var maxParameters = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumMethodParameters); var parameterDeclarations = element.ParameterDeclarations; if (parameterDeclarations.Count > maxParameters) diff --git a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs index aa1fc6b..38efef2 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Settings.Designer.cs @@ -60,24 +60,6 @@ internal Settings() { } } - /// - /// Looks up a localized string similar to Maximum Methods Per Class Check. - /// - public static string ClassTooBigCheck { - get { - return ResourceManager.GetString("ClassTooBigCheck", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Complex expression check (conditions). - /// - public static string ComplexExpressionCheck { - get { - return ResourceManager.GetString("ComplexExpressionCheck", resourceCulture); - } - } - /// /// Looks up a localized string similar to Maximum declarations per method. /// @@ -87,42 +69,6 @@ public static string DeclarationsMaximum { } } - /// - /// Looks up a localized string similar to Excessive Depth Of Nesting Check. - /// - public static string ExcessiveDepthCheck { - get { - return ResourceManager.GetString("ExcessiveDepthCheck", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Flag Arguments Check. - /// - public static string FlagArgumentsCheck { - get { - return ResourceManager.GetString("FlagArgumentsCheck", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Hollow Type Name Check. - /// - public static string HollowTypeNameCheck { - get { - return ResourceManager.GetString("HollowTypeNameCheck", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Maximum Chained References Check. - /// - public static string MaxChainedReferencesCheck { - get { - return ResourceManager.GetString("MaxChainedReferencesCheck", resourceCulture); - } - } - /// /// Looks up a localized string similar to Maximum chained references. /// @@ -141,15 +87,6 @@ public static string MaximumConstructorDependencies { } } - /// - /// Looks up a localized string similar to Maximum Dependencies Check. - /// - public static string MaximumDependenciesCheck { - get { - return ResourceManager.GetString("MaximumDependenciesCheck", resourceCulture); - } - } - /// /// Looks up a localized string similar to Maximum expressions inside a condition. /// @@ -168,15 +105,6 @@ public static string MaximumLevelOfNestingInAMethod { } } - /// - /// Looks up a localized string similar to Maximum Method Arguments Check. - /// - public static string MaximumMethodArgumentsCheck { - get { - return ResourceManager.GetString("MaximumMethodArgumentsCheck", resourceCulture); - } - } - /// /// Looks up a localized string similar to Maximum method declaration parameters. /// @@ -222,15 +150,6 @@ public static string MeaninglessNameSuffixesTooltip { } } - /// - /// Looks up a localized string similar to Maximum Statements Per Method Check. - /// - public static string MethodTooLongCheck { - get { - return ResourceManager.GetString("MethodTooLongCheck", resourceCulture); - } - } - /// /// Looks up a localized string similar to Minimum method name length. /// @@ -239,41 +158,5 @@ public static string MinimumMethodNameLength { return ResourceManager.GetString("MinimumMethodNameLength", resourceCulture); } } - - /// - /// Looks up a localized string similar to Minimum Method Name Length. - /// - public static string MinimumMethodNameLengthCheck { - get { - return ResourceManager.GetString("MinimumMethodNameLengthCheck", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The options below help enforce certain practices that can be considered to leading to cleaner and more maintainable code.. - /// - public static string Options_Header { - get { - return ResourceManager.GetString("Options_Header", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Note: All references to Clean Code, including but not limited to the Clean Code icon are used with permission of Robert C. Martin (a.k.a. UncleBob). - /// - public static string Options_SubHeader { - get { - return ResourceManager.GetString("Options_SubHeader", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Too Many Declarations Check. - /// - public static string TooManyDeclarationsCheck { - get { - return ResourceManager.GetString("TooManyDeclarationsCheck", resourceCulture); - } - } } } diff --git a/CleanCode/src/CleanCode/Resources/Settings.resx b/CleanCode/src/CleanCode/Resources/Settings.resx index 683c2b1..7297fcd 100644 --- a/CleanCode/src/CleanCode/Resources/Settings.resx +++ b/CleanCode/src/CleanCode/Resources/Settings.resx @@ -117,18 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - The options below help enforce certain practices that can be considered to leading to cleaner and more maintainable code. - - - Maximum Dependencies Check - - - Maximum Method Arguments Check - - - Maximum Statements Per Method Check - Maximum statements per method @@ -138,45 +126,21 @@ Maximum method declaration parameters - - Note: All references to Clean Code, including but not limited to the Clean Code icon are used with permission of Robert C. Martin (a.k.a. UncleBob) - Maximum level of nesting in a method - - Excessive Depth Of Nesting Check - Maximum methods per class - - Maximum Methods Per Class Check - Maximum chained references - - Maximum Chained References Check - Minimum method name length - - Minimum Method Name Length - - - Complex expression check (conditions) - Maximum expressions inside a condition - - Flag Arguments Check - - - Hollow Type Name Check - List of meaningless suffixes @@ -186,7 +150,4 @@ Maximum declarations per method - - Too Many Declarations Check - \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs index cc07a0f..40f8864 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs +++ b/CleanCode/src/CleanCode/Resources/Warnings.Designer.cs @@ -61,7 +61,7 @@ internal Warnings() { } /// - /// Looks up a localized string similar to Too many chained references.. + /// Looks up a localized string similar to Too many chained references. This might be violating the Law of Demeter.. /// public static string ChainedReferences { get { @@ -70,7 +70,7 @@ public static string ChainedReferences { } /// - /// Looks up a localized string similar to Class contains too many methods.. + /// Looks up a localized string similar to Class contains too many methods. This might be violating the Single Responsibility Principle.. /// public static string ClassTooBig { get { @@ -97,7 +97,7 @@ public static string ExpressionTooComplex { } /// - /// Looks up a localized string similar to This argument is used as a flag in the method. It usually means that the method has more than one responsibility.. + /// Looks up a localized string similar to This argument is used as a flag in the method. This might be violating the Single Responsibility Principle.. /// public static string FlagArgument { get { @@ -106,16 +106,7 @@ public static string FlagArgument { } /// - /// Looks up a localized string similar to This method does more than one thing. Passing a boolean into a function is a truly terrible practice.. - /// - public static string FlagMethodArguments { - get { - return ResourceManager.GetString("FlagMethodArguments", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The usage of the suffix '{0}' is discouraged because it's too generic. Please, choose a meaningful name instead to clarify its intent and responsibilities.. + /// Looks up a localized string similar to The usage of the suffix '{0}' is discouraged because it's too generic. Choose a meaningful name instead to clarify its intent and responsibilities.. /// public static string HollowTypeName { get { @@ -133,7 +124,7 @@ public static string MethodNameNotMeaningful { } /// - /// Looks up a localized string similar to This method is too long.. + /// Looks up a localized string similar to This method is too long, indicating that it has too much responsibility.. /// public static string MethodTooLong { get { @@ -142,7 +133,7 @@ public static string MethodTooLong { } /// - /// Looks up a localized string similar to There are too many interfaces being passed in to this constructor. You might be violating the Single Responsibility Principle.. + /// Looks up a localized string similar to There are too many interfaces being passed in to this constructor. It might be violating the Single Responsibility Principle.. /// public static string TooManyDependencies { get { @@ -158,14 +149,5 @@ public static string TooManyMethodArguments { return ResourceManager.GetString("TooManyMethodArguments", resourceCulture); } } - - /// - /// Looks up a localized string similar to Too many declarations. This method is likely doing more than one thing.. - /// - public static string Warning_TooManyDeclarations { - get { - return ResourceManager.GetString("Warning_TooManyDeclarations", resourceCulture); - } - } } } diff --git a/CleanCode/src/CleanCode/Resources/Warnings.resx b/CleanCode/src/CleanCode/Resources/Warnings.resx index 79e1e61..f00f274 100644 --- a/CleanCode/src/CleanCode/Resources/Warnings.resx +++ b/CleanCode/src/CleanCode/Resources/Warnings.resx @@ -118,39 +118,33 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - There are too many interfaces being passed in to this constructor. You might be violating the Single Responsibility Principle. + There are too many interfaces being passed in to this constructor. It might be violating the Single Responsibility Principle. This method requires too many arguments. - This method is too long. + This method is too long, indicating that it has too much responsibility. Excessive depth of nested code blocks. - Class contains too many methods. + Class contains too many methods. This might be violating the Single Responsibility Principle. - Too many chained references. + Too many chained references. This might be violating the Law of Demeter. The name of this method is too short to be meaningful. - - This method does more than one thing. Passing a boolean into a function is a truly terrible practice. - - This argument is used as a flag in the method. It usually means that the method has more than one responsibility. + This argument is used as a flag in the method. This might be violating the Single Responsibility Principle. This expression is too complex. - The usage of the suffix '{0}' is discouraged because it's too generic. Please, choose a meaningful name instead to clarify its intent and responsibilities. - - - Too many declarations. This method is likely doing more than one thing. + The usage of the suffix '{0}' is discouraged because it's too generic. Choose a meaningful name instead to clarify its intent and responsibilities. \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Settings/CleanCodeOptionsPage.cs b/CleanCode/src/CleanCode/Settings/CleanCodeOptionsPage.cs index 35b1b17..05f81fb 100644 --- a/CleanCode/src/CleanCode/Settings/CleanCodeOptionsPage.cs +++ b/CleanCode/src/CleanCode/Settings/CleanCodeOptionsPage.cs @@ -1,8 +1,10 @@ -using CleanCode.Resources.Icons; +using System.Drawing; +using CleanCode.Resources.Icons; using JetBrains.DataFlow; using JetBrains.ReSharper.Feature.Services.Daemon.OptionPages; using JetBrains.UI.Options; using JetBrains.UI.Options.OptionsDialog2.SimpleOptions; +using JetBrains.UI.RichText; namespace CleanCode.Settings { @@ -16,42 +18,46 @@ public CleanCodeOptionsPage(Lifetime lifetime, OptionsSettingsSmartContext optio { AddHeader("Single Responsibility"); AddText("A class should only have a single responsibility. Do not do too much in a class or method."); - AddIntOption((CleanCodeSettings s) => s.ClassTooBigMaximum, + AddIntOption((CleanCodeSettings s) => s.MaximumMethodsInClass, Resources.Settings.MaximumMethodsPerClass, "Too many method declarations in a class is an indicator that the class is doing too much."); - AddIntOption((CleanCodeSettings s) => s.TooManyMethodArgumentsMaximum, + AddIntOption((CleanCodeSettings s) => s.MaximumMethodParameters, Resources.Settings.MaximumMethodDeclarationParameters, "Too many parameters in a method declaration is an indicator of having more than one responsibility"); - AddIntOption((CleanCodeSettings s) => s.MethodTooLongMaximum, Resources.Settings.MaximumStatementsPerMethod, + AddIntOption((CleanCodeSettings s) => s.MaximumMethodStatements, Resources.Settings.MaximumStatementsPerMethod, "Long methods are indicator of having more than one responsibility."); - AddIntOption((CleanCodeSettings s) => s.TooManyDeclarationsMaximum, + AddIntOption((CleanCodeSettings s) => s.MaximumDeclarationsInMethod, Resources.Settings.DeclarationsMaximum, "Too many variables are an indicator of having more than one responsibility."); - AddIntOption((CleanCodeSettings s) => s.ExcessiveIndentationMaximum, + AddIntOption((CleanCodeSettings s) => s.MaximumIndentationDepth, Resources.Settings.MaximumLevelOfNestingInAMethod, "Too much nesting in a method is an indicator of having more than one responsibility."); AddHeader("Coupling"); AddText("Avoid excessive coupling beween classes."); - AddIntOption((CleanCodeSettings s) => s.TooManyDependenciesMaximum, + AddIntOption((CleanCodeSettings s) => s.MaximumConstructorDependencies, Resources.Settings.MaximumConstructorDependencies); - AddIntOption((CleanCodeSettings s) => s.TooManyChainedReferencesMaximum, + AddIntOption((CleanCodeSettings s) => s.MaximumChainedReferences, Resources.Settings.MaximumChainedReferences, "Avoid breaking the Law of Demeter."); AddHeader("Legibility"); AddText("Names should be meaningful."); - AddIntOption((CleanCodeSettings s) => s.MethodNameNotMeaningfulMinimum, + AddIntOption((CleanCodeSettings s) => s.MinimumMeaningfulMethodNameLength, Resources.Settings.MinimumMethodNameLength); - AddStringOption((CleanCodeSettings s) => s.HollowTypeNameString, + AddStringOption((CleanCodeSettings s) => s.MeaninglessClassNameSuffixes, Resources.Settings.MeaninglessNameSuffixes, Resources.Settings.MeaninglessNameSuffixesTooltip); AddHeader("Complexity"); AddText("Reduce complexity in individual statements."); - AddIntOption((CleanCodeSettings s) => s.ComplexExpressionMaximum, + AddIntOption((CleanCodeSettings s) => s.MaximumExpressionsInCondition, Resources.Settings.MaximumExpressionsInsideACondition); + AddRichText( + new RichText( + "Note: All references to Clean Code, including but not limited to the Clean Code icon are used with permission of Robert C. Martin (a.k.a. UncleBob)", + new TextStyle(FontStyle.Italic))); FinishPage(); } } diff --git a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs index 4ee5fc1..4cb5a24 100644 --- a/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs +++ b/CleanCode/src/CleanCode/Settings/CleanCodeSettings.cs @@ -1,32 +1,3 @@ -#region License - -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. - -#endregion - using JetBrains.Application.Settings; using JetBrains.ReSharper.Resources.Settings; @@ -35,62 +6,34 @@ namespace CleanCode.Settings [SettingsKey(typeof(CodeInspectionSettings), "CleanCode")] public class CleanCodeSettings { - [SettingsEntry(3, "TooManyDependenciesMaximum")] - public readonly int TooManyDependenciesMaximum; - [SettingsEntry(true, "TooManyDependenciesMaximumEnabled")] - public readonly bool TooManyDependenciesMaximumEnabled; - - [SettingsEntry(3, "TooManyMethodArgumentsMaximum")] - public readonly int TooManyMethodArgumentsMaximum; - [SettingsEntry(true, "TooManyMethodArgumentsEnabled")] - public readonly bool TooManyMethodArgumentsEnabled; - - [SettingsEntry(true, "MethodTooLongEnabled")] - public readonly bool MethodTooLongEnabled; - [SettingsEntry(15, "MethodTooLongMaximum")] - public readonly int MethodTooLongMaximum; - - [SettingsEntry(3, "ExcessiveIndentationMaximum")] - public int ExcessiveIndentationMaximum { get; set; } - [SettingsEntry(true, "ExcessiveIndentationEnabled")] - public bool ExcessiveIndentationEnabled { get; set; } - - [SettingsEntry(true, "ClassTooBigEnabled")] - public bool ClassTooBigEnabled { get; set; } - [SettingsEntry(20, "ClassTooBigMaximum")] - public int ClassTooBigMaximum { get; set; } + [SettingsEntry(3, "MaximumConstructorDependencies")] + public readonly int MaximumConstructorDependencies; - [SettingsEntry(true, "TooManyChainedReferencesEnabled")] - public bool TooManyChainedReferencesEnabled { get; set; } - [SettingsEntry(2, "TooManyChainedReferencesMaximum")] - public int TooManyChainedReferencesMaximum { get; set; } + [SettingsEntry(3, "MaximumMethodParameters")] + public readonly int MaximumMethodParameters; - [SettingsEntry(true, "MethodNameNotMeaningfulMinimumEnabled")] - public bool MethodNameNotMeaningfulMinimumEnabled { get; set; } - [SettingsEntry(4, "MethodNameNotMeaningfulMinimum")] - public int MethodNameNotMeaningfulMinimum { get; set; } + [SettingsEntry(15, "MaximumMethodStatements")] + public readonly int MaximumMethodStatements; - [SettingsEntry(true, "FlagArgumentsEnabled")] - public bool FlagArgumentsEnabled { get; set; } + [SettingsEntry(6, "MaximumDeclarationsInMethod")] + public readonly int MaximumDeclarationsInMethod; - [SettingsEntry(true, "HollowTypeNameEnabled")] - public bool HollowTypeNameEnabled { get; set; } + [SettingsEntry(3, "MaximumIndentationDepth")] + public int MaximumIndentationDepth { get; set; } - [SettingsEntry("Handler,Manager,Processor,Controller,Helper", "HollowTypeNameString")] - public string HollowTypeNameString { get; set; } + [SettingsEntry(20, "MaximumMethodsInClass")] + public int MaximumMethodsInClass { get; set; } - [SettingsEntry(true, "ComplexExpressionEnabled")] + [SettingsEntry(2, "MaximumChainedReferences")] + public int MaximumChainedReferences { get; set; } - public bool ComplexExpressionEnabled { get; set; } - [SettingsEntry(1, "ComplexExpressionMaximum")] - public int ComplexExpressionMaximum { get; set; } + [SettingsEntry(4, "MinimumMeaningfulMethodNameLength")] + public int MinimumMeaningfulMethodNameLength { get; set; } - [SettingsEntry(true, "TooManyDeclarationsEnabled")] - public readonly bool TooManyDeclarationsEnabled; - [SettingsEntry(6, "TooManyDeclarationsMaximum")] - public readonly int TooManyDeclarationsMaximum; + [SettingsEntry("Handler,Manager,Processor,Controller,Helper", "MeaninglessClassNameSuffixes")] + public string MeaninglessClassNameSuffixes { get; set; } - [SettingsEntry(true, "InterfacesWithNoPrefixEnabled")] - public readonly bool InterfacesWithNoPrefixEnabled; + [SettingsEntry(1, "MaximumExpressionsInCondition")] + public int MaximumExpressionsInCondition { get; set; } } } \ No newline at end of file From 40162307501dfb9500b7770d155a3047f97e1e7d Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 14:14:36 +0100 Subject: [PATCH 44/50] Updated readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ffc49a..d8ccfd9 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Please use the previous issue tracker for logging bugs, feature requests, etc. ## Installing -Copy the DLL for each Plugin to the ReSharper\bin\Plugins folder +Install from ReSharper → Extension Manager. ## License From 1fffd94b9c5ef80b6d75b9a0e096ef14809bc2a8 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 16:07:56 +0100 Subject: [PATCH 45/50] Updated to C# 6 Works around an issue in the installer where the C# 5 compiler doesn't add a reference to a type used in an attribute, and the installer complains that the dependency is unknown. --- CleanCode/src/CleanCode.nuspec | 3 +- CleanCode/src/CleanCode.sln | 4 +-- .../MaximumChainedReferencesHighlighting.cs | 26 +++------------ .../ClassTooBig/ClassTooBigHighlighting.cs | 26 +++------------ .../ComplexConditionExpressionCheck.cs | 5 +-- .../ComplexConditionExpressionHighlighting.cs | 23 +++---------- .../ExcessiveIndentHighlighting.cs | 23 +++---------- .../CleanCode/Features/ExtensionMethods.cs | 27 +++------------- .../FlagArgumentsHighlighting.cs | 23 +++---------- .../HollowNames/HollowTypeNameHighlighting.cs | 26 +++------------ .../MethodNameNotMeaningfulHighlighting.cs | 23 +++---------- .../MethodTooLongHighlighting.cs | 23 +++---------- .../TooManyDependenciesHighlighting.cs | 23 +++---------- .../TooManyArgumentsHighlighting.cs | 26 +++------------ .../src/CleanCode/Properties/AssemblyInfo.cs | 32 ++----------------- 15 files changed, 57 insertions(+), 256 deletions(-) diff --git a/CleanCode/src/CleanCode.nuspec b/CleanCode/src/CleanCode.nuspec index 1ef08cf..5738fac 100644 --- a/CleanCode/src/CleanCode.nuspec +++ b/CleanCode/src/CleanCode.nuspec @@ -2,7 +2,7 @@ CleanCode.CleanCode - 5.0.0 + 5.0.1 Clean Code Hadi Hariri, Matt Ellis, SuperJMN Hadi Hariri, Matt Ellis @@ -13,6 +13,7 @@ Automates some of the concepts in Uncle Bob's Clean Code book • Updated to ReSharper 2016.2 +• Fix minor installer issue From 4.0.0: • Warning if a method uses flag parameters diff --git a/CleanCode/src/CleanCode.sln b/CleanCode/src/CleanCode.sln index 42b4822..e960136 100644 --- a/CleanCode/src/CleanCode.sln +++ b/CleanCode/src/CleanCode.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.40629.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CleanCode", "CleanCode\CleanCode.csproj", "{5F96119C-2646-4298-AD40-30209E7E7BB2}" EndProject diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs index 1f5df58..b09aa52 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs @@ -15,33 +15,17 @@ public class MaximumChainedReferencesHighlighting : IHighlighting { internal const string SeverityID = "TooManyChainedReferences"; - private readonly string tooltip; private readonly DocumentRange documentRange; public MaximumChainedReferencesHighlighting(string toolTip, DocumentRange documentRange) { - tooltip = toolTip; + ToolTip = toolTip; this.documentRange = documentRange; } - public DocumentRange CalculateRange() - { - return documentRange; - } - - public string ToolTip - { - get { return tooltip; } - } - - public string ErrorStripeToolTip - { - get { return tooltip; } - } - - public bool IsValid() - { - return true; - } + public DocumentRange CalculateRange() => documentRange; + public string ToolTip { get; } + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs index 6107f63..5a06983 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs @@ -15,33 +15,17 @@ public class ClassTooBigHighlighting : IHighlighting { internal const string SeverityID = "ClassTooBig"; - private readonly string tooltip; private readonly DocumentRange documentRange; public ClassTooBigHighlighting(string toolTip, DocumentRange documentRange) { - tooltip = toolTip; + ToolTip = toolTip; this.documentRange = documentRange; } - public DocumentRange CalculateRange() - { - return documentRange; - } - - public string ToolTip - { - get { return tooltip; } - } - - public string ErrorStripeToolTip - { - get { return tooltip; } - } - - public bool IsValid() - { - return true; - } + public DocumentRange CalculateRange() => documentRange; + public string ToolTip { get; } + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs index 7ab38d1..131c11f 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionCheck.cs @@ -53,10 +53,7 @@ private static IExpression GetExpression(ITreeNode node) return assignmentExpression.Source; var expressionInitializer = node as IExpressionInitializer; - if (expressionInitializer != null) - return expressionInitializer.Value; - - return null; + return expressionInitializer?.Value; } private static void CheckExpression(IExpression expression, ElementProblemAnalyzerData data, diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs index 5d7b531..23df5f2 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs @@ -23,24 +23,9 @@ public ComplexConditionExpressionHighlighting(DocumentRange documentRange) this.documentRange = documentRange; } - public DocumentRange CalculateRange() - { - return documentRange; - } - - public string ToolTip - { - get { return Warnings.ExpressionTooComplex; } - } - - public string ErrorStripeToolTip - { - get { return ToolTip; } - } - - public bool IsValid() - { - return true; - } + public DocumentRange CalculateRange() => documentRange; + public string ToolTip => Warnings.ExpressionTooComplex; + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs index d3dd420..bb12f4e 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs @@ -22,24 +22,9 @@ public ExcessiveIndentHighlighting(DocumentRange documentRange) this.documentRange = documentRange; } - public DocumentRange CalculateRange() - { - return documentRange; - } - - public string ToolTip - { - get { return Warnings.ExcessiveDepth; } - } - - public string ErrorStripeToolTip - { - get { return ToolTip; } - } - - public bool IsValid() - { - return true; - } + public DocumentRange CalculateRange() => documentRange; + public string ToolTip => Warnings.ExcessiveDepth; + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ExtensionMethods.cs b/CleanCode/src/CleanCode/Features/ExtensionMethods.cs index 353d886..1f3ade0 100644 --- a/CleanCode/src/CleanCode/Features/ExtensionMethods.cs +++ b/CleanCode/src/CleanCode/Features/ExtensionMethods.cs @@ -27,7 +27,7 @@ public static int CountChildren(this ITreeNode node) where T : ITreeNode public static int GetChildrenDepth(this ITreeNode node) - { + { var childrenDepth = 0; var children = node.Children(); foreach (var block in children) @@ -38,7 +38,7 @@ public static int GetChildrenDepth(this ITreeNode node) if (IsNodeThatIncreasesDepth(node)) { - return childrenDepth + 1; + return childrenDepth + 1; } return childrenDepth; } @@ -122,20 +122,10 @@ public static IReferenceExpression TryGetFirstReferenceExpression(ITreeNode curr var firstChildNode = childNodes.FirstOrDefault(); if (firstChildNode == null) - { return null; - } - else - { - var referenceExpression = firstChildNode as IReferenceExpression; - - if (referenceExpression == null) - { - referenceExpression = TryGetFirstReferenceExpression(firstChildNode); - } - return referenceExpression; - } + return firstChildNode as IReferenceExpression ?? + TryGetFirstReferenceExpression(firstChildNode); } private static IType TryGetClosedReturnTypeFromReference(IReference reference) @@ -143,9 +133,7 @@ private static IType TryGetClosedReturnTypeFromReference(IReference reference) var resolveResultWithInfo = GetResolveResult(reference); if (reference.CurrentResolveResult == null) - { reference.Resolve(); - } var declaredElement = resolveResultWithInfo.DeclaredElement; var parametersOwner = declaredElement as IParametersOwner; @@ -153,12 +141,7 @@ private static IType TryGetClosedReturnTypeFromReference(IReference reference) if (parametersOwner != null) { var returnType = parametersOwner.ReturnType; - if (returnType.IsOpenType) - { - return GetClosedType(resolveResultWithInfo, returnType); - } - - return returnType; + return returnType.IsOpenType ? GetClosedType(resolveResultWithInfo, returnType) : returnType; } return null; diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs index 0f1f0b2..a76cc22 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs @@ -22,24 +22,9 @@ public FlagArgumentsHighlighting(DocumentRange documentRange) this.documentRange = documentRange; } - public DocumentRange CalculateRange() - { - return documentRange; - } - - public string ToolTip - { - get { return Warnings.FlagArgument; } - } - - public string ErrorStripeToolTip - { - get { return ToolTip; } - } - - public bool IsValid() - { - return true; - } + public DocumentRange CalculateRange() => documentRange; + public string ToolTip => Warnings.FlagArgument; + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs b/CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs index e512824..adbc538 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs @@ -14,33 +14,17 @@ namespace CleanCode.Features.HollowNames public class HollowTypeNameHighlighting : IHighlighting { internal const string SeverityID = "HollowTypeName"; - private readonly string tooltip; private readonly DocumentRange documentRange; public HollowTypeNameHighlighting(string toolTip, DocumentRange documentRange) { - tooltip = toolTip; + ToolTip = toolTip; this.documentRange = documentRange; } - public DocumentRange CalculateRange() - { - return documentRange; - } - - public string ToolTip - { - get { return tooltip; } - } - - public string ErrorStripeToolTip - { - get { return tooltip; } - } - - public bool IsValid() - { - return true; - } + public DocumentRange CalculateRange() => documentRange; + public string ToolTip { get; } + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs index 65fe18c..5eb9160 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs @@ -23,24 +23,9 @@ public MethodNameNotMeaningfulHighlighting(DocumentRange documentRange) this.documentRange = documentRange; } - public DocumentRange CalculateRange() - { - return documentRange; - } - - public string ToolTip - { - get { return Warnings.MethodNameNotMeaningful; } - } - - public string ErrorStripeToolTip - { - get { return ToolTip; } - } - - public bool IsValid() - { - return true; - } + public DocumentRange CalculateRange() => documentRange; + public string ToolTip => Warnings.MethodNameNotMeaningful; + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs index c44924a..3d1e0c6 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs @@ -22,24 +22,9 @@ public MethodTooLongHighlighting(DocumentRange documentRange) this.documentRange = documentRange; } - public DocumentRange CalculateRange() - { - return documentRange; - } - - public string ToolTip - { - get { return Warnings.MethodTooLong; } - } - - public string ErrorStripeToolTip - { - get { return ToolTip; } - } - - public bool IsValid() - { - return true; - } + public DocumentRange CalculateRange() => documentRange; + public string ToolTip => Warnings.MethodTooLong; + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs index 2b60f29..4b4492d 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs @@ -22,24 +22,9 @@ public TooManyDependenciesHighlighting(DocumentRange documentRange) this.documentRange = documentRange; } - public DocumentRange CalculateRange() - { - return documentRange; - } - - public string ToolTip - { - get { return Warnings.TooManyDependencies; } - } - - public string ErrorStripeToolTip - { - get { return ToolTip; } - } - - public bool IsValid() - { - return true; - } + public DocumentRange CalculateRange() => documentRange; + public string ToolTip => Warnings.TooManyDependencies; + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs index 54917c7..2075a63 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs @@ -14,33 +14,17 @@ namespace CleanCode.Features.TooManyMethodArguments public class TooManyArgumentsHighlighting : IHighlighting { internal const string SeverityID = "TooManyArguments"; - private readonly string tooltip; private readonly DocumentRange documentRange; public TooManyArgumentsHighlighting(string toolTip, DocumentRange documentRange) { - tooltip = toolTip; + ToolTip = toolTip; this.documentRange = documentRange; } - public DocumentRange CalculateRange() - { - return documentRange; - } - - public string ToolTip - { - get { return tooltip; } - } - - public string ErrorStripeToolTip - { - get { return tooltip; } - } - - public bool IsValid() - { - return true; - } + public DocumentRange CalculateRange() => documentRange; + public string ToolTip { get; } + public string ErrorStripeToolTip => ToolTip; + public bool IsValid() => true; } } \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs index 36acfcd..3aa9691 100644 --- a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs +++ b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs @@ -1,30 +1,4 @@ -#region License -// Copyright (C) 2012 Hadi Hariri and Contributors -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall -// be included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS -// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. -#endregion -using System.Reflection; +using System.Reflection; using System.Runtime.InteropServices; [assembly: AssemblyTitle("ReSharper Clean Code Plugin")] @@ -38,5 +12,5 @@ [assembly: ComVisible(false)] [assembly: Guid("97927FF9-8C9C-4DC5-A309-29C23F41DA47")] -[assembly: AssemblyVersion("5.0.0.0")] -[assembly: AssemblyFileVersion("5.0.0.0")] +[assembly: AssemblyVersion("5.0.1.0")] +[assembly: AssemblyFileVersion("5.0.1.0")] From 843d323a6ebe00e2d0569b3403547e8436fce15e Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 21:49:17 +0100 Subject: [PATCH 46/50] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index d8ccfd9..1076f1d 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,7 @@ The limits used by each analysis are configurable in the options page. ### Upcoming features -All features are [logged here](http://youtrack.codebetter.com/issues/cc) - -Please use the previous issue tracker for logging bugs, feature requests, etc. +Please log feature requests and bugs in [Issues](https://github.com/hhariri/CleanCode/issues). ## Installing From 4bad62141ecf1f9d6e718eb0d2374d514167f1fe Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Tue, 6 Sep 2016 23:10:19 +0100 Subject: [PATCH 47/50] Method too long only uses declarations in body Fixes #12 --- CleanCode/src/CleanCode.nuspec | 5 ++++- .../CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs | 5 ++++- CleanCode/src/CleanCode/Properties/AssemblyInfo.cs | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CleanCode/src/CleanCode.nuspec b/CleanCode/src/CleanCode.nuspec index 5738fac..16a9c37 100644 --- a/CleanCode/src/CleanCode.nuspec +++ b/CleanCode/src/CleanCode.nuspec @@ -2,7 +2,7 @@ CleanCode.CleanCode - 5.0.1 + 5.0.2 Clean Code Hadi Hariri, Matt Ellis, SuperJMN Hadi Hariri, Matt Ellis @@ -12,6 +12,9 @@ false Automates some of the concepts in Uncle Bob's Clean Code book +• Method parameter and type parameter declarations mistakenly used for "method too long" check (#12) + +From 5.0.1: • Updated to ReSharper 2016.2 • Fix minor installer issue diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs index 6789f38..8e4f5e4 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs @@ -21,7 +21,10 @@ protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerDa var statementCount = element.CountChildren(); if (statementCount <= maxStatements) { - var declarationCount = element.CountChildren(); + // Only look in the method body for declarations, otherwise we see + // parameters + type parameters. We can ignore arrow expressions, as + // they must be a single expression and won't have declarations + var declarationCount = element.Body?.CountChildren(); if (declarationCount <= maxDeclarations) return; } diff --git a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs index 3aa9691..b723f6b 100644 --- a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs +++ b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs @@ -12,5 +12,5 @@ [assembly: ComVisible(false)] [assembly: Guid("97927FF9-8C9C-4DC5-A309-29C23F41DA47")] -[assembly: AssemblyVersion("5.0.1.0")] -[assembly: AssemblyFileVersion("5.0.1.0")] +[assembly: AssemblyVersion("5.0.2.0")] +[assembly: AssemblyFileVersion("5.0.2.0")] From 9a6d06383a5153e8e7b69622cabcc0001fb932fa Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Wed, 7 Sep 2016 13:30:23 +0100 Subject: [PATCH 48/50] Clarify only supports C# Resolves #13 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1076f1d..1dea790 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ 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). -Each check is intended 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: +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: * **Too many dependencies** - warns when a constructor has too many interfaces passed in. * **Excessive indentation** - warns if a class contains members with too much indentation. @@ -21,7 +21,7 @@ The limits used by each analysis are configurable in the options page. ### Upcoming features -Please log feature requests and bugs in [Issues](https://github.com/hhariri/CleanCode/issues). +Please log feature requests and bugs in [Issues](https://github.com/hhariri/CleanCode/issues). Note that this version only supports C#. ## Installing From aa64ac281e90e76d8f7adb9f5ac094bc91a1d904 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Fri, 9 Sep 2016 09:06:35 +0100 Subject: [PATCH 49/50] Stop marking abstract methods too long Fixes #19 --- CleanCode/src/CleanCode.nuspec | 5 ++++- .../CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs | 2 +- CleanCode/src/CleanCode/Properties/AssemblyInfo.cs | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CleanCode/src/CleanCode.nuspec b/CleanCode/src/CleanCode.nuspec index 16a9c37..aad337d 100644 --- a/CleanCode/src/CleanCode.nuspec +++ b/CleanCode/src/CleanCode.nuspec @@ -2,7 +2,7 @@ CleanCode.CleanCode - 5.0.2 + 5.0.3 Clean Code Hadi Hariri, Matt Ellis, SuperJMN Hadi Hariri, Matt Ellis @@ -12,6 +12,9 @@ false Automates some of the concepts in Uncle Bob's Clean Code book +• Stop marking abstract methods too long (#19) + +From 5.0.2: • Method parameter and type parameter declarations mistakenly used for "method too long" check (#12) From 5.0.1: diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs index 8e4f5e4..de17804 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongCheck.cs @@ -24,7 +24,7 @@ protected override void Run(IMethodDeclaration element, ElementProblemAnalyzerDa // Only look in the method body for declarations, otherwise we see // parameters + type parameters. We can ignore arrow expressions, as // they must be a single expression and won't have declarations - var declarationCount = element.Body?.CountChildren(); + var declarationCount = element.Body?.CountChildren() ?? 0; if (declarationCount <= maxDeclarations) return; } diff --git a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs index b723f6b..a402089 100644 --- a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs +++ b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs @@ -12,5 +12,5 @@ [assembly: ComVisible(false)] [assembly: Guid("97927FF9-8C9C-4DC5-A309-29C23F41DA47")] -[assembly: AssemblyVersion("5.0.2.0")] -[assembly: AssemblyFileVersion("5.0.2.0")] +[assembly: AssemblyVersion("5.0.3.0")] +[assembly: AssemblyFileVersion("5.0.3.0")] From dd08fb32b229ee7b7bfcb377d9a2c91465942cfb Mon Sep 17 00:00:00 2001 From: Kevin Bosman Date: Thu, 6 Apr 2017 12:12:05 +0200 Subject: [PATCH 50/50] Update build for ReSharper 2017.1 (Wave 8) --- CleanCode/src/CleanCode.nuspec | 9 +- CleanCode/src/CleanCode/CleanCode.csproj | 251 ++++++++++++++---- .../ChainedReferencesCheck.cs | 2 +- .../MaximumChainedReferencesHighlighting.cs | 2 +- .../ClassTooBig/ClassTooBigHighlighting.cs | 2 +- .../ComplexConditionExpressionHighlighting.cs | 2 +- .../ExcessiveIndentHighlighting.cs | 2 +- .../CleanCode/Features/ExtensionMethods.cs | 8 - .../FlagArgumentsHighlighting.cs | 2 +- .../HollowNames/HollowTypeNameHighlighting.cs | 2 +- .../MethodNameNotMeaningfulHighlighting.cs | 2 +- .../MethodTooLongHighlighting.cs | 2 +- .../TooManyDependenciesHighlighting.cs | 2 +- .../TooManyArgumentsHighlighting.cs | 2 +- .../src/CleanCode/Properties/AssemblyInfo.cs | 4 +- CleanCode/src/CleanCode/packages.config | 102 +++---- 16 files changed, 267 insertions(+), 129 deletions(-) diff --git a/CleanCode/src/CleanCode.nuspec b/CleanCode/src/CleanCode.nuspec index aad337d..5acc271 100644 --- a/CleanCode/src/CleanCode.nuspec +++ b/CleanCode/src/CleanCode.nuspec @@ -2,7 +2,7 @@ CleanCode.CleanCode - 5.0.3 + 5.1.0 Clean Code Hadi Hariri, Matt Ellis, SuperJMN Hadi Hariri, Matt Ellis @@ -12,6 +12,9 @@ false Automates some of the concepts in Uncle Bob's Clean Code book +• Updated to ReSharper 2017.1 + +From 5.0.3: • Stop marking abstract methods too long (#19) From 5.0.2: @@ -33,11 +36,11 @@ From 4.0.0: Copyright 2014-2016 Hadi Hariri and Contributors - + clean code - + diff --git a/CleanCode/src/CleanCode/CleanCode.csproj b/CleanCode/src/CleanCode/CleanCode.csproj index 3e43a4d..d6ea69a 100644 --- a/CleanCode/src/CleanCode/CleanCode.csproj +++ b/CleanCode/src/CleanCode/CleanCode.csproj @@ -1,6 +1,6 @@  - + Debug AnyCPU @@ -11,7 +11,7 @@ Properties CleanCode CleanCode - v4.0 + v4.5 512 aa44b150 @@ -38,12 +38,12 @@ ..\packages\Antlr2.Runtime.2.7.7.02\lib\antlr.runtime.dll True - - ..\packages\AsyncBridge.JetBrains.0.1.1.0\lib\net40-Client\AsyncBridge.dll + + ..\packages\Appccelerate.StateMachine.JetBrains.2.2.0.1\lib\net45\Appccelerate.Fundamentals.dll True - - ..\packages\AsyncIO.0.1.18.0\lib\net40\AsyncIO.dll + + ..\packages\Appccelerate.StateMachine.JetBrains.2.2.0.1\lib\net45\Appccelerate.StateMachine.dll True @@ -66,16 +66,29 @@ ..\packages\JetBrains.Platform.Lib.DevExpress.2.0.20150224.0\lib\Net\DevExpress.XtraTreeList.v7.1.dll True - - ..\packages\SharpZipLib.JetBrains.Stripped.0.86.20150204.1\lib\20\ICSharpCode.SharpZipLib.dll + + ..\packages\SharpZipLib.JetBrains.Stripped.0.87.20161027.6\lib\net40\ICSharpCode.SharpZipLib.dll True ..\packages\DotNetZip.Reduced.1.9.1.8\lib\net20\Ionic.Zip.Reduced.dll True - - ..\packages\JetBrains.Annotations.10.1.5\lib\net\JetBrains.Annotations.dll + + ..\packages\JetBrains.Annotations.10.4.0\lib\net\JetBrains.Annotations.dll + True + + + ..\packages\JetBrains.Platform.MSBuild.Logger.1.0.20170130.0\lib\net\JetBrains.MSBuild.Logger.dll + True + True + + + ..\packages\JetBrains.System.Reflection.Metadata.1.0.0\lib\net45\JetBrains.System.Reflection.Metadata.dll + True + + + ..\packages\JetBrains.MahApps.Metro.1.3.1\lib\net45\MahApps.Metro.dll True @@ -86,6 +99,26 @@ ..\packages\JetBrains.Platform.Lib.Microsoft.Deployment.Compression.Cab.2.0.20140304.0\lib\Microsoft.Deployment.Compression.Cab.dll True + + ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll + True + + + ..\packages\Microsoft.Owin.FileSystems.3.0.1\lib\net45\Microsoft.Owin.FileSystems.dll + True + + + ..\packages\Microsoft.Owin.Host.HttpListener.3.0.1\lib\net45\Microsoft.Owin.Host.HttpListener.dll + True + + + ..\packages\Microsoft.Owin.Hosting.3.0.1\lib\net45\Microsoft.Owin.Hosting.dll + True + + + ..\packages\Microsoft.Owin.StaticFiles.3.0.1\lib\net45\Microsoft.Owin.StaticFiles.dll + True + ..\packages\Microsoft.Web.Xdt.2.1.1\lib\net40\Microsoft.Web.XmlTransform.dll True @@ -98,20 +131,100 @@ ..\packages\Windows7APICodePack.JetBrains.Stripped.1.1.20150225.0\lib\Net\Microsoft.WindowsAPICodePack.Shell.dll True - - ..\packages\JetBrains.Mono.Posix.0.1\lib\net40\Mono.Posix.dll + + ..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll True - - ..\packages\NetMQ.3.3.3.1\lib\net40\NetMQ.dll + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Client.dll True - - ..\packages\Newtonsoft35.Json.7.0.1\lib\net35\Newtonsoft.Json.dll + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Commands.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Common.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Configuration.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.ContentModel.dll + True + + + ..\packages\JetBrains.NuGet.Core.2.14.1\lib\net40-Client\NuGet.Core.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.DependencyResolver.Core.dll + True + + + ..\packages\JetBrains.NuGet.Frameworks.4.0.0\lib\net45\NuGet.Frameworks.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.LibraryModel.dll True - - ..\packages\NuGet.Core.2.12.0\lib\net40-Client\NuGet.Core.dll + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.PackageManagement.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Packaging.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Packaging.Core.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Packaging.Core.Types.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.ProjectManagement.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.ProjectModel.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Protocol.Core.Types.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Protocol.Core.v2.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Protocol.Core.v3.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Protocol.VisualStudio.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Repositories.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.Resolver.dll + True + + + ..\packages\JetBrains.NuGet.Ultimate.4.0.0\lib\net45\NuGet.RuntimeModel.dll + True + + + ..\packages\JetBrains.NuGet.Versioning.4.0.0\lib\net45\NuGet.Versioning.dll True @@ -122,22 +235,41 @@ ..\packages\NVelocity.1.0.3\lib\NVelocity.dll True + + ..\packages\Owin.1.0\lib\net40\Owin.dll + True + - - ..\packages\Sprache.JetBrains.2.0.0.44\lib\portable-net4+netcore45+win8+wp8+sl5+MonoAndroid1+MonoTouch1\Sprache.dll + + ..\packages\sharpcompress.0.11.6\lib\net40\SharpCompress.dll + True + + + ..\packages\Sprache.JetBrains.2.1.0\lib\net40\Sprache.dll True + - - - ..\packages\JetBrains.Platform.Lib.System.Windows.Interactivity.2.0.20140318.0\lib\System.Windows.Interactivity.dll + + + + + + + + ..\packages\JetBrains.Platform.Lib.System.Windows.Interactivity.3.0.40218\lib\System.Windows.Interactivity.dll True - + + + + + + ..\packages\Vestris.ResourceLib.JetBrains.1.4.20150303.0\lib\Net\Vestris.ResourceLib.dll True @@ -152,11 +284,11 @@ True - ..\packages\xunit.abstractions.JetBrains.2.0.0\lib\net35\xunit.abstractions.dll + ..\packages\xunit.abstractions.2.0.1\lib\net35\xunit.abstractions.dll True - - ..\packages\xunit.runner.utility.JetBrains.2.2.0\lib\net35\xunit.runner.utility.desktop.dll + + ..\packages\xunit.runner.utility.2.2.0\lib\net35\xunit.runner.utility.net35.dll True @@ -230,47 +362,48 @@ CleanCode.nuspec + Designer - - - + - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs index ba8d649..cf9a714 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/ChainedReferencesCheck.cs @@ -18,7 +18,7 @@ public class ChainedReferencesCheck : ElementProblemAnalyzer { protected override void Run(ICSharpStatement element, ElementProblemAnalyzerData data, IHighlightingConsumer consumer) { - if (!element.IsEmbeddedStatement) + if (!element.CanBeEmbedded) { var threshold = data.SettingsStore.GetValue((CleanCodeSettings s) => s.MaximumChainedReferences); HighlightMethodChainsThatAreTooLong(element, consumer, threshold); diff --git a/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs b/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs index b09aa52..5b8ae6c 100644 --- a/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/ChainedReferences/MaximumChainedReferencesHighlighting.cs @@ -6,7 +6,7 @@ [assembly: RegisterConfigurableSeverity(MaximumChainedReferencesHighlighting.SeverityID, null, CleanCodeHighlightingGroupIds.CleanCode, "Too many chained references", "Too many chained references can break the Law of Demeter.", - Severity.WARNING, false)] + Severity.WARNING)] namespace CleanCode.Features.ChainedReferences { diff --git a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs index 5a06983..d417805 100644 --- a/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/ClassTooBig/ClassTooBigHighlighting.cs @@ -6,7 +6,7 @@ [assembly: RegisterConfigurableSeverity(ClassTooBigHighlighting.SeverityID, null, CleanCodeHighlightingGroupIds.CleanCode, "Class too big", "This class contains too many methods", - Severity.SUGGESTION, false)] + Severity.SUGGESTION)] namespace CleanCode.Features.ClassTooBig { diff --git a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs index 23df5f2..e2ddaa9 100644 --- a/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/ComplexExpression/ComplexConditionExpressionHighlighting.cs @@ -7,7 +7,7 @@ [assembly:RegisterConfigurableSeverity(ComplexConditionExpressionHighlighting.SeverityID, null, CleanCodeHighlightingGroupIds.CleanCode, "Condition expression too complex", "The expression in the condition is too complex.", - Severity.WARNING, false)] + Severity.WARNING)] namespace CleanCode.Features.ComplexExpression { diff --git a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs index bb12f4e..7292d80 100644 --- a/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/ExcessiveIndentation/ExcessiveIndentHighlighting.cs @@ -7,7 +7,7 @@ [assembly:RegisterConfigurableSeverity(ExcessiveIndentHighlighting.SeverityID, null, CleanCodeHighlightingGroupIds.CleanCode, "Excessive indentation", "The nesting in this method is excessive.", - Severity.WARNING, false)] + Severity.WARNING)] namespace CleanCode.Features.ExcessiveIndentation { diff --git a/CleanCode/src/CleanCode/Features/ExtensionMethods.cs b/CleanCode/src/CleanCode/Features/ExtensionMethods.cs index 1f3ade0..06bfdc5 100644 --- a/CleanCode/src/CleanCode/Features/ExtensionMethods.cs +++ b/CleanCode/src/CleanCode/Features/ExtensionMethods.cs @@ -132,9 +132,6 @@ private static IType TryGetClosedReturnTypeFromReference(IReference reference) { var resolveResultWithInfo = GetResolveResult(reference); - if (reference.CurrentResolveResult == null) - reference.Resolve(); - var declaredElement = resolveResultWithInfo.DeclaredElement; var parametersOwner = declaredElement as IParametersOwner; @@ -155,11 +152,6 @@ private static IType GetClosedType(ResolveResultWithInfo resolveResultWithInfo, public static ResolveResultWithInfo GetResolveResult(this IReference reference) { - if (reference.CurrentResolveResult != null) - { - return reference.CurrentResolveResult; - } - return reference.Resolve(); } } diff --git a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs index a76cc22..084b01c 100644 --- a/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/FlagArguments/FlagArgumentsHighlighting.cs @@ -7,7 +7,7 @@ [assembly: RegisterConfigurableSeverity(FlagArgumentsHighlighting.SeverityID, null, CleanCodeHighlightingGroupIds.CleanCode, "Flag argument", "An argument that is used as a flag.", - Severity.WARNING, false)] + Severity.WARNING)] namespace CleanCode.Features.FlagArguments { diff --git a/CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs b/CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs index adbc538..d3750b2 100644 --- a/CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/HollowNames/HollowTypeNameHighlighting.cs @@ -6,7 +6,7 @@ [assembly: RegisterConfigurableSeverity(HollowTypeNameHighlighting.SeverityID, null, CleanCodeHighlightingGroupIds.CleanCode, "Hollow type name", "This type has a name that doesn't express its intent.", - Severity.SUGGESTION, false)] + Severity.SUGGESTION)] namespace CleanCode.Features.HollowNames { diff --git a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs index 5eb9160..20c297b 100644 --- a/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/MethodNameNotMeaningful/MethodNameNotMeaningfulHighlighting.cs @@ -8,7 +8,7 @@ [assembly: RegisterConfigurableSeverity(MethodNameNotMeaningfulHighlighting.SeverityID, null, CleanCodeHighlightingGroupIds.CleanCode, "Method name not meaningful", "This method name is too short to be meaningful.", - Severity.WARNING, false)] + Severity.WARNING)] namespace CleanCode.Features.MethodNameNotMeaningful { diff --git a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs index 3d1e0c6..8645138 100644 --- a/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/MethodTooLong/MethodTooLongHighlighting.cs @@ -7,7 +7,7 @@ [assembly: RegisterConfigurableSeverity(MethodTooLongHighlighting.SeverityID, null, CleanCodeHighlightingGroupIds.CleanCode, "Method too long", "The method is bigger than it should be.", - Severity.SUGGESTION, false)] + Severity.SUGGESTION)] namespace CleanCode.Features.MethodTooLong { diff --git a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs index 4b4492d..909760c 100644 --- a/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/TooManyDependencies/TooManyDependenciesHighlighting.cs @@ -7,7 +7,7 @@ [assembly: RegisterConfigurableSeverity(TooManyDependenciesHighlighting.SeverityID, null, CleanCodeHighlightingGroupIds.CleanCode, "Too many dependencies", "Too many dependencies passed into constructor.", - Severity.WARNING, false)] + Severity.WARNING)] namespace CleanCode.Features.TooManyDependencies { diff --git a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs index 2075a63..1465da9 100644 --- a/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs +++ b/CleanCode/src/CleanCode/Features/TooManyMethodArguments/TooManyArgumentsHighlighting.cs @@ -6,7 +6,7 @@ [assembly: RegisterConfigurableSeverity(TooManyArgumentsHighlighting.SeverityID, null, CleanCodeHighlightingGroupIds.CleanCode, "Too many arguments", "Too many arguments passed to a method.", - Severity.WARNING, false)] + Severity.WARNING)] namespace CleanCode.Features.TooManyMethodArguments { diff --git a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs index a402089..e95eb3d 100644 --- a/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs +++ b/CleanCode/src/CleanCode/Properties/AssemblyInfo.cs @@ -12,5 +12,5 @@ [assembly: ComVisible(false)] [assembly: Guid("97927FF9-8C9C-4DC5-A309-29C23F41DA47")] -[assembly: AssemblyVersion("5.0.3.0")] -[assembly: AssemblyFileVersion("5.0.3.0")] +[assembly: AssemblyVersion("5.1.0.0")] +[assembly: AssemblyFileVersion("5.1.0.0")] diff --git a/CleanCode/src/CleanCode/packages.config b/CleanCode/src/CleanCode/packages.config index 184d2a5..bf0f33c 100644 --- a/CleanCode/src/CleanCode/packages.config +++ b/CleanCode/src/CleanCode/packages.config @@ -1,49 +1,59 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file