diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexCondition.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexCondition.kt index bc5b5a9d2..29303b993 100644 --- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexCondition.kt +++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexCondition.kt @@ -5,10 +5,12 @@ import io.gitlab.arturbosch.detekt.api.Debt import io.gitlab.arturbosch.detekt.api.Entity import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Metric +import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity -import io.gitlab.arturbosch.detekt.api.ThresholdRule import io.gitlab.arturbosch.detekt.api.ThresholdedCodeSmell import io.gitlab.arturbosch.detekt.api.internal.ActiveByDefault +import io.gitlab.arturbosch.detekt.api.internal.Configuration +import io.gitlab.arturbosch.detekt.api.internal.config import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtDoWhileExpression import org.jetbrains.kotlin.psi.KtExpression @@ -36,14 +38,11 @@ import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType * * fun hasCorrectEnding() = return !str.endsWith("foo") && !str.endsWith("bar") && !str.endsWith("_") * - * - * @configuration threshold - the number of conditions which will trigger the rule (default: `4`) */ @ActiveByDefault(since = "1.0.0") class ComplexCondition( - config: Config = Config.empty, - threshold: Int = DEFAULT_CONDITIONS_COUNT -) : ThresholdRule(config, threshold) { + config: Config = Config.empty +) : Rule(config) { override val issue = Issue( "ComplexCondition", @@ -52,6 +51,9 @@ class ComplexCondition( Debt.TWENTY_MINS ) + @Configuration("the number of conditions which will trigger the rule") + private val threshold: Int by config(defaultValue = 4) + override fun visitIfExpression(expression: KtIfExpression) { val condition = expression.condition checkIfComplex(condition) @@ -108,8 +110,4 @@ class ComplexCondition( return count } - - companion object { - const val DEFAULT_CONDITIONS_COUNT = 4 - } } diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexInterface.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexInterface.kt index d23d4328d..0c4da255e 100644 --- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexInterface.kt +++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexInterface.kt @@ -5,9 +5,11 @@ import io.gitlab.arturbosch.detekt.api.Debt import io.gitlab.arturbosch.detekt.api.Entity import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Metric +import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity -import io.gitlab.arturbosch.detekt.api.ThresholdRule import io.gitlab.arturbosch.detekt.api.ThresholdedCodeSmell +import io.gitlab.arturbosch.detekt.api.internal.Configuration +import io.gitlab.arturbosch.detekt.api.internal.config import io.gitlab.arturbosch.detekt.rules.companionObject import org.jetbrains.kotlin.com.intellij.psi.PsiElement import org.jetbrains.kotlin.psi.KtClass @@ -25,15 +27,10 @@ import org.jetbrains.kotlin.psi.psiUtil.isPrivate * * Large interfaces should be split into smaller interfaces which have a clear responsibility and are easier * to understand and implement. - * - * @configuration threshold - the amount of definitions in an interface to trigger the rule (default: `10`) - * @configuration includeStaticDeclarations - whether static declarations should be included (default: `false`) - * @configuration includePrivateDeclarations - whether private declarations should be included (default: `false`) */ class ComplexInterface( config: Config = Config.empty, - threshold: Int = DEFAULT_LARGE_INTERFACE_COUNT -) : ThresholdRule(config, threshold) { +) : Rule(config) { override val issue = Issue( javaClass.simpleName, @@ -45,8 +42,14 @@ class ComplexInterface( Debt.TWENTY_MINS ) - private val includeStaticDeclarations = valueOrDefault(INCLUDE_STATIC_DECLARATIONS, false) - private val includePrivateDeclarations = valueOrDefault(INCLUDE_PRIVATE_DECLARATIONS, false) + @Configuration("the amount of definitions in an interface to trigger the rule") + private val threshold: Int by config(defaultValue = 10) + + @Configuration("whether static declarations should be included") + private val includeStaticDeclarations: Boolean by config(defaultValue = false) + + @Configuration("whether private declarations should be included") + private val includePrivateDeclarations: Boolean by config(defaultValue = false) override fun visitClass(klass: KtClass) { if (klass.isInterface()) { @@ -84,10 +87,4 @@ class ComplexInterface( .filter(PsiElement::considerPrivate) .count(PsiElement::isMember) } - - companion object { - const val INCLUDE_STATIC_DECLARATIONS = "includeStaticDeclarations" - const val INCLUDE_PRIVATE_DECLARATIONS = "includePrivateDeclarations" - const val DEFAULT_LARGE_INTERFACE_COUNT = 10 - } } diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexMethod.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexMethod.kt index e0c34fa67..6fd52d0fc 100644 --- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexMethod.kt +++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexMethod.kt @@ -40,8 +40,15 @@ import org.jetbrains.kotlin.psi.KtWhenExpression @ActiveByDefault(since = "1.0.0") class ComplexMethod(config: Config = Config.empty) : Rule(config) { + override val issue = Issue( + "ComplexMethod", + Severity.Maintainability, + "Prefer splitting up complex methods into smaller, easier to understand methods.", + Debt.TWENTY_MINS + ) + @Configuration("McCabe's Cyclomatic Complexity (MCC) number for a method.") - private val threshold: Int by config(DEFAULT_THRESHOLD_METHOD_COMPLEXITY) + private val threshold: Int by config(defaultValue = 15) @Configuration("Ignores a complex method if it only contains a single when expression.") private val ignoreSingleWhenExpression: Boolean by config(false) @@ -55,13 +62,6 @@ class ComplexMethod(config: Config = Config.empty) : Rule(config) { @Configuration("Comma separated list of function names which add complexity.") private val nestingFunctions: Set by config(DEFAULT_NESTING_FUNCTIONS) { it.toSet() } - override val issue = Issue( - "ComplexMethod", - Severity.Maintainability, - "Prefer splitting up complex methods into smaller, easier to understand methods.", - Debt.TWENTY_MINS - ) - override fun visitNamedFunction(function: KtNamedFunction) { if (ignoreSingleWhenExpression && hasSingleWhenExpression(function.bodyExpression)) { return @@ -100,7 +100,6 @@ class ComplexMethod(config: Config = Config.empty) : Rule(config) { this is KtReturnExpression && this.returnedExpression is KtWhenExpression companion object { - const val DEFAULT_THRESHOLD_METHOD_COMPLEXITY = 15 val DEFAULT_NESTING_FUNCTIONS = listOf( "run", "let", diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LabeledExpression.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LabeledExpression.kt index a7d7e4c7c..81cec9b67 100644 --- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LabeledExpression.kt +++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LabeledExpression.kt @@ -7,7 +7,8 @@ import io.gitlab.arturbosch.detekt.api.Entity import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity -import io.gitlab.arturbosch.detekt.api.internal.valueOrDefaultCommaSeparated +import io.gitlab.arturbosch.detekt.api.internal.Configuration +import io.gitlab.arturbosch.detekt.api.internal.config import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtExpressionWithLabel @@ -57,9 +58,6 @@ import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration * } * } * - * - * @configuration ignoredLabels - allows to provide a list of label names which should be ignored by this rule - * (default: `[]`) */ class LabeledExpression(config: Config = Config.empty) : Rule(config) { @@ -70,14 +68,16 @@ class LabeledExpression(config: Config = Config.empty) : Rule(config) { Debt.TWENTY_MINS ) - private val ignoredLabels = valueOrDefaultCommaSeparated(IGNORED_LABELS, emptyList()) - .map { it.removePrefix("*").removeSuffix("*") } + @Configuration("allows to provide a list of label names which should be ignored by this rule") + private val ignoredLabels: List by config(listOf()) { list -> + list.map { it.removePrefix("*").removeSuffix("*") } + } override fun visitExpressionWithLabel(expression: KtExpressionWithLabel) { super.visitExpressionWithLabel(expression) if (expression !is KtThisExpression || isNotReferencingOuterClass(expression)) { expression.getLabelName()?.let { labelName -> - if (!ignoredLabels.any { labelName.contains(it, ignoreCase = true) }) { + if (ignoredLabels.none { labelName.contains(it, ignoreCase = true) }) { report(CodeSmell(issue, Entity.from(expression), issue.description)) } } @@ -104,8 +104,4 @@ class LabeledExpression(config: Config = Config.empty) : Rule(config) { classes.add(containingClass) getClassHierarchy(containingClass, classes) } - - companion object { - const val IGNORED_LABELS = "ignoredLabels" - } } diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LargeClass.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LargeClass.kt index f2c6df90c..2f41d4d17 100644 --- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LargeClass.kt +++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LargeClass.kt @@ -6,10 +6,12 @@ import io.gitlab.arturbosch.detekt.api.Debt import io.gitlab.arturbosch.detekt.api.Entity import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Metric +import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity -import io.gitlab.arturbosch.detekt.api.ThresholdRule import io.gitlab.arturbosch.detekt.api.ThresholdedCodeSmell import io.gitlab.arturbosch.detekt.api.internal.ActiveByDefault +import io.gitlab.arturbosch.detekt.api.internal.Configuration +import io.gitlab.arturbosch.detekt.api.internal.config import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType @@ -21,14 +23,9 @@ import java.util.IdentityHashMap * the class does instead handle multiple responsibilities. Instead of doing many things at once prefer to * split up large classes into smaller classes. These smaller classes are then easier to understand and handle less * things. - * - * @configuration threshold - the size of class required to trigger the rule (default: `600`) */ @ActiveByDefault(since = "1.0.0") -class LargeClass( - config: Config = Config.empty, - threshold: Int = DEFAULT_THRESHOLD_CLASS_LENGTH -) : ThresholdRule(config, threshold) { +class LargeClass(config: Config = Config.empty) : Rule(config) { override val issue = Issue( "LargeClass", @@ -38,6 +35,9 @@ class LargeClass( Debt.TWENTY_MINS ) + @Configuration("the size of class required to trigger the rule") + private val threshold: Int by config(defaultValue = 600) + private val classToLinesCache = IdentityHashMap() private val nestedClassTracking = IdentityHashMap>() @@ -80,8 +80,4 @@ class LargeClass( nestedClasses = nestedClasses.mapNotNull { nestedClassTracking[it] }.flattenTo(HashSet()) } } - - companion object { - const val DEFAULT_THRESHOLD_CLASS_LENGTH = 600 - } } diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongMethod.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongMethod.kt index c95c14d8d..f9e8a391b 100644 --- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongMethod.kt +++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongMethod.kt @@ -6,10 +6,12 @@ import io.gitlab.arturbosch.detekt.api.Debt import io.gitlab.arturbosch.detekt.api.Entity import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Metric +import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity -import io.gitlab.arturbosch.detekt.api.ThresholdRule import io.gitlab.arturbosch.detekt.api.ThresholdedCodeSmell import io.gitlab.arturbosch.detekt.api.internal.ActiveByDefault +import io.gitlab.arturbosch.detekt.api.internal.Configuration +import io.gitlab.arturbosch.detekt.api.internal.config import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType @@ -21,14 +23,9 @@ import java.util.IdentityHashMap * Prefer smaller methods with clear names that describe their functionality clearly. * * Extract parts of the functionality of long methods into separate, smaller methods. - * - * @configuration threshold - number of lines in a method to trigger the rule (default: `60`) */ @ActiveByDefault(since = "1.0.0") -class LongMethod( - config: Config = Config.empty, - threshold: Int = DEFAULT_THRESHOLD_METHOD_LENGTH -) : ThresholdRule(config, threshold) { +class LongMethod(config: Config = Config.empty) : Rule(config) { override val issue = Issue( "LongMethod", @@ -38,6 +35,9 @@ class LongMethod( Debt.TWENTY_MINS ) + @Configuration("number of lines in a method to trigger the rule") + private val threshold: Int by config(defaultValue = 60) + private val functionToLinesCache = HashMap() private val functionToBodyLinesCache = HashMap() private val nestedFunctionTracking = IdentityHashMap>() @@ -91,8 +91,4 @@ class LongMethod( nestedFunctions = nestedFunctions.mapNotNull { nestedFunctionTracking[it] }.flattenTo(HashSet()) } } - - companion object { - const val DEFAULT_THRESHOLD_METHOD_LENGTH = 60 - } } diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongParameterList.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongParameterList.kt index d548e1977..5c49f22d6 100644 --- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongParameterList.kt +++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongParameterList.kt @@ -10,7 +10,9 @@ import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity import io.gitlab.arturbosch.detekt.api.ThresholdedCodeSmell import io.gitlab.arturbosch.detekt.api.internal.ActiveByDefault -import io.gitlab.arturbosch.detekt.api.internal.valueOrDefaultCommaSeparated +import io.gitlab.arturbosch.detekt.api.internal.Configuration +import io.gitlab.arturbosch.detekt.api.internal.config +import io.gitlab.arturbosch.detekt.api.internal.configWithFallback import io.gitlab.arturbosch.detekt.rules.isOverride import org.jetbrains.kotlin.psi.KtAnnotated import org.jetbrains.kotlin.psi.KtClass @@ -25,22 +27,9 @@ import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject /** * Reports functions and constructors which have more parameters than a certain threshold. - * - * @configuration threshold - number of parameters required to trigger the rule (default: `6`) - * (deprecated: "Use `functionThreshold` and `constructorThreshold` instead") - * @configuration functionThreshold - number of function parameters required to trigger the rule (default: `6`) - * @configuration constructorThreshold - number of constructor parameters required to trigger the rule (default: `7`) - * @configuration ignoreDefaultParameters - ignore parameters that have a default value (default: `false`) - * @configuration ignoreDataClasses - ignore long constructor parameters list for data classes (default: `true`) - * @configuration ignoreAnnotated - ignore long parameters list for constructors or functions in the context of these - * annotation class names (default: `[]`); (e.g. ['Inject', 'Module', 'Suppress']); - * the most common case is for dependency injection where constructors are annotated with @Inject. */ @ActiveByDefault(since = "1.0.0") -class LongParameterList( - config: Config = Config.empty -) : Rule(config) { - +class LongParameterList(config: Config = Config.empty) : Rule(config) { override val issue = Issue( "LongParameterList", Severity.Maintainability, @@ -50,18 +39,37 @@ class LongParameterList( Debt.TWENTY_MINS ) - private val functionThreshold: Int = - valueOrDefault(FUNCTION_THRESHOLD, valueOrDefault(THRESHOLD, DEFAULT_FUNCTION_THRESHOLD)) + @Suppress("unused") + @Deprecated("Use `functionThreshold` and `constructorThreshold` instead") + @Configuration("number of parameters required to trigger the rule") + private val threshold: Int by config(DEFAULT_FUNCTION_THRESHOLD) - private val constructorThreshold: Int = - valueOrDefault(CONSTRUCTOR_THRESHOLD, valueOrDefault(THRESHOLD, DEFAULT_CONSTRUCTOR_THRESHOLD)) + @Configuration("number of function parameters required to trigger the rule") + private val functionThreshold: Int by configWithFallback( + fallbackPropertyName = "threshold", + defaultValue = DEFAULT_FUNCTION_THRESHOLD + ) - private val ignoreDefaultParameters = valueOrDefault(IGNORE_DEFAULT_PARAMETERS, false) + @Configuration("number of constructor parameters required to trigger the rule") + private val constructorThreshold: Int by configWithFallback( + fallbackPropertyName = "threshold", + defaultValue = DEFAULT_CONSTRUCTOR_THRESHOLD + ) - private val ignoreDataClasses = valueOrDefault(IGNORE_DATA_CLASSES, true) + @Configuration("ignore parameters that have a default value") + private val ignoreDefaultParameters: Boolean by config(defaultValue = false) - private val ignoreAnnotated = valueOrDefaultCommaSeparated(IGNORE_ANNOTATED, emptyList()) - .map { it.removePrefix("*").removeSuffix("*") } + @Configuration("ignore long constructor parameters list for data classes") + private val ignoreDataClasses: Boolean by config(defaultValue = true) + + @Configuration( + "ignore long parameters list for constructors or functions in the " + + "context of these annotation class names; (e.g. ['Inject', 'Module', 'Suppress']); " + + "the most common case is for dependency injection where constructors are annotated with `@Inject`." + ) + private val ignoreAnnotated: List by config(listOf()) { list -> + list.map { it.removePrefix("*").removeSuffix("*") } + } private lateinit var annotationExcluder: AnnotationExcluder @@ -131,14 +139,7 @@ class LongParameterList( } companion object { - const val THRESHOLD = "threshold" - const val FUNCTION_THRESHOLD = "functionThreshold" - const val CONSTRUCTOR_THRESHOLD = "constructorThreshold" - const val IGNORE_DEFAULT_PARAMETERS = "ignoreDefaultParameters" - const val IGNORE_DATA_CLASSES = "ignoreDataClasses" - const val IGNORE_ANNOTATED = "ignoreAnnotated" - - const val DEFAULT_FUNCTION_THRESHOLD = 6 - const val DEFAULT_CONSTRUCTOR_THRESHOLD = 7 + private const val DEFAULT_FUNCTION_THRESHOLD = 6 + private const val DEFAULT_CONSTRUCTOR_THRESHOLD = 7 } } diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/MethodOverloading.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/MethodOverloading.kt index c302fa831..8bb72ffe0 100644 --- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/MethodOverloading.kt +++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/MethodOverloading.kt @@ -6,9 +6,11 @@ import io.gitlab.arturbosch.detekt.api.DetektVisitor import io.gitlab.arturbosch.detekt.api.Entity import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Metric +import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity -import io.gitlab.arturbosch.detekt.api.ThresholdRule import io.gitlab.arturbosch.detekt.api.ThresholdedCodeSmell +import io.gitlab.arturbosch.detekt.api.internal.Configuration +import io.gitlab.arturbosch.detekt.api.internal.config import io.gitlab.arturbosch.detekt.rules.isOverride import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtEnumEntry @@ -23,13 +25,8 @@ import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration * Method overloading tightly couples these methods together which might make the code harder to understand. * * Refactor these methods and try to use optional parameters instead to prevent some of the overloading. - * - * @configuration threshold - number of overloads which will trigger the rule (default: `6`) */ -class MethodOverloading( - config: Config = Config.empty, - threshold: Int = DEFAULT_THRESHOLD_OVERLOAD_COUNT -) : ThresholdRule(config, threshold) { +class MethodOverloading(config: Config = Config.empty) : Rule(config) { override val issue = Issue( "MethodOverloading", @@ -40,6 +37,9 @@ class MethodOverloading( Debt.TWENTY_MINS ) + @Configuration("number of overloads which will trigger the rule") + private val threshold: Int by config(defaultValue = 6) + override fun visitKtFile(file: KtFile) { val visitor = OverloadedMethodVisitor() file.getChildrenOfType().forEach { visitor.visitMethod(it) } @@ -93,8 +93,4 @@ class MethodOverloading( private fun KtNamedFunction.isOverriddenInsideEnumEntry() = containingClass() is KtEnumEntry && isOverride() } - - companion object { - const val DEFAULT_THRESHOLD_OVERLOAD_COUNT = 6 - } } diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArguments.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArguments.kt index f7930795f..e6e3a4c2e 100644 --- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArguments.kt +++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArguments.kt @@ -5,9 +5,11 @@ import io.gitlab.arturbosch.detekt.api.Config import io.gitlab.arturbosch.detekt.api.Debt import io.gitlab.arturbosch.detekt.api.Entity import io.gitlab.arturbosch.detekt.api.Issue +import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity -import io.gitlab.arturbosch.detekt.api.ThresholdRule +import io.gitlab.arturbosch.detekt.api.internal.Configuration import io.gitlab.arturbosch.detekt.api.internal.RequiresTypeResolution +import io.gitlab.arturbosch.detekt.api.internal.config import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtLambdaArgument import org.jetbrains.kotlin.resolve.BindingContext @@ -28,22 +30,20 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall * } * sum(a = 1, b = 2, c = 3, d = 4) * - * - * @configuration threshold - number of parameters that triggers this inspection (default: `3`) */ @RequiresTypeResolution -class NamedArguments( - config: Config = Config.empty, - threshold: Int = DEFAULT_FUNCTION_THRESHOLD -) : ThresholdRule(config, threshold) { +class NamedArguments(config: Config = Config.empty) : Rule(config) { override val issue = Issue( "NamedArguments", Severity.Maintainability, - "Function invocation with more than $threshold parameters must all be named", + "Parameters of function invocation must all be named", Debt.FIVE_MINS ) + @Configuration("number of parameters that triggers this inspection") + private val threshold: Int by config(defaultValue = 3) + override fun visitCallExpression(expression: KtCallExpression) { if (bindingContext == BindingContext.EMPTY) return val valueArguments = expression.valueArguments @@ -64,8 +64,4 @@ class NamedArguments( resolvedCall.getParameterForArgument(it)?.varargElementType == null || it.getSpreadElement() != null } } - - companion object { - const val DEFAULT_FUNCTION_THRESHOLD = 3 - } } diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NestedBlockDepth.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NestedBlockDepth.kt index b66331207..3ffa22a12 100644 --- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NestedBlockDepth.kt +++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NestedBlockDepth.kt @@ -6,10 +6,12 @@ import io.gitlab.arturbosch.detekt.api.DetektVisitor import io.gitlab.arturbosch.detekt.api.Entity import io.gitlab.arturbosch.detekt.api.Issue import io.gitlab.arturbosch.detekt.api.Metric +import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity -import io.gitlab.arturbosch.detekt.api.ThresholdRule import io.gitlab.arturbosch.detekt.api.ThresholdedCodeSmell import io.gitlab.arturbosch.detekt.api.internal.ActiveByDefault +import io.gitlab.arturbosch.detekt.api.internal.Configuration +import io.gitlab.arturbosch.detekt.api.internal.config import io.gitlab.arturbosch.detekt.rules.isUsedForNesting import org.jetbrains.kotlin.psi.KtCallExpression import org.jetbrains.kotlin.psi.KtContainerNodeForControlStructureBody @@ -25,14 +27,9 @@ import org.jetbrains.kotlin.psi.KtWhenExpression * its hidden complexity. It might become harder to understand edge-cases of the function. * * Prefer extracting the nested code into well-named functions to make it easier to understand. - * - * @configuration threshold - the nested depth required to trigger rule (default: `4`) */ @ActiveByDefault(since = "1.0.0") -class NestedBlockDepth( - config: Config = Config.empty, - threshold: Int = DEFAULT_THRESHOLD_NESTING -) : ThresholdRule(config, threshold) { +class NestedBlockDepth(config: Config = Config.empty) : Rule(config) { override val issue = Issue( "NestedBlockDepth", @@ -42,6 +39,9 @@ class NestedBlockDepth( Debt.TWENTY_MINS ) + @Configuration("the nested depth required to trigger rule") + private val threshold: Int by config(defaultValue = 4) + override fun visitNamedFunction(function: KtNamedFunction) { val visitor = FunctionDepthVisitor(threshold) visitor.visitNamedFunction(function) @@ -122,8 +122,4 @@ class NestedBlockDepth( } } } - - companion object { - const val DEFAULT_THRESHOLD_NESTING = 4 - } } diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/StringLiteralDuplication.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/StringLiteralDuplication.kt index 55ec640e2..552cd7d71 100644 --- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/StringLiteralDuplication.kt +++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/StringLiteralDuplication.kt @@ -5,11 +5,12 @@ import io.gitlab.arturbosch.detekt.api.Debt import io.gitlab.arturbosch.detekt.api.DetektVisitor import io.gitlab.arturbosch.detekt.api.Entity import io.gitlab.arturbosch.detekt.api.Issue -import io.gitlab.arturbosch.detekt.api.LazyRegex import io.gitlab.arturbosch.detekt.api.Metric +import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity -import io.gitlab.arturbosch.detekt.api.ThresholdRule import io.gitlab.arturbosch.detekt.api.ThresholdedCodeSmell +import io.gitlab.arturbosch.detekt.api.internal.Configuration +import io.gitlab.arturbosch.detekt.api.internal.config import io.gitlab.arturbosch.detekt.rules.isPartOf import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.psi.KtFile @@ -41,16 +42,8 @@ import org.jetbrains.kotlin.psi.psiUtil.plainContent * } * } * - * - * @configuration threshold - amount of duplications to trigger rule (default: `3`) - * @configuration ignoreAnnotation - if values in Annotations should be ignored (default: `true`) - * @configuration excludeStringsWithLessThan5Characters - if short strings should be excluded (default: `true`) - * @configuration ignoreStringsRegex - RegEx of Strings that should be ignored (default: `'$^'`) */ -class StringLiteralDuplication( - config: Config = Config.empty, - threshold: Int = DEFAULT_DUPLICATION -) : ThresholdRule(config, threshold) { +class StringLiteralDuplication(config: Config = Config.empty) : Rule(config) { override val issue = Issue( javaClass.simpleName, @@ -59,9 +52,17 @@ class StringLiteralDuplication( Debt.FIVE_MINS ) - private val ignoreAnnotation = valueOrDefault(IGNORE_ANNOTATION, true) - private val excludeStringsWithLessThan5Characters = valueOrDefault(EXCLUDE_SHORT_STRING, true) - private val ignoreStringsRegex by LazyRegex(IGNORE_STRINGS_REGEX, "$^") + @Configuration("amount of duplications to trigger rule") + private val threshold: Int by config(defaultValue = 3) + + @Configuration("if values in Annotations should be ignored") + private val ignoreAnnotation: Boolean by config(true) + + @Configuration("if short strings should be excluded") + private val excludeStringsWithLessThan5Characters: Boolean by config(true) + + @Configuration("RegEx of Strings that should be ignored") + private val ignoreStringsRegex: Regex by config("$^", String::toRegex) override fun visitKtFile(file: KtFile) { val visitor = StringLiteralVisitor() @@ -116,10 +117,6 @@ class StringLiteralDuplication( } companion object { - const val DEFAULT_DUPLICATION = 3 - const val STRING_EXCLUSION_LENGTH = 5 - const val IGNORE_ANNOTATION = "ignoreAnnotation" - const val EXCLUDE_SHORT_STRING = "excludeStringsWithLessThan5Characters" - const val IGNORE_STRINGS_REGEX = "ignoreStringsRegex" + private const val STRING_EXCLUSION_LENGTH = 5 } } diff --git a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctions.kt b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctions.kt index 90ee59dd0..2d6ff52ae 100644 --- a/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctions.kt +++ b/detekt-rules-complexity/src/main/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctions.kt @@ -9,6 +9,8 @@ import io.gitlab.arturbosch.detekt.api.Rule import io.gitlab.arturbosch.detekt.api.Severity import io.gitlab.arturbosch.detekt.api.ThresholdedCodeSmell import io.gitlab.arturbosch.detekt.api.internal.ActiveByDefault +import io.gitlab.arturbosch.detekt.api.internal.Configuration +import io.gitlab.arturbosch.detekt.api.internal.config import io.gitlab.arturbosch.detekt.rules.hasAnnotation import io.gitlab.arturbosch.detekt.rules.isOverride import org.jetbrains.kotlin.psi.KtClass @@ -24,15 +26,6 @@ import org.jetbrains.kotlin.psi.psiUtil.isPrivate * * Too many functions indicate a violation of the single responsibility principle. Prefer extracting functionality * which clearly belongs together in separate parts of the code. - * - * @configuration thresholdInFiles - threshold in files (default: `11`) - * @configuration thresholdInClasses - threshold in classes (default: `11`) - * @configuration thresholdInInterfaces - threshold in interfaces (default: `11`) - * @configuration thresholdInObjects - threshold in objects (default: `11`) - * @configuration thresholdInEnums - threshold in enums (default: `11`) - * @configuration ignoreDeprecated - ignore deprecated functions (default: `false`) - * @configuration ignorePrivate - ignore private functions (default: `false`) - * @configuration ignoreOverridden - ignore overridden functions (default: `false`) */ @ActiveByDefault(since = "1.0.0") class TooManyFunctions(config: Config = Config.empty) : Rule(config) { @@ -46,14 +39,29 @@ class TooManyFunctions(config: Config = Config.empty) : Rule(config) { Debt.TWENTY_MINS ) - private val thresholdInFiles = valueOrDefault(THRESHOLD_IN_FILES, DEFAULT_THRESHOLD) - private val thresholdInClasses = valueOrDefault(THRESHOLD_IN_CLASSES, DEFAULT_THRESHOLD) - private val thresholdInObjects = valueOrDefault(THRESHOLD_IN_OBJECTS, DEFAULT_THRESHOLD) - private val thresholdInInterfaces = valueOrDefault(THRESHOLD_IN_INTERFACES, DEFAULT_THRESHOLD) - private val thresholdInEnums = valueOrDefault(THRESHOLD_IN_ENUMS, DEFAULT_THRESHOLD) - private val ignoreDeprecated = valueOrDefault(IGNORE_DEPRECATED, false) - private val ignorePrivate = valueOrDefault(IGNORE_PRIVATE, false) - private val ignoreOverridden = valueOrDefault(IGNORE_OVERRIDDEN, false) + @Configuration("threshold in files") + private val thresholdInFiles: Int by config(DEFAULT_THRESHOLD) + + @Configuration("threshold in classes") + private val thresholdInClasses: Int by config(DEFAULT_THRESHOLD) + + @Configuration("threshold in interfaces") + private val thresholdInInterfaces: Int by config(DEFAULT_THRESHOLD) + + @Configuration("threshold in objects") + private val thresholdInObjects: Int by config(DEFAULT_THRESHOLD) + + @Configuration("threshold in enums") + private val thresholdInEnums: Int by config(DEFAULT_THRESHOLD) + + @Configuration("ignore deprecated functions") + private val ignoreDeprecated: Boolean by config(false) + + @Configuration("ignore private functions") + private val ignorePrivate: Boolean by config(false) + + @Configuration("ignore overridden functions") + private val ignoreOverridden: Boolean by config(false) private var amountOfTopLevelFunctions: Int = 0 @@ -160,14 +168,6 @@ class TooManyFunctions(config: Config = Config.empty) : Rule(config) { companion object { const val DEFAULT_THRESHOLD = 11 - const val THRESHOLD_IN_FILES = "thresholdInFiles" - const val THRESHOLD_IN_CLASSES = "thresholdInClasses" - const val THRESHOLD_IN_INTERFACES = "thresholdInInterfaces" - const val THRESHOLD_IN_OBJECTS = "thresholdInObjects" - const val THRESHOLD_IN_ENUMS = "thresholdInEnums" - const val IGNORE_DEPRECATED = "ignoreDeprecated" - const val IGNORE_PRIVATE = "ignorePrivate" - const val IGNORE_OVERRIDDEN = "ignoreOverridden" private const val DEPRECATED = "Deprecated" } } diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexInterfaceSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexInterfaceSpec.kt index c66616119..90c9cf1cc 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexInterfaceSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/ComplexInterfaceSpec.kt @@ -6,11 +6,18 @@ import org.assertj.core.api.Assertions.assertThat import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe +private const val THRESHOLD = 4 +private val defaultConfigMap = mapOf("threshold" to THRESHOLD) +private val staticDeclarationsConfig = TestConfig( + defaultConfigMap + ("includeStaticDeclarations" to true) +) +private val privateDeclarationsConfig = TestConfig( + defaultConfigMap + ("includePrivateDeclarations" to true) +) + class ComplexInterfaceSpec : Spek({ - val subject by memoized { ComplexInterface(threshold = THRESHOLD) } - val staticDeclarationsConfig by memoized { TestConfig(mapOf(ComplexInterface.INCLUDE_STATIC_DECLARATIONS to "true")) } - val privateDeclarationsConfig by memoized { TestConfig(mapOf(ComplexInterface.INCLUDE_PRIVATE_DECLARATIONS to "true")) } + val subject by memoized { ComplexInterface(TestConfig(defaultConfigMap)) } describe("ComplexInterface rule positives") { @@ -29,7 +36,7 @@ class ComplexInterfaceSpec : Spek({ } it("reports complex interface with includeStaticDeclarations config") { - val rule = ComplexInterface(staticDeclarationsConfig, threshold = THRESHOLD) + val rule = ComplexInterface(staticDeclarationsConfig) assertThat(rule.compileAndLint(code)).hasSize(1) } } @@ -51,7 +58,7 @@ class ComplexInterfaceSpec : Spek({ } it("reports complex interface with includeStaticDeclarations config") { - val rule = ComplexInterface(staticDeclarationsConfig, threshold = THRESHOLD) + val rule = ComplexInterface(staticDeclarationsConfig) assertThat(rule.compileAndLint(code)).hasSize(1) } } @@ -73,7 +80,7 @@ class ComplexInterfaceSpec : Spek({ } it("reports complex interface with includeStaticDeclarations config") { - val rule = ComplexInterface(staticDeclarationsConfig, threshold = THRESHOLD) + val rule = ComplexInterface(staticDeclarationsConfig) assertThat(rule.compileAndLint(code)).hasSize(1) } } @@ -93,7 +100,7 @@ class ComplexInterfaceSpec : Spek({ } it("does report complex interface with includePrivateDeclarations config") { - val rule = ComplexInterface(privateDeclarationsConfig, threshold = THRESHOLD) + val rule = ComplexInterface(privateDeclarationsConfig) assertThat(rule.compileAndLint(code)).hasSize(1) } } @@ -114,7 +121,7 @@ class ComplexInterfaceSpec : Spek({ } it("does report complex interface with includePrivateDeclarations config") { - val rule = ComplexInterface(privateDeclarationsConfig, threshold = THRESHOLD) + val rule = ComplexInterface(privateDeclarationsConfig) assertThat(rule.compileAndLint(code)).hasSize(1) } } @@ -157,5 +164,3 @@ class ComplexInterfaceSpec : Spek({ } } }) - -private const val THRESHOLD = 4 diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LabeledExpressionSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LabeledExpressionSpec.kt index 0bc72b8e4..7c63626aa 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LabeledExpressionSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LabeledExpressionSpec.kt @@ -134,7 +134,7 @@ class LabeledExpressionSpec : Spek({ loop@ for (i in 1..5) {} } """ - val config = TestConfig(mapOf(LabeledExpression.IGNORED_LABELS to listOf("loop"))) + val config = TestConfig(mapOf("ignoredLabels" to listOf("loop"))) val findings = LabeledExpression(config).compileAndLint(code) assertThat(findings).isEmpty() } @@ -145,7 +145,18 @@ class LabeledExpressionSpec : Spek({ loop@ for (i in 1..5) {} } """ - val config = TestConfig(mapOf(LabeledExpression.IGNORED_LABELS to "loop")) + val config = TestConfig(mapOf("ignoredLabels" to "loop")) + val findings = LabeledExpression(config).compileAndLint(code) + assertThat(findings).isEmpty() + } + + it("does not report excluded label config with leading and trailing wildcard") { + val code = """ + fun f() { + loop@ for (i in 1..5) {} + } + """ + val config = TestConfig(mapOf("ignoredLabels" to "*loop*,other")) val findings = LabeledExpression(config).compileAndLint(code) assertThat(findings).isEmpty() } diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LargeClassSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LargeClassSpec.kt index 39105991e..7ba8f96b9 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LargeClassSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LargeClassSpec.kt @@ -2,18 +2,21 @@ package io.gitlab.arturbosch.detekt.rules.complexity import io.github.detekt.test.utils.resourceAsPath import io.gitlab.arturbosch.detekt.api.SourceLocation +import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint import io.gitlab.arturbosch.detekt.test.lint import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe +private fun subject(threshold: Int) = LargeClass(TestConfig(mapOf("threshold" to threshold))) + class LargeClassSpec : Spek({ describe("nested classes are also considered") { it("should detect only the nested large class which exceeds threshold 70") { - val findings = LargeClass(threshold = 70).lint(resourceAsPath("NestedClasses.kt")) + val findings = subject(threshold = 70).lint(resourceAsPath("NestedClasses.kt")) assertThat(findings).hasSize(1) assertThat(findings).hasSourceLocations(SourceLocation(12, 15)) } @@ -30,7 +33,7 @@ class LargeClassSpec : Spek({ println() } """ - val rule = LargeClass(threshold = 2) + val rule = subject(threshold = 2) assertThat(rule.compileAndLint(code)).isEmpty() } } diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongMethodSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongMethodSpec.kt index 8ecfc7423..922be48d5 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongMethodSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongMethodSpec.kt @@ -1,6 +1,7 @@ package io.gitlab.arturbosch.detekt.rules.complexity import io.gitlab.arturbosch.detekt.api.ThresholdedCodeSmell +import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint import org.spekframework.spek2.Spek @@ -8,7 +9,7 @@ import org.spekframework.spek2.style.specification.describe class LongMethodSpec : Spek({ - val subject by memoized { LongMethod(threshold = 5) } + val subject by memoized { LongMethod(TestConfig(mapOf("threshold" to 5))) } describe("nested functions can be long") { diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongParameterListSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongParameterListSpec.kt index 3342cb3f7..46edf06ca 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongParameterListSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/LongParameterListSpec.kt @@ -12,8 +12,8 @@ class LongParameterListSpec : Spek({ val defaultConfig by memoized { TestConfig( mapOf( - LongParameterList.FUNCTION_THRESHOLD to defaultThreshold, - LongParameterList.CONSTRUCTOR_THRESHOLD to defaultThreshold + "functionThreshold" to defaultThreshold, + "constructorThreshold" to defaultThreshold ) ) } @@ -45,7 +45,7 @@ class LongParameterListSpec : Spek({ } it("does not report long parameter list if parameters with defaults should be ignored") { - val config = TestConfig(mapOf(LongParameterList.IGNORE_DEFAULT_PARAMETERS to "true")) + val config = TestConfig(mapOf("ignoreDefaultParameters" to "true")) val rule = LongParameterList(config) val code = "fun long(a: Int, b: Int, c: Int = 2) {}" assertThat(rule.compileAndLint(code)).isEmpty() @@ -76,7 +76,7 @@ class LongParameterListSpec : Spek({ } it("reports long parameter list if custom threshold is set") { - val config = TestConfig(mapOf(LongParameterList.CONSTRUCTOR_THRESHOLD to "1")) + val config = TestConfig(mapOf("constructorThreshold" to "1")) val rule = LongParameterList(config) val code = "class LongCtor(a: Int)" assertThat(rule.compileAndLint(code)).hasSize(1) @@ -85,8 +85,8 @@ class LongParameterListSpec : Spek({ it("does not report long parameter list for constructors of data classes if asked") { val config = TestConfig( mapOf( - LongParameterList.IGNORE_DATA_CLASSES to "true", - LongParameterList.CONSTRUCTOR_THRESHOLD to "1" + "ignoreDataClasses" to "true", + "constructorThreshold" to "1" ) ) val rule = LongParameterList(config) @@ -99,9 +99,13 @@ class LongParameterListSpec : Spek({ val config by memoized { TestConfig( mapOf( - LongParameterList.IGNORE_ANNOTATED to listOf("Generated", "kotlin.Deprecated", "kotlin.jvm.JvmName"), - LongParameterList.FUNCTION_THRESHOLD to 1, - LongParameterList.CONSTRUCTOR_THRESHOLD to 1 + "ignoreAnnotated" to listOf( + "Generated", + "kotlin.Deprecated", + "kotlin.jvm.JvmName" + ), + "functionThreshold" to 1, + "constructorThreshold" to 1 ) ) } diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/MethodOverloadingSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/MethodOverloadingSpec.kt index 9036f3952..d25c9af64 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/MethodOverloadingSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/MethodOverloadingSpec.kt @@ -1,13 +1,16 @@ package io.gitlab.arturbosch.detekt.rules.complexity +import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.compileAndLint import org.assertj.core.api.Assertions.assertThat import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe class MethodOverloadingSpec : Spek({ + val defaultThreshold = 3 + val defaultConfig by memoized { TestConfig(mapOf("threshold" to defaultThreshold)) } - val subject by memoized { MethodOverloading(threshold = 3) } + val subject by memoized { MethodOverloading(defaultConfig) } describe("MethodOverloading rule") { diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArgumentsSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArgumentsSpec.kt index 632a645ca..41247055d 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArgumentsSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NamedArgumentsSpec.kt @@ -1,6 +1,7 @@ package io.gitlab.arturbosch.detekt.rules.complexity import io.gitlab.arturbosch.detekt.rules.setupKotlinEnvironment +import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment @@ -12,11 +13,11 @@ class NamedArgumentsSpec : Spek({ val env: KotlinCoreEnvironment by memoized() val defaultThreshold = 2 - val namedArguments by memoized { NamedArguments(threshold = defaultThreshold) } + val defaultConfig by memoized { TestConfig(mapOf("threshold" to defaultThreshold)) } + val subject by memoized { NamedArguments(defaultConfig) } describe("NameArguments rule") { - val errorMessage = "Function invocation with more than $defaultThreshold parameters must all be named" it("invocation with more than 2 parameters should throw error") { val code = """ fun sum(a: Int, b:Int, c:Int) { @@ -26,9 +27,8 @@ class NamedArgumentsSpec : Spek({ sum(1, 2, 3) } """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(1) - assertThat(findings.first().message).isEqualTo(errorMessage) } it("Function invocation with more than 2 parameters should not throw error if named") { @@ -40,7 +40,7 @@ class NamedArgumentsSpec : Spek({ sum(a = 1, b = 2, c = 3) } """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(0) } @@ -53,9 +53,8 @@ class NamedArgumentsSpec : Spek({ sum(1, b = 2, c = 3) } """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(1) - assertThat(findings.first().message).isEqualTo(errorMessage) } it("invocation with less than 3 parameters should not throw error") { @@ -67,7 +66,7 @@ class NamedArgumentsSpec : Spek({ sum(1, 2) } """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(0) } @@ -80,7 +79,7 @@ class NamedArgumentsSpec : Spek({ sum(a = 1, b = 2) } """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(0) } @@ -90,9 +89,8 @@ class NamedArgumentsSpec : Spek({ val obj = C(1, 2, 3) """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(1) - assertThat(findings.first().message).isEqualTo(errorMessage) } it("constructor invocation with more than 3 named parameters should not throw error") { @@ -101,7 +99,7 @@ class NamedArgumentsSpec : Spek({ val obj = C(a = 1, b = 2, c= 3) """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(0) } @@ -111,7 +109,7 @@ class NamedArgumentsSpec : Spek({ val obj = C(1, 2) """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(0) } @@ -123,7 +121,7 @@ class NamedArgumentsSpec : Spek({ LocalDateTime.of(2020, 3, 13, 14, 0, 0) } """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(0) } @@ -136,7 +134,7 @@ class NamedArgumentsSpec : Spek({ bar(1, 2, 3, "a") } """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(0) } @@ -147,7 +145,7 @@ class NamedArgumentsSpec : Spek({ bar(1, 2, 3, *arrayOf("a")) } """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(1) } @@ -160,7 +158,7 @@ class NamedArgumentsSpec : Spek({ foo(a = 1, b = 2, c = 3, { it }) } """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(1) } @@ -172,7 +170,7 @@ class NamedArgumentsSpec : Spek({ foo(a = 1, b = 2, c = 3) { it } } """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(0) } @@ -184,7 +182,7 @@ class NamedArgumentsSpec : Spek({ foo(a = 1, b = 2, 3) { it } } """ - val findings = namedArguments.compileAndLintWithContext(env, code) + val findings = subject.compileAndLintWithContext(env, code) assertThat(findings).hasSize(1) } } diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NestedBlockDepthSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NestedBlockDepthSpec.kt index 850fe8c50..a45f494e2 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NestedBlockDepthSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/NestedBlockDepthSpec.kt @@ -2,6 +2,7 @@ package io.gitlab.arturbosch.detekt.rules.complexity import io.github.detekt.test.utils.resourceAsPath import io.gitlab.arturbosch.detekt.api.ThresholdedCodeSmell +import io.gitlab.arturbosch.detekt.test.TestConfig import io.gitlab.arturbosch.detekt.test.assertThat import io.gitlab.arturbosch.detekt.test.compileAndLint import io.gitlab.arturbosch.detekt.test.lint @@ -11,7 +12,9 @@ import org.spekframework.spek2.style.specification.describe class NestedBlockDepthSpec : Spek({ - val subject by memoized { NestedBlockDepth(threshold = 4) } + val defaultThreshold = 4 + val defaultConfig by memoized { TestConfig(mapOf("threshold" to defaultThreshold)) } + val subject by memoized { NestedBlockDepth(defaultConfig) } describe("nested classes are also considered") { it("should detect only the nested large class") { diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/StringLiteralDuplicationSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/StringLiteralDuplicationSpec.kt index 5237d595c..63d74f304 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/StringLiteralDuplicationSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/StringLiteralDuplicationSpec.kt @@ -8,6 +8,10 @@ import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe import java.util.regex.PatternSyntaxException +private const val IGNORE_ANNOTATION = "ignoreAnnotation" +private const val EXCLUDE_SHORT_STRING = "excludeStringsWithLessThan5Characters" +private const val IGNORE_STRINGS_REGEX = "ignoreStringsRegex" + class StringLiteralDuplicationSpec : Spek({ val subject by memoized { StringLiteralDuplication() } @@ -49,7 +53,7 @@ class StringLiteralDuplicationSpec : Spek({ } it("reports strings in annotations according to config") { - val config = TestConfig(mapOf(StringLiteralDuplication.IGNORE_ANNOTATION to "false")) + val config = TestConfig(mapOf(IGNORE_ANNOTATION to "false")) assertFindingWithConfig(code, config, 1) } } @@ -63,7 +67,7 @@ class StringLiteralDuplicationSpec : Spek({ } it("reports string with 4 characters") { - val config = TestConfig(mapOf(StringLiteralDuplication.EXCLUDE_SHORT_STRING to "false")) + val config = TestConfig(mapOf(EXCLUDE_SHORT_STRING to "false")) assertFindingWithConfig(code, config, 1) } } @@ -80,21 +84,21 @@ class StringLiteralDuplicationSpec : Spek({ val str1 = "lorem" + "lorem" + "lorem" val str2 = "ipsum" + "ipsum" + "ipsum" """ - val config = TestConfig(mapOf(StringLiteralDuplication.IGNORE_STRINGS_REGEX to "(lorem|ipsum)")) + val config = TestConfig(mapOf(IGNORE_STRINGS_REGEX to "(lorem|ipsum)")) assertFindingWithConfig(code, config, 0) } it("should not fail with invalid regex when disabled") { val configValues = mapOf( "active" to "false", - StringLiteralDuplication.IGNORE_STRINGS_REGEX to "*lorem" + IGNORE_STRINGS_REGEX to "*lorem" ) val config = TestConfig(configValues) assertFindingWithConfig(regexTestingCode, config, 0) } it("should fail with invalid regex") { - val config = TestConfig(mapOf(StringLiteralDuplication.IGNORE_STRINGS_REGEX to "*lorem")) + val config = TestConfig(mapOf(IGNORE_STRINGS_REGEX to "*lorem")) assertThatExceptionOfType(PatternSyntaxException::class.java).isThrownBy { StringLiteralDuplication(config).compileAndLint(regexTestingCode) } diff --git a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctionsSpec.kt b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctionsSpec.kt index fbfbcf465..b32421a0d 100644 --- a/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctionsSpec.kt +++ b/detekt-rules-complexity/src/test/kotlin/io/gitlab/arturbosch/detekt/rules/complexity/TooManyFunctionsSpec.kt @@ -6,19 +6,27 @@ import io.gitlab.arturbosch.detekt.test.compileAndLint import org.spekframework.spek2.Spek import org.spekframework.spek2.style.specification.describe -class TooManyFunctionsSpec : Spek({ +private const val THRESHOLD_IN_FILES = "thresholdInFiles" +private const val THRESHOLD_IN_CLASSES = "thresholdInClasses" +private const val THRESHOLD_IN_INTERFACES = "thresholdInInterfaces" +private const val THRESHOLD_IN_OBJECTS = "thresholdInObjects" +private const val THRESHOLD_IN_ENUMS = "thresholdInEnums" +private const val IGNORE_DEPRECATED = "ignoreDeprecated" +private const val IGNORE_PRIVATE = "ignorePrivate" +private const val IGNORE_OVERRIDDEN = "ignoreOverridden" +object TooManyFunctionsSpec : Spek({ describe("different declarations with one function as threshold") { val rule by memoized { TooManyFunctions( TestConfig( mapOf( - TooManyFunctions.THRESHOLD_IN_CLASSES to "1", - TooManyFunctions.THRESHOLD_IN_ENUMS to "1", - TooManyFunctions.THRESHOLD_IN_FILES to "1", - TooManyFunctions.THRESHOLD_IN_INTERFACES to "1", - TooManyFunctions.THRESHOLD_IN_OBJECTS to "1" + THRESHOLD_IN_CLASSES to "1", + THRESHOLD_IN_ENUMS to "1", + THRESHOLD_IN_FILES to "1", + THRESHOLD_IN_INTERFACES to "1", + THRESHOLD_IN_OBJECTS to "1" ) ) ) @@ -128,9 +136,9 @@ class TooManyFunctionsSpec : Spek({ val configuredRule = TooManyFunctions( TestConfig( mapOf( - TooManyFunctions.THRESHOLD_IN_CLASSES to "1", - TooManyFunctions.THRESHOLD_IN_FILES to "1", - TooManyFunctions.IGNORE_DEPRECATED to "true" + THRESHOLD_IN_CLASSES to "1", + THRESHOLD_IN_FILES to "1", + IGNORE_DEPRECATED to "true" ) ) ) @@ -154,9 +162,9 @@ class TooManyFunctionsSpec : Spek({ val configuredRule = TooManyFunctions( TestConfig( mapOf( - TooManyFunctions.THRESHOLD_IN_CLASSES to "1", - TooManyFunctions.THRESHOLD_IN_FILES to "1", - TooManyFunctions.IGNORE_PRIVATE to "true" + THRESHOLD_IN_CLASSES to "1", + THRESHOLD_IN_FILES to "1", + IGNORE_PRIVATE to "true" ) ) ) @@ -188,11 +196,11 @@ class TooManyFunctionsSpec : Spek({ val configuredRule = TooManyFunctions( TestConfig( mapOf( - TooManyFunctions.THRESHOLD_IN_CLASSES to "1", - TooManyFunctions.THRESHOLD_IN_FILES to "1", - TooManyFunctions.IGNORE_PRIVATE to "true", - TooManyFunctions.IGNORE_DEPRECATED to "true", - TooManyFunctions.IGNORE_OVERRIDDEN to "true" + THRESHOLD_IN_CLASSES to "1", + THRESHOLD_IN_FILES to "1", + IGNORE_PRIVATE to "true", + IGNORE_DEPRECATED to "true", + IGNORE_OVERRIDDEN to "true" ) ) ) @@ -218,9 +226,9 @@ class TooManyFunctionsSpec : Spek({ val configuredRule = TooManyFunctions( TestConfig( mapOf( - TooManyFunctions.THRESHOLD_IN_CLASSES to "1", - TooManyFunctions.THRESHOLD_IN_FILES to "1", - TooManyFunctions.IGNORE_OVERRIDDEN to "true" + THRESHOLD_IN_CLASSES to "1", + THRESHOLD_IN_FILES to "1", + IGNORE_OVERRIDDEN to "true" ) ) ) @@ -231,9 +239,9 @@ class TooManyFunctionsSpec : Spek({ val configuredRule = TooManyFunctions( TestConfig( mapOf( - TooManyFunctions.THRESHOLD_IN_CLASSES to "1", - TooManyFunctions.THRESHOLD_IN_FILES to "1", - TooManyFunctions.IGNORE_OVERRIDDEN to "false" + THRESHOLD_IN_CLASSES to "1", + THRESHOLD_IN_FILES to "1", + IGNORE_OVERRIDDEN to "false" ) ) )